diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000..c4b674eff71a6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +.java text=auto +.xml text=auto diff --git a/CODEOWNERS b/CODEOWNERS index 813d44296fc64..bc976170a2733 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -8,6 +8,7 @@ /bundles/org.openhab.binding.adorne/ @theiding /bundles/org.openhab.binding.airquality/ @kubawolanin /bundles/org.openhab.binding.airvisualnode/ @3cky +/bundles/org.openhab.binding.alarmdecoder/ @bobadair @billfor @berndpfrommer /bundles/org.openhab.binding.allplay/ @dominicdesu /bundles/org.openhab.binding.amazondashbutton/ @OLibutzki /bundles/org.openhab.binding.amazonechocontrol/ @mgeramb @@ -33,6 +34,7 @@ /bundles/org.openhab.binding.coolmasternet/ @projectgus /bundles/org.openhab.binding.coronastats/ @DerOetzi /bundles/org.openhab.binding.daikin/ @caffineehacker +/bundles/org.openhab.binding.danfossairunit/ @pravussum /bundles/org.openhab.binding.darksky/ @cweitkamp /bundles/org.openhab.binding.deconz/ @davidgraeff /bundles/org.openhab.binding.denonmarantz/ @jwveldhuis @@ -47,6 +49,8 @@ /bundles/org.openhab.binding.dwdpollenflug/ @DerOetzi /bundles/org.openhab.binding.dwdunwetter/ @limdul79 /bundles/org.openhab.binding.elerotransmitterstick/ @vbier +/bundles/org.openhab.binding.energenie/ @hmerk +/bundles/org.openhab.binding.enigma2/ @gdolfen /bundles/org.openhab.binding.enocean/ @fruggy83 /bundles/org.openhab.binding.enturno/ @klocsson /bundles/org.openhab.binding.etherrain/ @dfad1469 @@ -75,6 +79,7 @@ /bundles/org.openhab.binding.hydrawise/ @digitaldan /bundles/org.openhab.binding.hyperion/ @tavalin /bundles/org.openhab.binding.iaqualink/ @digitaldan +/bundles/org.openhab.binding.icalendar/ @daMihe /bundles/org.openhab.binding.icloud/ @pgfeller /bundles/org.openhab.binding.ihc/ @paulianttila /bundles/org.openhab.binding.innogysmarthome/ @ollie-dev @@ -139,6 +144,7 @@ /bundles/org.openhab.binding.onkyo/ @pail23 @paulianttila /bundles/org.openhab.binding.opengarage/ @psmedley /bundles/org.openhab.binding.opensprinkler/ @CrackerStealth @FlorianSW +/bundles/org.openhab.binding.openthermgateway/ @ArjenKorevaar /bundles/org.openhab.binding.openuv/ @clinique /bundles/org.openhab.binding.openweathermap/ @cweitkamp /bundles/org.openhab.binding.orvibo/ @tavalin @@ -177,6 +183,7 @@ /bundles/org.openhab.binding.snmp/ @J-N-K /bundles/org.openhab.binding.solaredge/ @alexf2015 /bundles/org.openhab.binding.solarlog/ @johannrichard +/bundles/org.openhab.binding.somfymylink/ @loungeflyz /bundles/org.openhab.binding.somfytahoma/ @octa22 /bundles/org.openhab.binding.sonos/ @kgoderis @lolodomo /bundles/org.openhab.binding.sonyaudio/ @freke diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index 3f35127fd2fd0..b120947b42edf 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bom org.openhab.addons.reactor.bom - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.addons.bom.openhab-addons @@ -29,6 +31,11 @@ org.openhab.binding.airvisualnode ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.alarmdecoder + ${project.version} + org.openhab.addons.bundles org.openhab.binding.allplay @@ -118,7 +125,7 @@ org.openhab.addons.bundles org.openhab.binding.bosesoundtouch ${project.version} - + org.openhab.addons.bundles org.openhab.binding.bsblan @@ -154,6 +161,11 @@ org.openhab.binding.daikin ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.danfossairunit + ${project.version} + org.openhab.addons.bundles org.openhab.binding.darksky @@ -224,6 +236,16 @@ org.openhab.binding.elerotransmitterstick ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.energenie + ${project.version} + + + org.openhab.addons.bundles + org.openhab.binding.enigma2 + ${project.version} + org.openhab.addons.bundles org.openhab.binding.enocean @@ -369,6 +391,11 @@ org.openhab.binding.iaqualink ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.icalendar + ${project.version} + org.openhab.addons.bundles org.openhab.binding.icloud @@ -689,6 +716,11 @@ org.openhab.binding.opensprinkler ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.openthermgateway + ${project.version} + org.openhab.addons.bundles org.openhab.binding.openuv diff --git a/bom/openhab-core-index/pom.xml b/bom/openhab-core-index/pom.xml index 1a74a24d1eaca..199d1cdcc071f 100644 --- a/bom/openhab-core-index/pom.xml +++ b/bom/openhab-core-index/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bom org.openhab.addons.reactor.bom - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.addons.bom.openhab-core-index diff --git a/bom/pom.xml b/bom/pom.xml index 9d3559e43988f..90cffc818e955 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons org.openhab.addons.reactor - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.addons.bom @@ -37,11 +39,14 @@ - + - + - + header diff --git a/bom/runtime-index/pom.xml b/bom/runtime-index/pom.xml index f3101452c8cc9..d9bef01724fba 100644 --- a/bom/runtime-index/pom.xml +++ b/bom/runtime-index/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bom org.openhab.addons.reactor.bom - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.addons.bom.runtime-index diff --git a/bom/test-index/pom.xml b/bom/test-index/pom.xml index fd60560d568a1..fffcc021d3b9b 100644 --- a/bom/test-index/pom.xml +++ b/bom/test-index/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bom org.openhab.addons.reactor.bom - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.addons.bom.test-index diff --git a/bundles/create_openhab_binding_skeleton.cmd b/bundles/create_openhab_binding_skeleton.cmd index 0e5d9b21fbf0b..effe5925acc2b 100644 --- a/bundles/create_openhab_binding_skeleton.cmd +++ b/bundles/create_openhab_binding_skeleton.cmd @@ -1,44 +1,44 @@ -@echo off - -SETLOCAL -SET ARGC=0 - -FOR %%x IN (%*) DO SET /A ARGC+=1 - -IF %ARGC% NEQ 3 ( - echo Usage: %0 BindingIdInCamelCase Author GithubUser - exit /B 1 -) - -SET OpenhabCoreVersion="2.5.0" -SET OpenhabVersion="2.5.4-SNAPSHOT" - -SET BindingIdInCamelCase=%~1 -SET BindingIdInLowerCase=%BindingIdInCamelCase% -SET Author=%~2 -SET GithubUser=%~3 - -call :LoCase BindingIdInLowerCase - -call mvn -s archetype-settings.xml archetype:generate -N -DarchetypeGroupId=org.openhab.core.tools.archetypes -DarchetypeArtifactId=org.openhab.core.tools.archetypes.binding -DarchetypeVersion=%OpenhabCoreVersion% -DgroupId=org.openhab.binding -DartifactId=org.openhab.binding.%BindingIdInLowerCase% -Dpackage=org.openhab.binding.%BindingIdInLowerCase% -Dversion=%OpenhabVersion% -DbindingId=%BindingIdInLowerCase% -DbindingIdCamelCase=%BindingIdInCamelCase% -DvendorName=openHAB -Dnamespace=org.openhab -Dauthor="%Author%" -DgithubUser="%GithubUser%" - -COPY ..\src\etc\NOTICE org.openhab.binding.%BindingIdInLowerCase%\ - -:: temporary fix -:: replace ${project.version} by ${ohc.version} in src/main/feature/feature.xml -@powershell -command "(Get-Content org.openhab.binding.$env:BindingIdInLowerCase/src/main/feature/feature.xml).replace('-core/${project.version}', '-core/${ohc.version}') | Set-Content org.openhab.binding.$env:BindingIdInLowerCase/src/main/feature/feature.xml" - -(SET BindingIdInLowerCase=) -(SET BindingIdInCamelCase=) -(SET Author=) -(SET GithubUser=) - -GOTO:EOF - -:LoCase -:: Subroutine to convert a variable VALUE to all lower case. -:: The argument for this subroutine is the variable NAME. -FOR %%i IN ("A=a" "B=b" "C=c" "D=d" "E=e" "F=f" "G=g" "H=h" "I=i" "J=j" "K=k" "L=l" "M=m" "N=n" "O=o" "P=p" "Q=q" "R=r" "S=s" "T=t" "U=u" "V=v" "W=w" "X=x" "Y=y" "Z=z") DO CALL SET "%1=%%%1:%%~i%%" -GOTO:EOF - -ENDLOCAL +@echo off + +SETLOCAL +SET ARGC=0 + +FOR %%x IN (%*) DO SET /A ARGC+=1 + +IF %ARGC% NEQ 3 ( + echo Usage: %0 BindingIdInCamelCase Author GithubUser + exit /B 1 +) + +SET OpenhabCoreVersion="2.5.0" +SET OpenhabVersion="2.5.6-SNAPSHOT" + +SET BindingIdInCamelCase=%~1 +SET BindingIdInLowerCase=%BindingIdInCamelCase% +SET Author=%~2 +SET GithubUser=%~3 + +call :LoCase BindingIdInLowerCase + +call mvn -s archetype-settings.xml archetype:generate -N -DarchetypeGroupId=org.openhab.core.tools.archetypes -DarchetypeArtifactId=org.openhab.core.tools.archetypes.binding -DarchetypeVersion=%OpenhabCoreVersion% -DgroupId=org.openhab.binding -DartifactId=org.openhab.binding.%BindingIdInLowerCase% -Dpackage=org.openhab.binding.%BindingIdInLowerCase% -Dversion=%OpenhabVersion% -DbindingId=%BindingIdInLowerCase% -DbindingIdCamelCase=%BindingIdInCamelCase% -DvendorName=openHAB -Dnamespace=org.openhab -Dauthor="%Author%" -DgithubUser="%GithubUser%" + +COPY ..\src\etc\NOTICE org.openhab.binding.%BindingIdInLowerCase%\ + +:: temporary fix +:: replace ${project.version} by ${ohc.version} in src/main/feature/feature.xml +@powershell -command "(Get-Content org.openhab.binding.$env:BindingIdInLowerCase/src/main/feature/feature.xml).replace('-core/${project.version}', '-core/${ohc.version}') | Set-Content org.openhab.binding.$env:BindingIdInLowerCase/src/main/feature/feature.xml" + +(SET BindingIdInLowerCase=) +(SET BindingIdInCamelCase=) +(SET Author=) +(SET GithubUser=) + +GOTO:EOF + +:LoCase +:: Subroutine to convert a variable VALUE to all lower case. +:: The argument for this subroutine is the variable NAME. +FOR %%i IN ("A=a" "B=b" "C=c" "D=d" "E=e" "F=f" "G=g" "H=h" "I=i" "J=j" "K=k" "L=l" "M=m" "N=n" "O=o" "P=p" "Q=q" "R=r" "S=s" "T=t" "U=u" "V=v" "W=w" "X=x" "Y=y" "Z=z") DO CALL SET "%1=%%%1:%%~i%%" +GOTO:EOF + +ENDLOCAL diff --git a/bundles/create_openhab_binding_skeleton.sh b/bundles/create_openhab_binding_skeleton.sh index e5db32ff33b50..7d50b2af2b804 100755 --- a/bundles/create_openhab_binding_skeleton.sh +++ b/bundles/create_openhab_binding_skeleton.sh @@ -3,7 +3,7 @@ [ $# -lt 3 ] && { echo "Usage: $0 "; exit 1; } openHABCoreVersion=2.5.0 -openHABVersion=2.5.4-SNAPSHOT +openHABVersion=2.5.6-SNAPSHOT camelcaseId=$1 id=`echo $camelcaseId | tr '[:upper:]' '[:lower:]'` diff --git a/bundles/org.openhab.binding.adorne/pom.xml b/bundles/org.openhab.binding.adorne/pom.xml index c30d3bfb3f206..2e17c19fa26b3 100644 --- a/bundles/org.openhab.binding.adorne/pom.xml +++ b/bundles/org.openhab.binding.adorne/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.adorne diff --git a/bundles/org.openhab.binding.adorne/src/main/java/org/openhab/binding/adorne/internal/handler/AdorneDimmerHandler.java b/bundles/org.openhab.binding.adorne/src/main/java/org/openhab/binding/adorne/internal/handler/AdorneDimmerHandler.java index 187453d0c2f47..ce5b0506fabbb 100644 --- a/bundles/org.openhab.binding.adorne/src/main/java/org/openhab/binding/adorne/internal/handler/AdorneDimmerHandler.java +++ b/bundles/org.openhab.binding.adorne/src/main/java/org/openhab/binding/adorne/internal/handler/AdorneDimmerHandler.java @@ -95,5 +95,4 @@ public void refresh() { super.refresh(); refreshBrightness(); } - } diff --git a/bundles/org.openhab.binding.adorne/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.adorne/src/main/resources/ESH-INF/thing/thing-types.xml index 417a8cda5d012..02f299343d151 100644 --- a/bundles/org.openhab.binding.adorne/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.adorne/src/main/resources/ESH-INF/thing/thing-types.xml @@ -6,14 +6,14 @@ - + Controls an Adorne switch or outlet. - + @@ -25,15 +25,15 @@ - + Controls an Adorne dimmer switch. - - + + diff --git a/bundles/org.openhab.binding.airquality/pom.xml b/bundles/org.openhab.binding.airquality/pom.xml index 44da3ac2600ff..13458aa7f9026 100644 --- a/bundles/org.openhab.binding.airquality/pom.xml +++ b/bundles/org.openhab.binding.airquality/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.airquality diff --git a/bundles/org.openhab.binding.airquality/src/main/feature/feature.xml b/bundles/org.openhab.binding.airquality/src/main/feature/feature.xml index 6e9f744f2a713..24cc88f1acbd7 100644 --- a/bundles/org.openhab.binding.airquality/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.airquality/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.airquality/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.airquality/${project.version} + diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityBindingConstants.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityBindingConstants.java index 65bb101bf3aa8..d9636bbea9c57 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityBindingConstants.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityBindingConstants.java @@ -72,5 +72,4 @@ public class AirQualityBindingConstants { public static final Unit API_TEMPERATURE_UNIT = SIUnits.CELSIUS; public static final Unit API_HUMIDITY_UNIT = SmartHomeUnits.PERCENT; public static final Unit API_PRESSURE_UNIT = HECTO(SIUnits.PASCAL); - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityConfiguration.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityConfiguration.java index 7bb3253d21042..67eeca388490f 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityConfiguration.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityConfiguration.java @@ -26,5 +26,4 @@ public class AirQualityConfiguration { public String location; public Integer stationId; public Integer refresh; - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityHandlerFactory.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityHandlerFactory.java index d7e4ec691a23d..88df58ebc64e4 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityHandlerFactory.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/AirQualityHandlerFactory.java @@ -51,5 +51,4 @@ protected ThingHandler createHandler(Thing thing) { return null; } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/discovery/AirQualityDiscoveryService.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/discovery/AirQualityDiscoveryService.java index 6f603d8d4697f..de0a1418c64bd 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/discovery/AirQualityDiscoveryService.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/discovery/AirQualityDiscoveryService.java @@ -125,5 +125,4 @@ protected void setLocationProvider(LocationProvider locationProvider) { protected void unsetLocationProvider(LocationProvider locationProvider) { this.locationProvider = null; } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/handler/AirQualityHandler.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/handler/AirQualityHandler.java index 10af8f9eabd97..109635f64e643 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/handler/AirQualityHandler.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/handler/AirQualityHandler.java @@ -318,5 +318,4 @@ public static Object getValue(String channelId, AirQualityJsonResponse data) thr return null; } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonCity.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonCity.java index ec595de9212f8..0b04d9da20190 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonCity.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonCity.java @@ -45,5 +45,4 @@ public String getGeo() { } return String.join(",", list); } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonData.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonData.java index ef4ff8e22fd90..300d4c7c46350 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonData.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonData.java @@ -130,5 +130,4 @@ public String getAqiDescription() { public String getDominentPol() { return dominentpol; } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonIaqi.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonIaqi.java index b2f8b550975b5..21bb21efe7477 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonIaqi.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonIaqi.java @@ -84,5 +84,4 @@ public BigDecimal getH() { public BigDecimal getW() { return wind.getValue(); } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonResponse.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonResponse.java index cf85c87ed7263..4a4bc0f4b346c 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonResponse.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonResponse.java @@ -34,5 +34,4 @@ public String getStatus() { public AirQualityJsonData getData() { return data; } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonTime.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonTime.java index c7a008ef419c1..9624f504f793d 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonTime.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/AirQualityJsonTime.java @@ -42,5 +42,4 @@ public ZonedDateTime getObservationTime() throws Exception { ZonedDateTime observationTime = ZonedDateTime.parse(fullString); return observationTime; } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/Attribute.java b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/Attribute.java index d1b358d8ea0c4..bc1b4f25f7291 100644 --- a/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/Attribute.java +++ b/bundles/org.openhab.binding.airquality/src/main/java/org/openhab/binding/airquality/internal/json/Attribute.java @@ -28,5 +28,4 @@ public String getName() { public void setName(String name) { this.name = name; } - } diff --git a/bundles/org.openhab.binding.airquality/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.airquality/src/main/resources/ESH-INF/binding/binding.xml index 4c752d959df99..676f6db35c6ff 100644 --- a/bundles/org.openhab.binding.airquality/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.airquality/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Air Quality Binding Measure Air Quality Index and details about pollution particles for a given location diff --git a/bundles/org.openhab.binding.airquality/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.airquality/src/main/resources/ESH-INF/thing/thing-types.xml index e687504542d88..f382283411ce3 100644 --- a/bundles/org.openhab.binding.airquality/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.airquality/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -7,27 +8,29 @@ - Provides various air quality data from the World Air Quality Project. - In order to receive the data, you must register an account on http://aqicn.org/data-platform/token/ and get your API token. + Provides various air quality data from the World Air Quality Project. + In order to receive the data, you + must register an account on http://aqicn.org/data-platform/token/ and get your API + token. - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -130,7 +133,7 @@ Location of the measuring station Station Location - + @@ -170,9 +173,9 @@ Current humidity Humidity - + - + String @@ -180,4 +183,3 @@ - diff --git a/bundles/org.openhab.binding.airvisualnode/pom.xml b/bundles/org.openhab.binding.airvisualnode/pom.xml index e60c73277e9fc..0161b95ec84d9 100644 --- a/bundles/org.openhab.binding.airvisualnode/pom.xml +++ b/bundles/org.openhab.binding.airvisualnode/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.airvisualnode diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/feature/feature.xml b/bundles/org.openhab.binding.airvisualnode/src/main/feature/feature.xml index 36da7d2e34811..66adc39bd0085 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.airvisualnode/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.samba.jcifs/jcifs/1.3.17 - mvn:org.openhab.addons.bundles/org.openhab.binding.airvisualnode/${project.version} - + + openhab-runtime-base + mvn:org.samba.jcifs/jcifs/1.3.17 + mvn:org.openhab.addons.bundles/org.openhab.binding.airvisualnode/${project.version} + diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/AirVisualNodeBindingConstants.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/AirVisualNodeBindingConstants.java index 9d6a4f13a05e8..80be5560c0d40 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/AirVisualNodeBindingConstants.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/AirVisualNodeBindingConstants.java @@ -53,8 +53,7 @@ public class AirVisualNodeBindingConstants { .unmodifiableSet(new HashSet<>(Arrays.asList(THING_TYPE_AVNODE))); // List of all supported Channel ids - public static final Set SUPPORTED_CHANNEL_IDS = Collections - .unmodifiableSet(new HashSet<>(Arrays.asList(CHANNEL_CO2, CHANNEL_HUMIDITY, CHANNEL_AQI_US, - CHANNEL_PM_25, CHANNEL_TEMP_CELSIUS, CHANNEL_BATTERY_LEVEL, - CHANNEL_WIFI_STRENGTH, CHANNEL_TIMESTAMP, CHANNEL_USED_MEMORY))); + public static final Set SUPPORTED_CHANNEL_IDS = Collections.unmodifiableSet(new HashSet<>( + Arrays.asList(CHANNEL_CO2, CHANNEL_HUMIDITY, CHANNEL_AQI_US, CHANNEL_PM_25, CHANNEL_TEMP_CELSIUS, + CHANNEL_BATTERY_LEVEL, CHANNEL_WIFI_STRENGTH, CHANNEL_TIMESTAMP, CHANNEL_USED_MEMORY))); } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/discovery/AirVisualNodeDiscoveryService.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/discovery/AirVisualNodeDiscoveryService.java index 0a2aa98653070..6e68cfb620660 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/discovery/AirVisualNodeDiscoveryService.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/discovery/AirVisualNodeDiscoveryService.java @@ -129,5 +129,4 @@ private void scan() { } } } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/handler/AirVisualNodeHandler.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/handler/AirVisualNodeHandler.java index b99a34f33c639..c1e2d6aee3952 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/handler/AirVisualNodeHandler.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/handler/AirVisualNodeHandler.java @@ -12,6 +12,15 @@ */ package org.openhab.binding.airvisualnode.internal.handler; +import static org.eclipse.smarthome.core.library.unit.MetricPrefix.MICRO; +import static org.eclipse.smarthome.core.library.unit.SIUnits.CELSIUS; +import static org.eclipse.smarthome.core.library.unit.SIUnits.CUBIC_METRE; +import static org.eclipse.smarthome.core.library.unit.SIUnits.GRAM; +import static org.eclipse.smarthome.core.library.unit.SmartHomeUnits.ONE; +import static org.eclipse.smarthome.core.library.unit.SmartHomeUnits.PARTS_PER_MILLION; +import static org.eclipse.smarthome.core.library.unit.SmartHomeUnits.PERCENT; +import static org.openhab.binding.airvisualnode.internal.AirVisualNodeBindingConstants.*; + import java.io.IOException; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; @@ -27,14 +36,6 @@ import org.eclipse.smarthome.core.library.types.DateTimeType; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.QuantityType; -import static org.eclipse.smarthome.core.library.unit.SIUnits.CELSIUS; -import static org.eclipse.smarthome.core.library.unit.SIUnits.GRAM; -import static org.eclipse.smarthome.core.library.unit.SIUnits.CUBIC_METRE; -import static org.eclipse.smarthome.core.library.unit.SmartHomeUnits.ONE; -import static org.eclipse.smarthome.core.library.unit.SmartHomeUnits.PERCENT; -import static org.openhab.binding.airvisualnode.internal.AirVisualNodeBindingConstants.*; -import static org.eclipse.smarthome.core.library.unit.SmartHomeUnits.PARTS_PER_MILLION; -import static org.eclipse.smarthome.core.library.unit.MetricPrefix.MICRO; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; @@ -196,7 +197,8 @@ private State getChannelState(String channelId, NodeData nodeData) { if (CHANNEL_BATTERY_LEVEL.equals(channelId)) { state = new DecimalType(BigDecimal.valueOf(nodeData.getStatus().getBattery()).longValue()); } else if (CHANNEL_WIFI_STRENGTH.equals(channelId)) { - state = new DecimalType(BigDecimal.valueOf(Math.max(0, nodeData.getStatus().getWifiStrength()-1)).longValue()); + state = new DecimalType( + BigDecimal.valueOf(Math.max(0, nodeData.getStatus().getWifiStrength() - 1)).longValue()); } else { // Handle binding-specific channel IDs switch (channelId) { @@ -211,7 +213,8 @@ private State getChannelState(String channelId, NodeData nodeData) { break; case CHANNEL_PM_25: // PM2.5 is in ug/m3 - state = new QuantityType<>(nodeData.getMeasurements().getPm25Ugm3(), MICRO(GRAM).divide(CUBIC_METRE)); + state = new QuantityType<>(nodeData.getMeasurements().getPm25Ugm3(), + MICRO(GRAM).divide(CUBIC_METRE)); break; case CHANNEL_TEMP_CELSIUS: state = new QuantityType<>(nodeData.getMeasurements().getTemperatureC(), CELSIUS); @@ -237,5 +240,4 @@ private State getChannelState(String channelId, NodeData nodeData) { return state; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/DateAndTime.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/DateAndTime.java index f8e58b2b64323..cd9bdbfd544d4 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/DateAndTime.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/DateAndTime.java @@ -52,5 +52,4 @@ public String getTimestamp() { public void setTimestamp(String timestamp) { this.timestamp = timestamp; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Measurements.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Measurements.java index 8d0a9bd93000d..62418e13d9c00 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Measurements.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Measurements.java @@ -35,8 +35,8 @@ public class Measurements { private float temperatureF; private int vocPpb; - public Measurements(int co2Ppm, int humidityRH, int pm25AQICN, int pm25AQIUS, float pm25Ugm3, - float temperatureC, float temperatureF, int vocPpb) { + public Measurements(int co2Ppm, int humidityRH, int pm25AQICN, int pm25AQIUS, float pm25Ugm3, float temperatureC, + float temperatureF, int vocPpb) { this.co2Ppm = co2Ppm; this.humidityRH = humidityRH; this.pm25AQICN = pm25AQICN; @@ -110,5 +110,4 @@ public int getVocPpb() { public void setVocPpb(int vocPpb) { this.vocPpb = vocPpb; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/NodeData.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/NodeData.java index be3aa436a129e..31175e5a60d7b 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/NodeData.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/NodeData.java @@ -73,5 +73,4 @@ public Status getStatus() { public void setStatus(Status status) { this.status = status; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSaving.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSaving.java index ed201f3b34e86..5a9dd81b89cfd 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSaving.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSaving.java @@ -13,6 +13,7 @@ package org.openhab.binding.airvisualnode.internal.json; import java.util.List; + import com.google.gson.annotations.SerializedName; /** @@ -57,5 +58,4 @@ public String getMode() { public void setMode(String mode) { this.mode = mode; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSavingTime.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSavingTime.java index 9871d0a02be1f..bee3ff3ee97e6 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSavingTime.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSavingTime.java @@ -42,5 +42,4 @@ public int getMinute() { public void setMinute(int minute) { this.minute = minute; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSavingTimeSlot.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSavingTimeSlot.java index 3b3ac553a1b4a..97701c2ea269c 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSavingTimeSlot.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/PowerSavingTimeSlot.java @@ -42,5 +42,4 @@ public int getHourOn() { public void setHourOn(int hourOn) { this.hourOn = hourOn; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Settings.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Settings.java index 45643d3e6afec..b8294b1a5936d 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Settings.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Settings.java @@ -154,5 +154,4 @@ public String getTimezone() { public void setTimezone(String timezone) { this.timezone = timezone; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Status.java b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Status.java index 1f53ac377ca8f..f48c6e2dadd92 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Status.java +++ b/bundles/org.openhab.binding.airvisualnode/src/main/java/org/openhab/binding/airvisualnode/internal/json/Status.java @@ -113,5 +113,4 @@ public int getWifiStrength() { public void setWifiStrength(int wifiStrength) { this.wifiStrength = wifiStrength; } - } diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.airvisualnode/src/main/resources/ESH-INF/binding/binding.xml index e07a27374a3a6..9ff5fb3d00c75 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.airvisualnode/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - AirVisual Node Binding diff --git a/bundles/org.openhab.binding.airvisualnode/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.airvisualnode/src/main/resources/ESH-INF/thing/thing-types.xml index d017f5b8c86d1..7fc108b8f807d 100644 --- a/bundles/org.openhab.binding.airvisualnode/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.airvisualnode/src/main/resources/ESH-INF/thing/thing-types.xml @@ -11,15 +11,15 @@ - - - - - - - - - + + + + + + + + + @@ -65,7 +65,7 @@ CO₂ level, ppm CarbonDioxide - + @@ -73,21 +73,21 @@ Humidity, % Humidity - + Number:Dimensionless Air Quality Index (US) - + Number:Density PM2.5 level, µg/m³ - + @@ -95,21 +95,21 @@ Current temperature Temperature - + DateTime Status timestamp - + Number Used memory - + diff --git a/bundles/org.openhab.binding.alarmdecoder/.classpath b/bundles/org.openhab.binding.alarmdecoder/.classpath new file mode 100644 index 0000000000000..a5d95095ccaaf --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.alarmdecoder/.project b/bundles/org.openhab.binding.alarmdecoder/.project new file mode 100644 index 0000000000000..f5fdcb71122ad --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/.project @@ -0,0 +1,23 @@ + + + org.openhab.binding.alarmdecoder + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.alarmdecoder/NOTICE b/bundles/org.openhab.binding.alarmdecoder/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.alarmdecoder/README.md b/bundles/org.openhab.binding.alarmdecoder/README.md new file mode 100644 index 0000000000000..f976837efbe50 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/README.md @@ -0,0 +1,269 @@ +# Alarm Decoder Binding + +The [Alarm Decoder](http://www.alarmdecoder.com) from Nu Tech Software Solutions is a hardware adapter that interfaces with Ademco/Honeywell and DSC alarm panels. +It acts essentially like a keypad, reading and writing messages on the serial bus that connects keypads with the main panel. + +There are several versions of the adapter available: + +* *AD2PI* or *AD2PHAT* - A board that plugs into a Raspberry Pi and offers network-based TCP connectivity +* *AD2SERIAL* - Attaches to a host via a serial port +* *AD2USB* - Attaches to a host via USB + +This binding allows openHAB to access the state of wired or wireless contacts and motion detectors connected to supported alarm panels, as well as the state of attached keypads and the messages send to attached LRR devices. +Support is also available for sending keypad commands, including special/programmable keys supported by your panel. + +For those upgrading from the OH1 version of the binding, the [original OH1 README](https://www.openhab.org/v2.5/addons/bindings/alarmdecoder1/) file is available for reference. + +## Supported Things + +The binding supports the following thing types: + +* `ipbridge` - Supports TCP connection to the AD. +* `serialbridge` - Supports serial/USB connection to the AD. +* `keypad` - Reports keypad status and optionally sends keypad messages. +* `zone` - Reports status from zone expanders and relay expanders, and also from built-in zones via emulation. +* `rfzone` - Reports status from RF zones. +* `lrr` - Reports messages sent from the panel to a Long Range Radio (LRR) or emulated LRR device. + +## Discovery + +Background discovery is currently supported for `zone` and `rfzone` things. +If the bridge `discovery` parameter is set to *true*, the first time a status message is seen from each zone or RF zone a corresponding thing will appear in the inbox. +Leaving the `discovery` parameter set to *false* during normal operation is recommended, as it will slightly reduce resource consumption by the binding. + +## Prerequisites + +The process for wiring the Alarm Decoder into the alarm panel and configuring it is described in the Alarm Decoder Quick Start guide for your model. +Before working on the main panel, it is advisable to put the alarm system in test mode, and un-plug the phone connection to it for good measure. +Don't forget to plug it back in when you are finished! + +Understanding exactly what expansion boards are connected to the main panel is crucial for a successful setup of the AlarmDecoder and also helpful in interpreting the messages from the alarmdecoder. +While many of the expansion devices don't have labels on the outside, inserting a flat screwdriver into the right slot and prying gently will usually uncover a circuit board with numbers on it that can be web searched. + +Although not mentioned in the Quick Start guide, configuring virtual relay boards is absolutely necessary on panels like the Honeywell Vista 20p and similar, or else all of the eight on-board zones will not be visible! + +## Thing Configuration + +Alarm Decoder things can be configured through openHAB's management UI, or manually via configuration files. +When first configuring the binding it is probably easiest to configure it via the management UI, even if you plan to use configuration files later. +If you enable the *discovery* option on the bridge, as you fault zones (e.g. open doors and windows, trigger motion detectors, etc.) they should appear in the discovery inbox. + +### ipbridge + +The `ipbridge` thing supports a TCP/IP connection to an Alarm Decoder device such as *AD2PI* or *AD2PHAT*. + +* `hostname` (required) The hostname or IP address of the Alarm Decoder device +* `tcpPort` (default = 10000) TCP port number for the Alarm Decoder connection +* `discovery` (default = false) Enable automatic discovery of zones and RF zones +* `reconnect` (1-60, default = 2) The period in minutes that the handler will wait between connection checks and connection attempts +* `timeout` (0-60, default = 5) The period in minutes after which the connection will be reset if no valid messages have been received. Set to 0 to disable. + +Thing config file example: + +``` +Bridge alarmdecoder:ipbridge:ad1 [ hostname="cerberus.home", tcpPort=10000, discovery=true ] { + Thing ... + Thing ... +} +``` + +### serialbridge + +The `serialbridge` thing supports a serial or USB connection to an Alarm Decoder device such as *AD2SERIAL* or *AD2USB*. + +Parameters: + +* `serialPort` (required) The name of the serial port used to connect to the Alarm Decoder device +* `bitrate` Speed of the serial connection +* `discovery` (default=false) Enable automatic discovery of zones and RF zones + +Thing config file example: + +``` +Bridge alarmdecoder:serialbridge:ad1 [ serialPort="/dev/ttyS1", bitrate=115200, discovery=true ] { + Thing ... + Thing ... +} +``` + +### zone + +The `zone` thing reports status from zone expanders and relay expanders, and also from built-in zones via emulation. + +Parameters: + +* `address` (required) Zone address +* `channel` (required) Zone channel + +Thing config file example: + +``` + Thing zone frontdoor [ address=10, channel=1 ] +``` + +### rfzone + +The `rfzone` thing reports status from wireless zones, such as 5800 series RF devices, if your alarm panel has an RF receiver. + +Parameters: + +* `serial` (required) Serial number of the RF zone + +Thing config file example: + +``` + Thing rfzone motion1 [ serial=0180010 ] +``` + +### keypad + +The `keypad` thing reports keypad status and optionally sends keypad messages. +For panels that support multiple keypad addresses, it can be configured with an address mask of one or more keypad(s) for which it will receive messages. +When sending messages, it will send from the configured keypad address if only one is configured. +If a mask containing multiple addresses or 0 (all) is configured, it will send messages from the Alarm Decoder's configured address. + +Commands sent from the keypad thing are limited to the set of valid keypad command characters supported by the Alarm Decoder (0-9,*,#,<,>). +In addition, the characters A-H will be translated to special keys 1-8. +Command strings containing invalid characters will be ignored. + +Parameters: + +* `addressMask` (required) Keypad address mask (0 = All addresses) +* `sendCommands` (default = false) Allow keypad commands to be sent to the alarm system from openHAB. Enabling this means the alarm system will be only as secure as your openHAB system. +* `sendStar` (default = false) When disarmed/faulted, automatically send the * character to obtain zone fault information. +* `commandMapping` (optional) Comma separated list of key/value pairs mapping integers to command strings for `intcommand` channel. + +Thing config file example: + +``` + Thing keypad keypad1 [ addressMask=0, sendCommands=true ] +``` + +### lrr + +The `lrr` thing reports messages sent to a Long Range Radio (LRR) or emulated LRR device. +These are normally specifically formatted messages as described in the [SIA DC-05-1999.09](http://www.alarmdecoder.com/wiki/index.php/File:SIA-ContactIDCodes_Protocol.pdf) standard for Contact ID reporting. +They can also, depending on configuration, be other types of messages as described [here](http://www.alarmdecoder.com/wiki/index.php/LRR_Support). +For panels that support multiple partitions, the partition for which a given lrr thing will receive messages can be defined. + +* `partition` (default = 0) Partition for which to receive LRR events (0 = All) + +Thing config file example: + +``` + Thing lrr lrr [ partition=0 ] +``` + +## Channels + +The alarmdecoder things expose the following channels: + +**zone** + +| channel | type |RO/RW| description | +|--------------|---------|-----|------------------------------| +| contact | Contact |RO |Zone contact state | + +**rfzone** + +| channel | type |RO/RW| description | +|--------------|---------|-----|------------------------------| +| lowbat | Switch | RO |Low battery | +| supervision | Switch | RO |Supervision warning | +| loop1 | Contact | RO |Loop 1 state | +| loop2 | Contact | RO |Loop 2 state | +| loop3 | Contact | RO |Loop 3 state | +| loop4 | Contact | RO |Loop 4 state | + +**keypad** + +| channel | type |RO/RW| description | +|--------------|---------|-----|------------------------------| +| zone | Number | RO |Zone number for status | +| text | String | RO |Keypad message text | +| ready | Switch | RO |Panel ready | +| armedaway | Switch | RO |Armed/Away Indicator | +| armedhome | Switch | RO |Armed/Stay Indicator | +| backlight | Switch | RO |Keypad backlight on | +| program | Switch | RO |Programming mode | +| beeps | Number | RO |Number of beeps for message | +| bypassed | Switch | RO |Zone bypassed | +| acpower | Switch | RO |Panel on AC power | +| chime | Switch | RO |Chime enabled | +| alarmoccurred| Switch | RO |Alarm occurred in the past | +| alarm | Switch | RO |Alarm is currently sounding | +| lowbat | Switch | RO |Low battery warning | +| delayoff | Switch | RO |Entry delay off | +| fire | Switch | RO |Fire detected | +| sysfault | Switch | RO |System fault | +| perimeter | Switch | RO |Perimeter only | +| command | String | RW |Keypad command | +| intcommand | Number | RW |Integer keypad command | + +*Note* - The `intcommand` channel is provided for backward compatibility with the OH1 version of the binding. +The integer to command string mappings are provided by the optional keypad `commandMapping` parameter. +The default mapping is "0=0,1=1,2=2,3=3,4=4,5=5,6=6,7=7,8=8,9=9,10=*,11=#". + +**lrr** + +| channel | type |RO/RW| description | +|--------------|---------|-----|------------------------------| +| partition | Number | RO |Partition number (0=system) | +| eventdata | Number | RO |CID event data (user or zone) | +| cidmessage | String | RO |SIA Contact ID Protocol msg. | +| reportcode | String | RO |CID report code | + +## Full Example + +Example ad.things file: + +``` +Bridge alarmdecoder:ipbridge:ad1 [ hostname="cerberus.home", tcpPort=10000, discovery=true ] { + Thing zone frontdoor [ address=10, channel=1 ] + Thing zone backdoor [ address=11, channel=1 ] + Thing rfzone motion1 [ serial=0180010 ] + Thing keypad keypad1 [ addressMask=0, sendCommands=true ] + Thing lrr lrr [ partition=0 ] +} +``` + +Example ad.items file: + +``` +Number KeypadZone "Zone [%d]" {channel="alarmdecoder:keypad:ad1:keypad1:zone"} +String KeypadText "Message" {channel="alarmdecoder:keypad:ad1:keypad1:text"} +Switch KeypadArmedAway "Armed Away" {channel="alarmdecoder:keypad:ad1:keypad1:armedaway"} +Switch KeypadArmedHome "Armed Home" {channel="alarmdecoder:keypad:ad1:keypad1:armedhome"} +Switch KeypadAlarm "Alarm" {channel="alarmdecoder:keypad:ad1:keypad1:alarm"} +Switch KeypadFire "Fire" {channel="alarmdecoder:keypad:ad1:keypad1:fire"} +String KeypadCmd "Command" {channel="alarmdecoder:keypad:ad1:keypad1:command"} + +Contact FrontDoorContact "Front Door Zone" {channel="alarmdecoder:zone:ad1:frontdoor:contact"} + +Switch Motion1Lowbat "Low Battery" {channel="alarmdecoder:rfzone:ad1:motion1:lowbat"} +Switch Motion1Supervision "Supervision Warning" {channel="alarmdecoder:rfzone:ad1:motion1:supervision"} +Contact Motion1Loop1 "Loop 1" {channel="alarmdecoder:rfzone:ad1:motion1:loop1"} +Contact Motion1Loop2 "Loop 2" {channel="alarmdecoder:rfzone:ad1:motion1:loop2"} +Contact Motion1Loop3 "Loop 3" {channel="alarmdecoder:rfzone:ad1:motion1:loop3"} +Contact Motion1Loop4 "Loop 4" {channel="alarmdecoder:rfzone:ad1:motion1:loop4"} + +Number LrrPartition "Partition Number [%d]" {channel="alarmdecoder:lrr:ad1:lrr:partition"} +Number LrrEventData "CID Event Data [%d]" {channel="alarmdecoder:lrr:ad1:lrr:eventdata"} +String LrrMessage "CID Message" {channel="alarmdecoder:lrr:ad1:lrr:cidmessage"} +String LrrReportCode "CID Report Code" {channel="alarmdecoder:lrr:ad1:lrr:reportcode"} +``` + +*Note: For brevity, not every possible keypad channel is linked to an item in the above example.* + +## Thing Actions + +The `ipbridge` and `serialbridge` things expose the following action to the automation engine: + +*reboot* - Send command to reboot the Alarm Decoder device. Accepts no parameters. + +## Quirks + +The alarmdecoder device cannot query the panel for the state of individual zones. +For this reason, the binding puts contacts into the "unknown" state (UNDEF), *until the panel goes into the READY state*. +At that point, all contacts for which no update messages have arrived are presumed to be in the CLOSED state. +In other words: to get to a clean slate after an openHAB restart, close all doors/windows such that the panel is READY. diff --git a/bundles/org.openhab.binding.alarmdecoder/pom.xml b/bundles/org.openhab.binding.alarmdecoder/pom.xml new file mode 100644 index 0000000000000..32bf1481ecaf0 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + + + org.openhab.binding.alarmdecoder + + openHAB Add-ons :: Bundles :: Alarm Decoder Binding + + diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/feature/feature.xml b/bundles/org.openhab.binding.alarmdecoder/src/main/feature/feature.xml new file mode 100644 index 0000000000000..5fe49cd0078f3 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/feature/feature.xml @@ -0,0 +1,10 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.alarmdecoder/${project.version} + + diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderBindingConstants.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderBindingConstants.java new file mode 100644 index 0000000000000..f5b52d3707738 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderBindingConstants.java @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link AlarmDecoderBindingConstants} class defines common constants, which are + * used throughout the binding. + * + * @author Bob Adair - Initial contribution + * @author Bill Forsyth - Initial contribution + */ +@NonNullByDefault +public class AlarmDecoderBindingConstants { + + private static final String BINDING_ID = "alarmdecoder"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_IPBRIDGE = new ThingTypeUID(BINDING_ID, "ipbridge"); + public static final ThingTypeUID THING_TYPE_SERIALBRIDGE = new ThingTypeUID(BINDING_ID, "serialbridge"); + public static final ThingTypeUID THING_TYPE_ZONE = new ThingTypeUID(BINDING_ID, "zone"); + public static final ThingTypeUID THING_TYPE_RFZONE = new ThingTypeUID(BINDING_ID, "rfzone"); + public static final ThingTypeUID THING_TYPE_KEYPAD = new ThingTypeUID(BINDING_ID, "keypad"); + public static final ThingTypeUID THING_TYPE_LRR = new ThingTypeUID(BINDING_ID, "lrr"); + + public static final Set DISCOVERABLE_DEVICE_TYPE_UIDS = Collections.unmodifiableSet(Stream + .of(THING_TYPE_ZONE, THING_TYPE_RFZONE, THING_TYPE_KEYPAD, THING_TYPE_LRR).collect(Collectors.toSet())); + + // Bridge properties + public static final String PROPERTY_SERIALNUM = "serialNumber"; + public static final String PROPERTY_VERSION = "firmwareVersion"; + public static final String PROPERTY_CAPABILITIES = "capabilities"; + + // Channel IDs for ZoneHandler + public static final String PROPERTY_ADDRESS = "address"; + public static final String PROPERTY_CHANNEL = "channel"; + public static final String PROPERTY_ID = "id"; + + public static final String CHANNEL_CONTACT = "contact"; + + // Channel IDs for RFZoneHandler + public static final String PROPERTY_SERIAL = "serial"; + + public static final String CHANNEL_RF_LOWBAT = "lowbat"; + public static final String CHANNEL_RF_SUPERVISION = "supervision"; + public static final String CHANNEL_RF_LOOP1 = "loop1"; + public static final String CHANNEL_RF_LOOP2 = "loop2"; + public static final String CHANNEL_RF_LOOP3 = "loop3"; + public static final String CHANNEL_RF_LOOP4 = "loop4"; + + // Channel IDs for KeypadHandler + public static final String CHANNEL_KP_ZONE = "zone"; + public static final String CHANNEL_KP_TEXT = "text"; + public static final String CHANNEL_KP_READY = "ready"; + public static final String CHANNEL_KP_ARMEDAWAY = "armedaway"; + public static final String CHANNEL_KP_ARMEDHOME = "armedhome"; + public static final String CHANNEL_KP_BACKLIGHT = "backlight"; + public static final String CHANNEL_KP_PRORGAM = "program"; + public static final String CHANNEL_KP_BEEPS = "beeps"; + public static final String CHANNEL_KP_BYPASSED = "bypassed"; + public static final String CHANNEL_KP_ACPOWER = "acpower"; + public static final String CHANNEL_KP_CHIME = "chime"; + public static final String CHANNEL_KP_ALARMOCCURRED = "alarmoccurred"; + public static final String CHANNEL_KP_ALARM = "alarm"; + public static final String CHANNEL_KP_LOWBAT = "lowbat"; + public static final String CHANNEL_KP_DELAYOFF = "delayoff"; + public static final String CHANNEL_KP_FIRE = "fire"; + public static final String CHANNEL_KP_SYSFAULT = "sysfault"; + public static final String CHANNEL_KP_PERIMETER = "perimeter"; + public static final String CHANNEL_KP_COMMAND = "command"; + public static final String CHANNEL_KP_INTCOMMAND = "intcommand"; + public static final String DEFAULT_MAPPING = "0=0,1=1,2=2,3=3,4=4,5=5,6=6,7=7,8=8,9=9,10=*,11=#"; + + // Channel IDs for LRRHandler + public static final String CHANNEL_LRR_PARTITION = "partition"; + public static final String CHANNEL_LRR_EVENTDATA = "eventdata"; + public static final String CHANNEL_LRR_CIDMESSAGE = "cidmessage"; + public static final String CHANNEL_LRR_REPORTCODE = "reportcode"; +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderDiscoveryService.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderDiscoveryService.java new file mode 100644 index 0000000000000..c2eebac3dc303 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderDiscoveryService.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal; + +import static org.openhab.binding.alarmdecoder.internal.AlarmDecoderBindingConstants.*; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.alarmdecoder.internal.handler.ADBridgeHandler; +import org.openhab.binding.alarmdecoder.internal.handler.ZoneHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link AlarmDecoderDiscoveryService} handles discovery of devices as they are identified by the bridge handler. + * Requests from the framework to startScan() are ignored, since no active scanning is possible. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class AlarmDecoderDiscoveryService extends AbstractDiscoveryService { + + private final Logger logger = LoggerFactory.getLogger(AlarmDecoderDiscoveryService.class); + + private ADBridgeHandler bridgeHandler; + private final Set discoveredZoneSet = new HashSet<>(); + private final Set discoveredRFZoneSet = new HashSet<>(); + + public AlarmDecoderDiscoveryService(ADBridgeHandler bridgeHandler) throws IllegalArgumentException { + super(DISCOVERABLE_DEVICE_TYPE_UIDS, 0, false); + this.bridgeHandler = bridgeHandler; + } + + @Override + protected void startScan() { + // Ignore start scan requests + } + + public void processZone(int address, int channel) { + String token = ZoneHandler.zoneID(address, channel); + if (!discoveredZoneSet.contains(token)) { + notifyDiscoveryOfZone(address, channel, token); + discoveredZoneSet.add(token); + } + } + + public void processRFZone(int serial) { + if (!discoveredRFZoneSet.contains(serial)) { + notifyDiscoveryOfRFZone(serial); + discoveredRFZoneSet.add(serial); + } + } + + private void notifyDiscoveryOfZone(int address, int channel, String idString) { + ThingUID bridgeUID = bridgeHandler.getThing().getUID(); + ThingUID uid = new ThingUID(THING_TYPE_ZONE, bridgeUID, idString); + + Map properties = new HashMap<>(); + properties.put(PROPERTY_ADDRESS, address); + properties.put(PROPERTY_CHANNEL, channel); + properties.put(PROPERTY_ID, idString); + + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID).withProperties(properties) + .withRepresentationProperty(PROPERTY_ID).build(); + thingDiscovered(result); + logger.debug("Discovered Zone {}", uid); + } + + private void notifyDiscoveryOfRFZone(Integer serial) { + ThingUID bridgeUID = bridgeHandler.getThing().getUID(); + ThingUID uid = new ThingUID(THING_TYPE_RFZONE, bridgeUID, serial.toString()); + + Map properties = new HashMap<>(); + properties.put(PROPERTY_SERIAL, serial); + + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID).withProperties(properties) + .withRepresentationProperty(PROPERTY_SERIAL).build(); + thingDiscovered(result); + logger.debug("Discovered RF Zone{}", uid); + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderHandlerFactory.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderHandlerFactory.java new file mode 100644 index 0000000000000..56574fa474fd2 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/AlarmDecoderHandlerFactory.java @@ -0,0 +1,129 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal; + +import static org.openhab.binding.alarmdecoder.internal.AlarmDecoderBindingConstants.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.openhab.binding.alarmdecoder.internal.handler.ADBridgeHandler; +import org.openhab.binding.alarmdecoder.internal.handler.IPBridgeHandler; +import org.openhab.binding.alarmdecoder.internal.handler.KeypadHandler; +import org.openhab.binding.alarmdecoder.internal.handler.LRRHandler; +import org.openhab.binding.alarmdecoder.internal.handler.RFZoneHandler; +import org.openhab.binding.alarmdecoder.internal.handler.SerialBridgeHandler; +import org.openhab.binding.alarmdecoder.internal.handler.ZoneHandler; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link AlarmDecoderHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.alarmdecoder", service = ThingHandlerFactory.class) +public class AlarmDecoderHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Collections + .unmodifiableSet(Stream.of(THING_TYPE_IPBRIDGE, THING_TYPE_SERIALBRIDGE, THING_TYPE_ZONE, THING_TYPE_RFZONE, + THING_TYPE_KEYPAD, THING_TYPE_LRR).collect(Collectors.toSet())); + + private final Logger logger = LoggerFactory.getLogger(AlarmDecoderHandlerFactory.class); + + private final SerialPortManager serialPortManager; + + @Activate + public AlarmDecoderHandlerFactory(final @Reference SerialPortManager serialPortManager) { + // Obtain the serial port manager service using an OSGi reference + this.serialPortManager = serialPortManager; + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + private final Map> discoveryServiceRegMap = new HashMap<>(); + // Marked as Nullable only to fix incorrect redundant null check complaints from null annotations + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_IPBRIDGE.equals(thingTypeUID)) { + IPBridgeHandler bridgeHandler = new IPBridgeHandler((Bridge) thing); + registerDiscoveryService(bridgeHandler); + return bridgeHandler; + } else if (THING_TYPE_SERIALBRIDGE.equals(thingTypeUID)) { + SerialBridgeHandler bridgeHandler = new SerialBridgeHandler((Bridge) thing, serialPortManager); + registerDiscoveryService(bridgeHandler); + return bridgeHandler; + } else if (THING_TYPE_ZONE.equals(thingTypeUID)) { + return new ZoneHandler(thing); + } else if (THING_TYPE_RFZONE.equals(thingTypeUID)) { + return new RFZoneHandler(thing); + } else if (THING_TYPE_KEYPAD.equals(thingTypeUID)) { + return new KeypadHandler(thing); + } else if (THING_TYPE_LRR.equals(thingTypeUID)) { + return new LRRHandler(thing); + } + + return null; + } + + @Override + protected synchronized void removeHandler(ThingHandler thingHandler) { + if (thingHandler instanceof ADBridgeHandler) { + ServiceRegistration serviceReg = discoveryServiceRegMap.remove(thingHandler.getThing().getUID()); + if (serviceReg != null) { + logger.debug("Unregistering discovery service."); + serviceReg.unregister(); + } + } + } + + /** + * Register a discovery service for a bridge handler. + * + * @param bridgeHandler bridge handler for which to register the discovery service + */ + private synchronized void registerDiscoveryService(ADBridgeHandler bridgeHandler) { + logger.debug("Registering discovery service."); + AlarmDecoderDiscoveryService discoveryService = new AlarmDecoderDiscoveryService(bridgeHandler); + bridgeHandler.setDiscoveryService(discoveryService); + discoveryServiceRegMap.put(bridgeHandler.getThing().getUID(), + bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, null)); + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/actions/BridgeActions.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/actions/BridgeActions.java new file mode 100644 index 0000000000000..dac7696cc981e --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/actions/BridgeActions.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.actions; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.binding.ThingActions; +import org.eclipse.smarthome.core.thing.binding.ThingActionsScope; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.openhab.binding.alarmdecoder.internal.handler.ADBridgeHandler; +import org.openhab.binding.alarmdecoder.internal.protocol.ADCommand; +import org.openhab.core.automation.annotation.RuleAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link BridgeActions} class defines thing actions for alarmdecoder bridges. + * + * @author Bob Adair - Initial contribution + */ +@ThingActionsScope(name = "alarmdecoder") +@NonNullByDefault +public class BridgeActions implements ThingActions { + + private final Logger logger = LoggerFactory.getLogger(BridgeActions.class); + + private @Nullable ADBridgeHandler bridge; + + public BridgeActions() { + logger.trace("Alarm Decoder bridge actions service created"); + } + + @Override + public void setThingHandler(@Nullable ThingHandler handler) { + if (handler instanceof ADBridgeHandler) { + this.bridge = (ADBridgeHandler) handler; + } + } + + @Override + public @Nullable ThingHandler getThingHandler() { + return bridge; + } + + /** + * Reboot thing action + */ + @RuleAction(label = "Reboot", description = "Reboot the Alarm Decoder device") + public void reboot() { + ADBridgeHandler bridge = this.bridge; + if (bridge != null) { + bridge.sendADCommand(ADCommand.reboot()); + logger.debug("Sending reboot command."); + } else { + logger.debug("Request for reboot action, but bridge is undefined."); + } + } + + // Static method for Rules DSL backward compatibility + public static void reboot(@Nullable ThingActions actions) { + if (actions instanceof BridgeActions) { + ((BridgeActions) actions).reboot(); + } else { + throw new IllegalArgumentException("Instance is not a BridgeActions class."); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/IPBridgeConfig.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/IPBridgeConfig.java new file mode 100644 index 0000000000000..257f2e603f4cb --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/IPBridgeConfig.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link IPBridgeConfig} class contains fields mapping thing configuration parameters for IPBridgeHandler. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class IPBridgeConfig { + public @Nullable String hostname; + public int tcpPort = 10000; + public boolean discovery = false; + public int reconnect = 2; + public int timeout = 5; +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/KeypadConfig.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/KeypadConfig.java new file mode 100644 index 0000000000000..be65ab9b18fee --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/KeypadConfig.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.config; + +import static org.openhab.binding.alarmdecoder.internal.AlarmDecoderBindingConstants.DEFAULT_MAPPING; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link KeypadConfig} class contains fields mapping thing configuration parameters for KeypadHandler. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class KeypadConfig { + public int addressMask = 0; + public boolean sendCommands = false; + public boolean sendStar = false; + public String commandMapping = DEFAULT_MAPPING; +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/LRRConfig.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/LRRConfig.java new file mode 100644 index 0000000000000..aafc3e9b13a6d --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/LRRConfig.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link LRRConfig} class contains fields mapping thing configuration parameters for LRRHandler. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class LRRConfig { + public int partition = 0; +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/RFZoneConfig.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/RFZoneConfig.java new file mode 100644 index 0000000000000..c30b654e17e63 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/RFZoneConfig.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link RFZoneConfig} class contains fields mapping thing configuration parameters for RFZoneHandler. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class RFZoneConfig { + public int serial = -1; +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/SerialBridgeConfig.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/SerialBridgeConfig.java new file mode 100644 index 0000000000000..3d8e18be2e283 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/SerialBridgeConfig.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link SerialBridgeConfig} class contains fields mapping thing configuration parameters for SerialBridgeHandler. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class SerialBridgeConfig { + public String serialPort = ""; + public int bitrate = 115200; + public boolean discovery = false; +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/ZoneConfig.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/ZoneConfig.java new file mode 100644 index 0000000000000..95142e15d2cd7 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/config/ZoneConfig.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link ZoneConfig} class contains fields mapping thing configuration parameters for ZoneHandler. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class ZoneConfig { + public int address = -1; + public int channel = -1; +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ADBridgeHandler.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ADBridgeHandler.java new file mode 100644 index 0000000000000..6f3e34d074721 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ADBridgeHandler.java @@ -0,0 +1,375 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.handler; + +import static org.openhab.binding.alarmdecoder.internal.AlarmDecoderBindingConstants.*; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; +import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.alarmdecoder.internal.AlarmDecoderDiscoveryService; +import org.openhab.binding.alarmdecoder.internal.actions.BridgeActions; +import org.openhab.binding.alarmdecoder.internal.protocol.ADCommand; +import org.openhab.binding.alarmdecoder.internal.protocol.ADMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.ADMsgType; +import org.openhab.binding.alarmdecoder.internal.protocol.EXPMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.KeypadMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.LRRMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.RFXMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.VersionMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract base class for bridge handlers responsible for communicating with the Nu Tech Alarm Decoder devices. + * Based partly on and including code from the original OH1 alarmdecoder binding by Bernd Pfrommer. + * + * @author Bernd Pfrommer - Initial contribution (OH1 version) + * @author Bob Adair - Re-factored into OH2 binding + */ +@NonNullByDefault +public abstract class ADBridgeHandler extends BaseBridgeHandler { + protected static final Charset AD_CHARSET = StandardCharsets.UTF_8; + + private final Logger logger = LoggerFactory.getLogger(ADBridgeHandler.class); + + protected @Nullable BufferedReader reader = null; + protected @Nullable BufferedWriter writer = null; + protected @Nullable Thread msgReaderThread = null; + private final Object msgReaderThreadLock = new Object(); + protected @Nullable AlarmDecoderDiscoveryService discoveryService; + protected boolean discovery; + protected boolean panelReadyReceived = false; + protected volatile @Nullable Date lastReceivedTime; + protected volatile boolean writeException; + + protected @Nullable ScheduledFuture connectionCheckJob; + protected @Nullable ScheduledFuture connectRetryJob; + + public ADBridgeHandler(Bridge bridge) { + super(bridge); + } + + @Override + public void dispose() { + logger.trace("dispose called"); + disconnect(); + } + + @Override + public Collection> getServices() { + return Collections.singletonList(BridgeActions.class); + } + + public void setDiscoveryService(AlarmDecoderDiscoveryService discoveryService) { + this.discoveryService = discoveryService; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // Accepts no commands, so do nothing. + } + + /** + * Send a command to the alarm decoder using a buffered writer. This could block if the buffer is full, so it should + * eventually be replaced with a queuing mechanism and a separate writer thread. + * + * @param command Command string to send including terminator + */ + public void sendADCommand(ADCommand command) { + logger.debug("Sending AD command: {}", command); + try { + BufferedWriter bw = writer; + if (bw != null) { + bw.write(command.toString()); + bw.flush(); + } + } catch (IOException e) { + logger.info("Exception while sending command: {}", e.getMessage()); + writeException = true; + } + } + + protected abstract void connect(); + + protected abstract void disconnect(); + + protected void scheduleConnectRetry(long waitMinutes) { + logger.debug("Scheduling connection retry in {} minutes", waitMinutes); + connectRetryJob = scheduler.schedule(this::connect, waitMinutes, TimeUnit.MINUTES); + } + + protected void startMsgReader() { + synchronized (msgReaderThreadLock) { + Thread mrt = new Thread(this::readerThread, "AD Reader"); + mrt.setDaemon(true); + mrt.start(); + msgReaderThread = mrt; + } + } + + protected void stopMsgReader() { + synchronized (msgReaderThreadLock) { + Thread mrt = msgReaderThread; + if (mrt != null) { + logger.trace("Stopping reader thread."); + mrt.interrupt(); + msgReaderThread = null; + } + } + } + + /** + * Method executed by message reader thread + */ + private void readerThread() { + logger.debug("Message reader thread started"); + String message = null; + try { + // Send version command to get device to respond with VER message. + sendADCommand(ADCommand.getVersion()); + BufferedReader reader = this.reader; + while (!Thread.interrupted() && reader != null && (message = reader.readLine()) != null) { + logger.trace("Received msg: {}", message); + ADMsgType msgType = ADMsgType.getMsgType(message); + if (msgType != ADMsgType.INVALID) { + lastReceivedTime = new Date(); + } + try { + switch (msgType) { + case KPM: + parseKeypadMessage(message); + break; + case REL: + case EXP: + parseRelayOrExpanderMessage(msgType, message); + break; + case RFX: + parseRFMessage(message); + break; + case LRR: + parseLRRMessage(message); + break; + case VER: + parseVersionMessage(message); + break; + case INVALID: + default: + break; + } + } catch (MessageParseException e) { + logger.warn("Error {} while parsing message {}. Please report bug.", e.getMessage(), message); + } + } + if (message == null) { + logger.info("End of input stream detected"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Connection lost"); + } + } catch (IOException e) { + logger.debug("I/O error while reading from stream: {}", e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } catch (RuntimeException e) { + logger.warn("Runtime exception in reader thread", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } finally { + logger.debug("Message reader thread exiting"); + } + } + + /** + * Parse and handle keypad messages + * + * @param msg string containing incoming message payload + * @throws MessageParseException + */ + private void parseKeypadMessage(String msg) throws MessageParseException { + KeypadMessage kpMsg; + + // Parse the message + try { + kpMsg = new KeypadMessage(msg); + } catch (IllegalArgumentException e) { + throw new MessageParseException(e.getMessage()); + } + + if (kpMsg.panelClear()) { + // the panel is clear, so we can assume that all contacts that we + // have not heard from are open + notifyChildHandlersPanelReady(); + } + + notifyChildHandlers(kpMsg); + } + + /** + * Parse and handle relay and expander messages. The REL and EXP messages have identical format. + * + * @param mt message type of incoming message + * @param msg string containing incoming message payload + * @throws MessageParseException + */ + private void parseRelayOrExpanderMessage(ADMsgType mt, String msg) throws MessageParseException { + // mt is unused at the moment + EXPMessage expMsg; + + try { + expMsg = new EXPMessage(msg); + } catch (IllegalArgumentException e) { + throw new MessageParseException(e.getMessage()); + } + + notifyChildHandlers(expMsg); + + AlarmDecoderDiscoveryService ds = discoveryService; + if (discovery && ds != null) { + ds.processZone(expMsg.address, expMsg.channel); + } + } + + /** + * Parse and handle RFX messages. + * + * @param msg string containing incoming message payload + * @throws MessageParseException + */ + private void parseRFMessage(String msg) throws MessageParseException { + RFXMessage rfxMsg; + + try { + rfxMsg = new RFXMessage(msg); + } catch (IllegalArgumentException e) { + throw new MessageParseException(e.getMessage()); + } + + notifyChildHandlers(rfxMsg); + + AlarmDecoderDiscoveryService ds = discoveryService; + if (discovery && ds != null) { + ds.processRFZone(rfxMsg.serial); + } + } + + /** + * Parse and handle LRR messages. + * + * @param msg string containing incoming message payload + * @throws MessageParseException + */ + private void parseLRRMessage(String msg) throws MessageParseException { + LRRMessage lrrMsg; + + // Parse the message + try { + lrrMsg = new LRRMessage(msg); + } catch (IllegalArgumentException e) { + throw new MessageParseException(e.getMessage()); + } + + notifyChildHandlers(lrrMsg); + } + + /** + * Parse and handle version (VER) message. This just updates bridge properties. + * + * @param msg string containing incoming message payload + * @throws MessageParseException + */ + private void parseVersionMessage(String msg) throws MessageParseException { + VersionMessage verMsg; + + try { + verMsg = new VersionMessage(msg); + } catch (IllegalArgumentException e) { + throw new MessageParseException(e.getMessage()); + } + + logger.trace("Processing version message sn:{} ver:{} cap:{}", verMsg.serial, verMsg.version, + verMsg.capabilities); + Map properties = editProperties(); + properties.put(PROPERTY_SERIALNUM, verMsg.serial); + properties.put(PROPERTY_VERSION, verMsg.version); + properties.put(PROPERTY_CAPABILITIES, verMsg.capabilities); + updateProperties(properties); + } + + /** + * Notify appropriate child thing handlers of an AD message by calling their handleUpdate() methods. + * + * @param msg message to forward to child handler(s) + */ + private void notifyChildHandlers(ADMessage msg) { + for (Thing thing : getThing().getThings()) { + ADThingHandler handler = (ADThingHandler) thing.getHandler(); + //@formatter:off + if (handler != null && ((handler instanceof ZoneHandler && msg instanceof EXPMessage) || + (handler instanceof RFZoneHandler && msg instanceof RFXMessage) || + (handler instanceof KeypadHandler && msg instanceof KeypadMessage) || + (handler instanceof LRRHandler && msg instanceof LRRMessage))) { + handler.handleUpdate(msg); + } + //@formatter:on + } + } + + /** + * Notify child thing handlers that the alarm panel is in the ready state. Since there is no way to poll, all + * contact channels are initialized into the UNDEF state. This method is called when there is reason to assume that + * there are no faulted zones, because the alarm panel is in state READY. Zone handlers that have not yet received + * updates can then set their contact states to CLOSED. Only executes the first time panel is ready after bridge + * connect/reconnect. Currently only notifies ZoneHandler and RFZoneHandler things. + */ + private void notifyChildHandlersPanelReady() { + if (!panelReadyReceived) { + panelReadyReceived = true; + logger.trace("Notifying child handlers that panel is in ready state"); + + // Notify child zone handlers by calling notifyPanelReady() for each + for (Thing thing : getThing().getThings()) { + ADThingHandler handler = (ADThingHandler) thing.getHandler(); + if (handler != null && (handler instanceof ZoneHandler || handler instanceof RFZoneHandler)) { + handler.notifyPanelReady(); + } + } + } + } + + /** + * Exception thrown by message parsing code when it encounters a malformed message + */ + private static class MessageParseException extends Exception { + private static final long serialVersionUID = 1L; + + public MessageParseException(String msg) { + super(msg); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ADThingHandler.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ADThingHandler.java new file mode 100644 index 0000000000000..bba2c6a93c0e8 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ADThingHandler.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.handler; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.openhab.binding.alarmdecoder.internal.protocol.ADCommand; +import org.openhab.binding.alarmdecoder.internal.protocol.ADMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@link ADThingHandler} is the abstract base class for all AD thing handlers. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public abstract class ADThingHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(ADThingHandler.class); + protected final AtomicBoolean firstUpdateReceived = new AtomicBoolean(false); + + public ADThingHandler(Thing thing) { + super(thing); + } + + /** + * Initialize device state and set status for handler. Should be called at the end of initialize(). Also called by + * bridgeStatusChanged() when bridge status changes from OFFLINE to ONLINE. Calls initChannelState() to initialize + * channels if setting status to ONLINE. + */ + protected void initDeviceState() { + logger.trace("Initializing device state"); + Bridge bridge = getBridge(); + if (bridge == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bridge configured"); + } else if (bridge.getStatus() == ThingStatus.ONLINE) { + initChannelState(); + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + } + } + + /** + * Initialize channel states if necessary + */ + public abstract void initChannelState(); + + /** + * Notify handler that panel is in ready state so that any un-updated contact channels can be set to default + * (closed). + */ + public abstract void notifyPanelReady(); + + /** + * Notify handler of a message from the AD via the bridge + * + * @param msg The ADMessage to handle + */ + public abstract void handleUpdate(ADMessage msg); + + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + ThingStatus bridgeStatus = bridgeStatusInfo.getStatus(); + logger.debug("Bridge status changed to {} for AD handler", bridgeStatus); + + if (bridgeStatus == ThingStatus.ONLINE + && getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_OFFLINE) { + initDeviceState(); + + } else if (bridgeStatus == ThingStatus.OFFLINE) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + } + } + + /** + * Send a command via the bridge + * + * @param command command to send + */ + protected void sendCommand(ADCommand command) { + Bridge bridge = getBridge(); + ADBridgeHandler bridgeHandler = bridge == null ? null : (ADBridgeHandler) bridge.getHandler(); + + if (bridgeHandler == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_MISSING_ERROR, "No bridge associated"); + } else { + bridgeHandler.sendADCommand(command); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/IPBridgeHandler.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/IPBridgeHandler.java new file mode 100644 index 0000000000000..542f5de0cabc0 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/IPBridgeHandler.java @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.handler; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.Date; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.openhab.binding.alarmdecoder.internal.config.IPBridgeConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handler responsible for communicating via TCP with the Nu Tech Alarm Decoder device. + * Based on and including code from the original OH1 alarmdecoder binding. + * + * @author Bernd Pfrommer - Initial contribution (OH1 version) + * @author Bob Adair - Re-factored into OH2 binding + */ +@NonNullByDefault +public class IPBridgeHandler extends ADBridgeHandler { + + private final Logger logger = LoggerFactory.getLogger(IPBridgeHandler.class); + + private IPBridgeConfig config = new IPBridgeConfig(); + + private @Nullable Socket socket = null; + + public IPBridgeHandler(Bridge bridge) { + super(bridge); + } + + @Override + public void initialize() { + logger.debug("Initializing IP bridge handler"); + config = getConfigAs(IPBridgeConfig.class); + discovery = config.discovery; + + if (config.hostname == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "hostname not configured"); + return; + } + if (config.tcpPort <= 0 || config.tcpPort > 65535) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "invalid port number configured"); + return; + } + + // set the thing status to UNKNOWN temporarily and let the background connect task decide the real status. + updateStatus(ThingStatus.UNKNOWN); + + scheduler.submit(this::connect); // start the async connect task + } + + @Override + protected synchronized void connect() { + disconnect(); // make sure we are disconnected + writeException = false; + try { + Socket socket = new Socket(config.hostname, config.tcpPort); + this.socket = socket; + reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), AD_CHARSET)); + writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), AD_CHARSET)); + logger.debug("connected to {}:{}", config.hostname, config.tcpPort); + panelReadyReceived = false; + startMsgReader(); + updateStatus(ThingStatus.ONLINE); + + // Start connection check job + logger.debug("Scheduling connection check job with interval {} minutes.", config.reconnect); + lastReceivedTime = new Date(); + connectionCheckJob = scheduler.scheduleWithFixedDelay(this::connectionCheck, config.reconnect, + config.reconnect, TimeUnit.MINUTES); + } catch (UnknownHostException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "unknown host"); + disconnect(); + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + disconnect(); + scheduleConnectRetry(config.reconnect); // Possibly a retryable error. Try again later. + } + } + + protected synchronized void connectionCheck() { + logger.trace("Connection check job running"); + + Thread mrThread = msgReaderThread; + if (mrThread != null && !mrThread.isAlive()) { + logger.debug("Reader thread has exited abnormally. Restarting."); + scheduler.submit(this::connect); + } else if (writeException) { + logger.debug("Write exception encountered. Resetting connection."); + scheduler.submit(this::connect); + } else { + Date now = new Date(); + Date last = lastReceivedTime; + if (last != null && config.timeout > 0 + && ((last.getTime() + (config.timeout * 60 * 1000)) < now.getTime())) { + logger.warn("Last valid message received at {}. Resetting connection.", last); + scheduler.submit(this::connect); + } + } + } + + @Override + protected synchronized void disconnect() { + logger.trace("Disconnecting"); + // stop scheduled connection check and retry jobs + ScheduledFuture crJob = connectRetryJob; + if (crJob != null) { + // use cancel(false) so we don't kill ourselves when connect retry job calls disconnect() + crJob.cancel(false); + connectRetryJob = null; + } + ScheduledFuture ccJob = connectionCheckJob; + if (ccJob != null) { + // use cancel(false) so we don't kill ourselves when reconnect job calls disconnect() + ccJob.cancel(false); + connectionCheckJob = null; + } + + // Must close the socket first so the message reader thread will exit properly. + // The BufferedReader.readLine() call used in readerThread() is not interruptable. + Socket s = socket; + if (s != null) { + try { + s.close(); + } catch (IOException e) { + logger.debug("error closing socket: {}", e.getMessage()); + } + } + socket = null; + + stopMsgReader(); + + try { + BufferedWriter bw = writer; + if (bw != null) { + bw.close(); + } + BufferedReader br = reader; + if (br != null) { + br.close(); + } + } catch (IOException e) { + logger.debug("error closing reader/writer: {}", e.getMessage()); + } + writer = null; + reader = null; + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/KeypadHandler.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/KeypadHandler.java new file mode 100644 index 0000000000000..8d40baafe8334 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/KeypadHandler.java @@ -0,0 +1,204 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.handler; + +import static org.openhab.binding.alarmdecoder.internal.AlarmDecoderBindingConstants.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.alarmdecoder.internal.config.KeypadConfig; +import org.openhab.binding.alarmdecoder.internal.protocol.ADCommand; +import org.openhab.binding.alarmdecoder.internal.protocol.ADMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.IntCommandMap; +import org.openhab.binding.alarmdecoder.internal.protocol.KeypadMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link KeypadHandler} is responsible for handling keypad messages. + * + * @author Bob Adair - Initial contribution + * @author Bill Forsyth - Initial contribution + */ +@NonNullByDefault +public class KeypadHandler extends ADThingHandler { + + private static final Pattern VALID_COMMAND_PATTERN = Pattern.compile(ADCommand.KEYPAD_COMMAND_REGEX); + + private final Logger logger = LoggerFactory.getLogger(KeypadHandler.class); + + private KeypadConfig config = new KeypadConfig(); + private boolean singleAddress; + private @Nullable IntCommandMap intCommandMap; + private @Nullable KeypadMessage previousMessage; + + public KeypadHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + config = getConfigAs(KeypadConfig.class); + + if (config.addressMask < 0) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid addressMask setting"); + return; + } + singleAddress = (Integer.bitCount(config.addressMask) == 1); + + try { + intCommandMap = new IntCommandMap(config.commandMapping); + } catch (IllegalArgumentException e) { + logger.warn("Invalid commmandMapping parameter supplied. Error: {}.", e.getMessage()); + intCommandMap = null; + } + + logger.debug("Keypad handler initializing for address mask {}", config.addressMask); + + initDeviceState(); + + logger.trace("Keypad handler finished initializing"); + } + + @Override + public void initChannelState() { + previousMessage = null; + } + + @Override + public void notifyPanelReady() { + // Do nothing + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + IntCommandMap intCommandMap = this.intCommandMap; + + if (channelUID.getId().equals(CHANNEL_KP_COMMAND)) { + if (command instanceof StringType) { + String cmd = ((StringType) command).toString(); + handleKeypadCommand(cmd); + } + } else if (channelUID.getId().equals(CHANNEL_KP_INTCOMMAND)) { + if (command instanceof Number) { + int icmd = ((Number) command).intValue(); + if (intCommandMap != null) { + String cmd = intCommandMap.getCommand(icmd); + if (cmd != null) { + handleKeypadCommand(cmd); + } + } + } + } + } + + private void handleKeypadCommand(String command) { + String cmd = command; + if (cmd.length() > 0) { + if (!config.sendCommands) { + logger.info("Sending keypad commands is disabled. Enable using the sendCommands keypad parameter."); + return; + } + + // check that received command is valid + Matcher matcher = VALID_COMMAND_PATTERN.matcher(cmd); + if (!matcher.matches()) { + logger.info("Invalid characters in command. Ignoring command: {}", cmd); + return; + } + + // Replace A-H in command string with special key strings + cmd = cmd.replace("A", ADCommand.SPECIAL_KEY_1); + cmd = cmd.replace("B", ADCommand.SPECIAL_KEY_2); + cmd = cmd.replace("C", ADCommand.SPECIAL_KEY_3); + cmd = cmd.replace("D", ADCommand.SPECIAL_KEY_4); + cmd = cmd.replace("E", ADCommand.SPECIAL_KEY_5); + cmd = cmd.replace("F", ADCommand.SPECIAL_KEY_6); + cmd = cmd.replace("G", ADCommand.SPECIAL_KEY_7); + cmd = cmd.replace("H", ADCommand.SPECIAL_KEY_8); + + if (singleAddress) { + sendCommand(ADCommand.addressedMessage(config.addressMask, cmd)); // send from keypad address + } else { + sendCommand(new ADCommand(cmd)); // send from AD address + } + } + } + + @Override + public void handleUpdate(ADMessage msg) { + // This will ignore a received message unless it is a KeypadMessage and either this handler's address mask is 0 + // (all), the message's address mask is 0 (all), or any bits in this handler's address mask match bits set in + // the message's address mask. + if (!(msg instanceof KeypadMessage)) { + return; + } + KeypadMessage kpMsg = (KeypadMessage) msg; + int addressMask = kpMsg.getIntAddressMask(); + if (!(((config.addressMask & addressMask) != 0) || config.addressMask == 0 || addressMask == 0)) { + return; + } + logger.trace("Keypad handler for address mask {} received update: {}", config.addressMask, kpMsg); + + if (kpMsg.equals(previousMessage)) { + return; // ignore repeated messages + } + + if (config.sendStar) { + if (kpMsg.alphaMessage.contains("Hit * for faults") || kpMsg.alphaMessage.contains("Press * to show faults") + || kpMsg.alphaMessage.contains("Press * Key")) { + logger.debug("Sending * command to show faults."); + if (singleAddress) { + sendCommand(ADCommand.addressedMessage(config.addressMask, "*")); // send from keypad address + } else { + sendCommand(new ADCommand("*")); // send from AD address + } + } + } + + updateState(CHANNEL_KP_ZONE, new DecimalType(kpMsg.getZone())); + updateState(CHANNEL_KP_TEXT, new StringType(kpMsg.alphaMessage)); + + updateState(CHANNEL_KP_READY, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_READY))); + updateState(CHANNEL_KP_ARMEDAWAY, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_ARMEDAWAY))); + updateState(CHANNEL_KP_ARMEDHOME, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_ARMEDHOME))); + updateState(CHANNEL_KP_BACKLIGHT, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_BACKLIGHT))); + updateState(CHANNEL_KP_PRORGAM, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_PRORGAM))); + + updateState(CHANNEL_KP_BEEPS, new DecimalType(kpMsg.nbeeps)); + + updateState(CHANNEL_KP_BYPASSED, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_BYPASSED))); + updateState(CHANNEL_KP_ACPOWER, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_ACPOWER))); + updateState(CHANNEL_KP_CHIME, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_CHIME))); + updateState(CHANNEL_KP_ALARMOCCURRED, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_ALARMOCCURRED))); + updateState(CHANNEL_KP_ALARM, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_ALARM))); + updateState(CHANNEL_KP_LOWBAT, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_LOWBAT))); + updateState(CHANNEL_KP_DELAYOFF, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_DELAYOFF))); + updateState(CHANNEL_KP_FIRE, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_FIRE))); + updateState(CHANNEL_KP_SYSFAULT, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_SYSFAULT))); + updateState(CHANNEL_KP_PERIMETER, OnOffType.from(kpMsg.getStatus(KeypadMessage.BIT_PERIMETER))); + + previousMessage = kpMsg; + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/LRRHandler.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/LRRHandler.java new file mode 100644 index 0000000000000..eb3b52662e5a2 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/LRRHandler.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.handler; + +import static org.openhab.binding.alarmdecoder.internal.AlarmDecoderBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.alarmdecoder.internal.config.LRRConfig; +import org.openhab.binding.alarmdecoder.internal.protocol.ADMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.LRRMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link LRRHandler} is responsible for handling long range radio (LRR) messages. + * + * @author Bob Adair - Initial contribution + * @author Bill Forsyth - Initial contribution + */ +@NonNullByDefault +public class LRRHandler extends ADThingHandler { + + private final Logger logger = LoggerFactory.getLogger(LRRHandler.class); + + private LRRConfig config = new LRRConfig(); + + public LRRHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + config = getConfigAs(LRRConfig.class); + + if (config.partition < 0) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR); + return; + } + logger.debug("LRR handler initializing for partition {}", config.partition); + + initDeviceState(); + + logger.trace("LRR handler finished initializing"); + } + + @Override + public void initChannelState() { + // Do nothing + } + + @Override + public void notifyPanelReady() { + // Do nothing + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // All channels are read-only, so ignore all commands. + } + + @Override + public void handleUpdate(ADMessage msg) { + if (!(msg instanceof LRRMessage)) { + return; + } + LRRMessage lrrMsg = (LRRMessage) msg; + + if (config.partition == lrrMsg.partition || config.partition == 0 || lrrMsg.partition == 0) { + logger.trace("LRR handler for partition {} received update: {}", config.partition, msg); + updateState(CHANNEL_LRR_PARTITION, new DecimalType(lrrMsg.partition)); + updateState(CHANNEL_LRR_EVENTDATA, new DecimalType(lrrMsg.eventData)); + updateState(CHANNEL_LRR_CIDMESSAGE, new StringType(lrrMsg.cidMessage)); + updateState(CHANNEL_LRR_REPORTCODE, new StringType(lrrMsg.reportCode)); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/RFZoneHandler.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/RFZoneHandler.java new file mode 100644 index 0000000000000..5de4abf422b67 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/RFZoneHandler.java @@ -0,0 +1,121 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.handler; + +import static org.openhab.binding.alarmdecoder.internal.AlarmDecoderBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.alarmdecoder.internal.config.RFZoneConfig; +import org.openhab.binding.alarmdecoder.internal.protocol.ADMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.RFXMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link RFZoneHandler} is responsible for handling wired zones (i.e. RFX messages). + * + * @author Bob Adair - Initial contribution + * @author Bill Forsyth - Initial contribution + */ +@NonNullByDefault +public class RFZoneHandler extends ADThingHandler { + + private final Logger logger = LoggerFactory.getLogger(RFZoneHandler.class); + + private RFZoneConfig config = new RFZoneConfig(); + + public RFZoneHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + config = getConfigAs(RFZoneConfig.class); + + if (config.serial < 0) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid serial setting"); + return; + } + logger.debug("RF Zone handler initializing for serial {}", config.serial); + + initDeviceState(); + + logger.trace("RF Zone handler finished initializing"); + } + + /** + * Set contact channel states to "UNDEF" at init time. The real states will be set either when the first message + * arrives for the zone, or they will be set to "CLOSED" the first time the panel goes into the "READY" state. + */ + @Override + public void initChannelState() { + UnDefType state = UnDefType.UNDEF; + updateState(CHANNEL_RF_LOWBAT, state); + updateState(CHANNEL_RF_SUPERVISION, state); + updateState(CHANNEL_RF_LOOP1, state); + updateState(CHANNEL_RF_LOOP2, state); + updateState(CHANNEL_RF_LOOP3, state); + updateState(CHANNEL_RF_LOOP4, state); + firstUpdateReceived.set(false); + } + + @Override + public void notifyPanelReady() { + logger.trace("RF Zone handler for {} received panel ready notification.", config.serial); + if (firstUpdateReceived.compareAndSet(false, true)) { + updateState(CHANNEL_RF_LOOP1, OpenClosedType.CLOSED); + updateState(CHANNEL_RF_LOOP2, OpenClosedType.CLOSED); + updateState(CHANNEL_RF_LOOP3, OpenClosedType.CLOSED); + updateState(CHANNEL_RF_LOOP4, OpenClosedType.CLOSED); + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // Does not accept any commands + } + + @Override + public void handleUpdate(ADMessage msg) { + if (!(msg instanceof RFXMessage)) { + return; + } + RFXMessage rfxMsg = (RFXMessage) msg; + + if (config.serial == rfxMsg.serial) { + logger.trace("RF Zone handler for serial {} received update: {}", config.serial, rfxMsg.data); + firstUpdateReceived.set(true); + + updateState(CHANNEL_RF_LOWBAT, (rfxMsg.data & RFXMessage.BIT_LOWBAT) == 0 ? OnOffType.OFF : OnOffType.ON); + updateState(CHANNEL_RF_SUPERVISION, + (rfxMsg.data & RFXMessage.BIT_SUPER) == 0 ? OnOffType.OFF : OnOffType.ON); + + updateState(CHANNEL_RF_LOOP1, + (rfxMsg.data & RFXMessage.BIT_LOOP1) == 0 ? OpenClosedType.CLOSED : OpenClosedType.OPEN); + updateState(CHANNEL_RF_LOOP2, + (rfxMsg.data & RFXMessage.BIT_LOOP2) == 0 ? OpenClosedType.CLOSED : OpenClosedType.OPEN); + updateState(CHANNEL_RF_LOOP3, + (rfxMsg.data & RFXMessage.BIT_LOOP3) == 0 ? OpenClosedType.CLOSED : OpenClosedType.OPEN); + updateState(CHANNEL_RF_LOOP4, + (rfxMsg.data & RFXMessage.BIT_LOOP4) == 0 ? OpenClosedType.CLOSED : OpenClosedType.OPEN); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/SerialBridgeHandler.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/SerialBridgeHandler.java new file mode 100644 index 0000000000000..706e903004af4 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/SerialBridgeHandler.java @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.handler; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; +import org.openhab.binding.alarmdecoder.internal.config.SerialBridgeConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handler responsible for communicating via a serial port with the Nu Tech Alarm Decoder device. + * Based on code from the original OH1 alarmdecoder binding. Some OHC serial transport code taken from the Zigbee + * binding. + * + * @author Bernd Pfrommer - Initial contribution (OH1 version) + * @author Bob Adair - Re-factored into OH2 binding and rewrote to use OHC serial transport. + */ +@NonNullByDefault +public class SerialBridgeHandler extends ADBridgeHandler { + + private final Logger logger = LoggerFactory.getLogger(SerialBridgeHandler.class); + + private SerialBridgeConfig config = new SerialBridgeConfig(); + private final SerialPortManager serialPortManager; + private @NonNullByDefault({}) SerialPortIdentifier portIdentifier; + private @Nullable SerialPort serialPort; + private int serialPortSpeed = 115200; + + public SerialBridgeHandler(Bridge bridge, SerialPortManager serialPortManager) { + super(bridge); + this.serialPortManager = serialPortManager; + } + + @Override + public void initialize() { + logger.debug("Initializing serial bridge handler"); + config = getConfigAs(SerialBridgeConfig.class); + discovery = config.discovery; + + if (config.serialPort.isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "no serial port configured"); + return; + } + + if (config.bitrate > 0) { + serialPortSpeed = config.bitrate; + } + + portIdentifier = serialPortManager.getIdentifier(config.serialPort); + if (portIdentifier == null) { + logger.debug("Serial Error: Port {} does not exist.", config.serialPort); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Configured serial port does not exist"); + return; + } + + connect(); + + logger.trace("Finished initializing serial bridge handler"); + } + + @Override + protected synchronized void connect() { + disconnect(); // make sure we are disconnected + try { + SerialPort serialPort = portIdentifier.open("org.openhab.binding.alarmdecoder", 100); + serialPort.setSerialPortParams(serialPortSpeed, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, + SerialPort.PARITY_NONE); + serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN | SerialPort.FLOWCONTROL_RTSCTS_OUT); + // Note: The V1 code called disableReceiveFraming() and disableReceiveThreshold() here + + this.serialPort = serialPort; + reader = new BufferedReader(new InputStreamReader(serialPort.getInputStream(), AD_CHARSET)); + writer = new BufferedWriter(new OutputStreamWriter(serialPort.getOutputStream(), AD_CHARSET)); + + logger.debug("connected to serial port: {}", config.serialPort); + panelReadyReceived = false; + startMsgReader(); + updateStatus(ThingStatus.ONLINE); + } catch (PortInUseException e) { + logger.debug("Cannot open serial port: {}, it is already in use", config.serialPort); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Serial port already in use"); + } catch (UnsupportedCommOperationException | IOException | IllegalStateException e) { + logger.debug("Error connecting to serial port: {}", e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + @Override + protected synchronized void disconnect() { + logger.trace("Disconnecting"); + SerialPort sp = serialPort; + if (sp != null) { + logger.trace("Closing serial port"); + sp.close(); + serialPort = null; + } + + stopMsgReader(); + + BufferedReader br = reader; + if (br != null) { + logger.trace("Closing reader"); + try { + br.close(); + } catch (IOException e) { + logger.info("IO Exception closing reader: {}", e.getMessage()); + } finally { + reader = null; + } + } + + BufferedWriter bw = writer; + if (bw != null) { + logger.trace("Closing writer"); + try { + bw.close(); + } catch (IOException e) { + logger.info("IO Exception closing writer: {}", e.getMessage()); + } finally { + writer = null; + } + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ZoneHandler.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ZoneHandler.java new file mode 100644 index 0000000000000..67069aa44a2f2 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/handler/ZoneHandler.java @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.handler; + +import static org.openhab.binding.alarmdecoder.internal.AlarmDecoderBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.alarmdecoder.internal.config.ZoneConfig; +import org.openhab.binding.alarmdecoder.internal.protocol.ADMessage; +import org.openhab.binding.alarmdecoder.internal.protocol.EXPMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ZoneHandler} is responsible for handling wired zones (i.e. REL & EXP messages). + * + * @author Bob Adair - Initial contribution + * @author Bill Forsyth - Initial contribution + */ +@NonNullByDefault +public class ZoneHandler extends ADThingHandler { + + private final Logger logger = LoggerFactory.getLogger(ZoneHandler.class); + + private ZoneConfig config = new ZoneConfig(); + + public ZoneHandler(Thing thing) { + super(thing); + } + + /** Construct zone id from address and channel */ + public static final String zoneID(int address, int channel) { + return String.format("%d-%d", address, channel); + } + + @Override + public void initialize() { + config = getConfigAs(ZoneConfig.class); + + if (config.address < 0 || config.channel < 0) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid address/channel setting"); + return; + } + logger.debug("Zone handler initializing for address {} channel {}", config.address, config.channel); + + String id = zoneID(config.address, config.channel); + updateProperty(PROPERTY_ID, id); // set representation property used by discovery + + initDeviceState(); + logger.trace("Zone handler finished initializing"); + } + + /** + * Set contact channel state to "UNDEF" at init time. The real state will be set either when the first message + * arrives for the zone, or it should be set to "CLOSED" the first time the panel goes into the "READY" state. + */ + @Override + public void initChannelState() { + UnDefType state = UnDefType.UNDEF; + updateState(CHANNEL_CONTACT, state); + firstUpdateReceived.set(false); + } + + @Override + public void notifyPanelReady() { + logger.trace("Zone handler for {},{} received panel ready notification.", config.address, config.channel); + if (firstUpdateReceived.compareAndSet(false, true)) { + updateState(CHANNEL_CONTACT, OpenClosedType.CLOSED); + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // All channels are read-only, so ignore all commands. + } + + @Override + public void handleUpdate(ADMessage msg) { + if (!(msg instanceof EXPMessage)) { + return; + } + EXPMessage expMsg = (EXPMessage) msg; + + if (config.address == expMsg.address && config.channel == expMsg.channel) { + logger.trace("Zone handler for {},{} received update: {}", config.address, config.channel, expMsg.data); + + firstUpdateReceived.set(true); + OpenClosedType state = (expMsg.data == 0 ? OpenClosedType.CLOSED : OpenClosedType.OPEN); + updateState(CHANNEL_CONTACT, state); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADCommand.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADCommand.java new file mode 100644 index 0000000000000..e2a773c2b34eb --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADCommand.java @@ -0,0 +1,137 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link ADCCommand} class represents an alarm decoder command, and contains the static methods and definitions + * used to construct one. Not all supported AD commands are necessarily used by the current binding. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public final class ADCommand { + + public static final String SPECIAL_KEY_1 = "\u0001\u0001\u0001"; + public static final String SPECIAL_KEY_2 = "\u0002\u0002\u0002"; + public static final String SPECIAL_KEY_3 = "\u0003\u0003\u0003"; + public static final String SPECIAL_KEY_4 = "\u0004\u0004\u0004"; + public static final String SPECIAL_KEY_5 = "\u0005\u0005\u0005"; + public static final String SPECIAL_KEY_6 = "\u0006\u0006\u0006"; + public static final String SPECIAL_KEY_7 = "\u0007\u0007\u0007"; + public static final String SPECIAL_KEY_8 = "\u0008\u0008\u0008"; + + // public static final String KEYPAD_COMMAND_CHARACTERS = "0123456789*#<>"; + public static final String KEYPAD_COMMAND_REGEX = "^[0-9A-H*#<>]+$"; + + private static final String TERM = "\r\n"; + + private static final String COMMAND_REBOOT = "="; + private static final String COMMAND_CONFIG = "C"; + private static final String COMMAND_ZONE = "L"; + private static final String COMMAND_ERROR = "E"; + private static final String COMMAND_VERSION = "V"; + private static final String COMMAND_ADDRMSG = "K"; + private static final String COMMAND_ACKCRC = "R"; + + public final String command; + + public ADCommand(String command) { + this.command = command + TERM; + } + + @Override + public String toString() { + return command; + } + + public static ADCommand reboot() { + return new ADCommand(COMMAND_REBOOT); + } + + /** + * Construct an AD configuration command. If configParam is null, a query configuration command will be created. + * If configParam consists of one or more NAME=value pairs (separated by '&' characters), a set configuration + * command will be created. The validity of configParam is not checked. + * + * @param configParam String containing parameters to set or null + * @return ADCommand object containing the constructed command + */ + public static ADCommand config(@Nullable String configParam) { + if (configParam == null) { + return new ADCommand(COMMAND_CONFIG); + } else { + return new ADCommand(COMMAND_CONFIG + configParam); + } + } + + /** + * Construct an AD command to set the state of an emulated zone. + * + * @param zone The emulated zone number (0-99) for the command. + * @param state The new state (0 or 1) for the emulated zone. + * @return ADCommand object containing the constructed command + * @throws IllegalArgumentException + */ + public static ADCommand setZone(int zone, int state) throws IllegalArgumentException { + if (zone < 0 || zone > 99 || state < 0 || state > 1) { + throw new IllegalArgumentException("Invalid parameter(s)"); + } + return new ADCommand(String.format("%s%02d%d", COMMAND_ZONE, zone, state)); + } + + /** + * Construct an AD command to get and clear the error counters. + * + * @return ADCommand object containing the constructed command + */ + public static ADCommand getErrors() { + return new ADCommand(COMMAND_ERROR); + } + + /** + * Construct an AD command to request a version info message. + * + * @return ADCommand object containing the constructed command + */ + public static ADCommand getVersion() { + return new ADCommand(COMMAND_VERSION); + } + + /** + * Construct an AD command to send a message from a specific partition or keypad address, rather than from the Alarm + * Decoder unit's configured address. + * + * @param address The keypad address or partition (0-99) from which to send the command + * @param message A String containing the message to send. Length must be > 0. + * @return ADCommand object containing the constructed command + * @throws IllegalArgumentException + */ + public static ADCommand addressedMessage(int address, String message) throws IllegalArgumentException { + if (address < 0 || address > 99 || message.length() < 1) { + throw new IllegalArgumentException("Invalid parameter(s)"); + } + return new ADCommand(String.format("%s%02d%s", COMMAND_ADDRMSG, address, message)); + } + + /** + * Construct an AD command to acknowledge that a received CRC message was valid. + * + * @return ADCommand object containing the constructed command + */ + public static ADCommand ackCRC() { + return new ADCommand(COMMAND_ACKCRC); + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADMessage.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADMessage.java new file mode 100644 index 0000000000000..72111655be86e --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADMessage.java @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Superclass for all Alarm Decoder protocol message types. + * Includes code from the original OH1 alarmdecoder binding by Bernd Pfrommer. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public abstract class ADMessage { + + protected static final Pattern SPLIT_REGEX = Pattern.compile("[^\\,\"]+|\"[^\"]*\""); + + /** string containing the original unparsed message */ + public final String message; + + public ADMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return message; + } + + /** Utility routine to split an AD message into its component parts */ + protected static List splitMsg(String msg) { + List l = new ArrayList(); + Matcher regexMatcher = SPLIT_REGEX.matcher(msg); + while (regexMatcher.find()) { + l.add(regexMatcher.group()); + } + return l; + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADMsgType.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADMsgType.java new file mode 100644 index 0000000000000..b12ed7411d096 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/ADMsgType.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import java.util.HashMap; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The various message types that come from the ad2usb/ad2pi interface + * + * @author Bernd Pfrommer - Initial contribution (OH1) + * @author Bob Adair - Re-factored and removed methods unused in OH2 binding + */ +@NonNullByDefault +public enum ADMsgType { + EXP, // zone expander message + KPM, // keypad message + LRR, // long range radio message + REL, // relay message + RFX, // wireless message + VER, // version message + INVALID; // invalid message + + /** hash map from protocol message heading to type */ + private static HashMap startToMsgType = new HashMap<>(); + + static { + startToMsgType.put("!REL", ADMsgType.REL); + startToMsgType.put("!SER", ADMsgType.INVALID); + startToMsgType.put("!RFX", ADMsgType.RFX); + startToMsgType.put("!EXP", ADMsgType.EXP); + startToMsgType.put("!LRR", ADMsgType.LRR); + startToMsgType.put("!VER", ADMsgType.VER); + } + + /** + * Extract message type from message. Relies on static map startToMsgType. + * + * @param s message string + * @return message type + */ + public static ADMsgType getMsgType(@Nullable String s) { + if (s == null || s.length() < 4) { + return ADMsgType.INVALID; + } + if (s.startsWith("[")) { + return ADMsgType.KPM; + } + ADMsgType mt = startToMsgType.get(s.substring(0, 4)); + if (mt == null) { + mt = ADMsgType.INVALID; + } + return mt; + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/EXPMessage.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/EXPMessage.java new file mode 100644 index 0000000000000..094c174e5fe0e --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/EXPMessage.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link EXPMessage} class represents a parsed zone (EXP or REL) message. + * Based partly on code from the OH1 alarmdecoder binding by Bernd Pfrommer. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class EXPMessage extends ADMessage { + + // Example: !EXP:07,01,01 + // Example: !REL:12,01,01 + + /** Address number */ + public final int address; + + /** Channel number */ + public final int channel; + + /** Message data */ + public final int data; + + public EXPMessage(String message) throws IllegalArgumentException { + super(message); + + String topLevel[] = message.split(":"); + if (topLevel.length != 2) { + throw new IllegalArgumentException("Multiple colons found in EXP message"); + } + + List parts = splitMsg(topLevel[1]); + + if (parts.size() != 3) { + throw new IllegalArgumentException("Invalid number of parts in EXP message"); + } + + try { + address = Integer.parseInt(parts.get(0)); + channel = Integer.parseInt(parts.get(1)); + data = Integer.parseInt(parts.get(2)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("EXP message contains invalid number: " + e.getMessage(), e); + } + + if ((data & ~0x1) != 0) { + throw new IllegalArgumentException("zone status should only be 0 or 1"); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/IntCommandMap.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/IntCommandMap.java new file mode 100644 index 0000000000000..9c1c6602ca074 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/IntCommandMap.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link IntCommandMap} class contains an integer to command map used by the keypad intcommand channel. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class IntCommandMap { + private static final Pattern VALID_COMMAND_PATTERN = Pattern.compile(ADCommand.KEYPAD_COMMAND_REGEX); + + private final Map commandMap; + + public IntCommandMap(String mappingString) throws IllegalArgumentException { + commandMap = new HashMap<>(); + + String mstring = mappingString.replace("POUND", "#"); + String[] elements = mstring.split(","); + for (String element : elements) { + String[] kvPair = element.split("="); + if (kvPair.length != 2) { + throw new IllegalArgumentException("Invalid key-value pair format"); + } + + Matcher matcher = VALID_COMMAND_PATTERN.matcher(kvPair[1]); + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid command characters in mapping"); + } + + try { + commandMap.put(Integer.parseInt(kvPair[0]), kvPair[1]); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Unable to parse integer in mapping", e); + } + } + } + + @Nullable + public String getCommand(int key) { + return commandMap.get(key); + } + + public int size() { + return commandMap.size(); + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/KeypadMessage.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/KeypadMessage.java new file mode 100644 index 0000000000000..75869792a894c --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/KeypadMessage.java @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link KeypadMessage} class represents a parsed keypad (KPM) message. + * Based partly on code from the OH1 alarmdecoder binding by Bernd Pfrommer. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class KeypadMessage extends ADMessage { + + // Example: [00110011000000003A--],010,[f70700000010808c18020000000000],"ARMED ***STAY** ZONE BYPASSED " + + public static final int BIT_READY = 17; + public static final int BIT_ARMEDAWAY = 16; + public static final int BIT_ARMEDHOME = 15; + public static final int BIT_BACKLIGHT = 14; + public static final int BIT_PRORGAM = 13; + public static final int BIT_BYPASSED = 9; + public static final int BIT_ACPOWER = 8; + public static final int BIT_CHIME = 7; + public static final int BIT_ALARMOCCURRED = 6; + public static final int BIT_ALARM = 5; + public static final int BIT_LOWBAT = 4; + public static final int BIT_DELAYOFF = 3; + public static final int BIT_FIRE = 2; + public static final int BIT_SYSFAULT = 1; + public static final int BIT_PERIMETER = 0; + + public final String bitField; + public final int numericCode; + public final String rawData; + public final String alphaMessage; + public final int nbeeps; + public final int status; + + private final int upper; + private final int lower; + + public KeypadMessage(String message) throws IllegalArgumentException { + super(message); + List parts = splitMsg(message); + + if (parts.size() != 4) { + throw new IllegalArgumentException("Invalid number of parts in keypad message"); + } + if (parts.get(0).length() != 22) { + throw new IllegalArgumentException("Invalid field length in keypad message"); + } + + bitField = parts.get(0); + rawData = parts.get(2); + alphaMessage = parts.get(3).replaceAll("^\"|\"$", ""); + + try { + int numeric = 0; + try { + numeric = Integer.parseInt(parts.get(1)); + } catch (NumberFormatException e) { + numeric = Integer.parseInt(parts.get(1), 16); + } + this.numericCode = numeric; + + this.upper = Integer.parseInt(parts.get(0).substring(1, 6), 2); + this.nbeeps = Integer.parseInt(parts.get(0).substring(6, 7)); + this.lower = Integer.parseInt(parts.get(0).substring(7, 17), 2); + this.status = ((upper & 0x1F) << 13) | ((nbeeps & 0x3) << 10) | lower; + + } catch (NumberFormatException e) { + throw new IllegalArgumentException("keypad msg contains invalid number: " + e.getMessage(), e); + } + } + + public int getZone() { + return numericCode; + } + + /** + * Returns a string containing the keypad text + */ + public String getText() { + return alphaMessage; + } + + /** + * Returns the value of an individual bit in the status field + * + * @param bit status field bit to test + * @return true if bit is 1, false if bit is 0 + */ + public boolean getStatus(int bit) { + int v = (status >> bit) & 0x1; + return (v == 0) ? false : true; + } + + /** + * Returns true if the READY status bit is set + */ + public boolean panelClear() { + return ((status & (1 << BIT_READY)) != 0); + } + + /** + * Returns a string containing the address mask of the message in hex + */ + public String getAddressMask() { + return rawData.substring(3, 11); + } + + /** + * Returns an int containing the address mask of the message + */ + public int getIntAddressMask() { + return Integer.parseInt(getAddressMask(), 16); + } + + /** + * Compares two KeypadMessage objects + * + * @param obj KeypadMessage to compare against + * @return true if messages are equal, false if obj is null, messages are not equal, or obj is not a KeypadMessage + * object. + */ + @Override + public boolean equals(@Nullable Object obj) { + if (obj == null) { + return false; + } else if (this == obj) { + return true; + } else if (obj instanceof KeypadMessage) { + KeypadMessage other = (KeypadMessage) obj; + return this.message.equals(other.message); + } else { + return false; + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/LRRMessage.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/LRRMessage.java new file mode 100644 index 0000000000000..18284481e23c8 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/LRRMessage.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link LRRMessage} class represents a parsed LRR message. + * Based partly on code from the OH1 alarmdecoder binding by Bernd Pfrommer and Lucky Mallari. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class LRRMessage extends ADMessage { + + // Example: !LRR:012,1,CID_1441,ff + // or: !LRR:000,1,ARM_AWAY + + /** Event data contains user number or zone number for the event */ + public final String eventData; + + /** Partition event applies to. 0 means all partitions. */ + public final int partition; + + /** CID message for event as defined in SIA DC-05-1999.09 standard */ + public final String cidMessage; + + /** Report code */ + public final String reportCode; + + public LRRMessage(String message) throws IllegalArgumentException { + super(message); + + String topLevel[] = message.split(":"); + if (topLevel.length != 2) { + throw new IllegalArgumentException("multiple colons in LRR message"); + } + + List parts = splitMsg(topLevel[1]); + + // Apparently the 4th part of the LRR message may not be included depending on version + if (parts.size() < 3 || parts.size() > 4) { + throw new IllegalArgumentException("Invalid number of parts in LRR message"); + } + + eventData = parts.get(0); + cidMessage = parts.get(2); + reportCode = parts.size() == 4 ? parts.get(3) : ""; + + try { + partition = Integer.parseInt(parts.get(1)); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("LRR msg contains invalid number: " + e.getMessage(), e); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/RFXMessage.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/RFXMessage.java new file mode 100644 index 0000000000000..9aa60ec29a9c4 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/RFXMessage.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link RFXMessage} class represents a parsed RF zone (RFX) message. + * Based partly on code from the OH1 alarmdecoder binding by Bernd Pfrommer. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class RFXMessage extends ADMessage { + + // Example: !RFX:0180036,80 + + public static final int BIT_LOWBAT = 0x02; + public static final int BIT_SUPER = 0x04; + public static final int BIT_LOOP3 = 0x10; + public static final int BIT_LOOP2 = 0x20; + public static final int BIT_LOOP4 = 0x40; + public static final int BIT_LOOP1 = 0x80; + + /** Address serial number */ + public final int serial; + + /** Message data */ + public final int data; + + public RFXMessage(String message) throws IllegalArgumentException { + super(message); + + String topLevel[] = message.split(":"); + if (topLevel.length != 2) { + throw new IllegalArgumentException("Multiple colons found in RFX message"); + } + + List parts = splitMsg(topLevel[1]); + + if (parts.size() != 2) { + throw new IllegalArgumentException("Invalid number of parts in RFX message"); + } + + try { + serial = Integer.parseInt(parts.get(0)); + data = Integer.parseInt(parts.get(1), 16); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("RFX message contains invalid number: " + e.getMessage(), e); + } + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/VersionMessage.java b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/VersionMessage.java new file mode 100644 index 0000000000000..fc98dfa522e7b --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/java/org/openhab/binding/alarmdecoder/internal/protocol/VersionMessage.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.alarmdecoder.internal.protocol; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link VersionMessage} class represents a parsed VER message. + * + * @author Bob Adair - Initial contribution + */ +@NonNullByDefault +public class VersionMessage extends ADMessage { + + // Example: !VER:ffffffff,V2.2a.8.2,TX;RX;SM;VZ;RF;ZX;RE;AU;3X;CG;DD;MF;LR;KE;MK;CB;DS;ER + + /** Serial number */ + public final String serial; + + /** Firmware version */ + public final String version; + + /** Firmware capabilities */ + public final String capabilities; + + public VersionMessage(String message) throws IllegalArgumentException { + super(message); + + String topLevel[] = message.split(":"); + if (topLevel.length != 2) { + throw new IllegalArgumentException("Multiple colons found in VER message"); + } + + List parts = splitMsg(topLevel[1]); + + if (parts.size() != 3) { + throw new IllegalArgumentException("Invalid number of parts in VER message"); + } + + serial = parts.get(0); + version = parts.get(1); + capabilities = parts.get(2); + } +} diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.alarmdecoder/src/main/resources/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..798a34002f0e1 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/resources/ESH-INF/binding/binding.xml @@ -0,0 +1,11 @@ + + + + Alarm Decoder Binding + This binding is for the Nu Tech Alarm Decoder, used for interfacing with Ademco/Honeywell and DSC alarm + systems. + Bob Adair, Bill Forsyth + + diff --git a/bundles/org.openhab.binding.alarmdecoder/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.alarmdecoder/src/main/resources/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..9124605542f77 --- /dev/null +++ b/bundles/org.openhab.binding.alarmdecoder/src/main/resources/ESH-INF/thing/thing-types.xml @@ -0,0 +1,327 @@ + + + + + + + Nu Tech Alarm Decoder IP Bridge + + Nu Tech Software Solutions + + + + + + network-address + The hostname or IP address of the Alarm Decoder device + + + + TCP port number for the Alarm Decoder connection + 10000 + + + + Enable automatic discovery of zones and RF zones + false + + + + The period in minutes that the handler will wait between connection attempts and checks + minutes + 2 + true + + + + The period in minutes after which the connection will be reset if no valid messages have been received. + Set to 0 to disable. + minutes + 5 + true + + + + + + + Nu Tech Alarm Decoder Serial Bridge + + Nu Tech Software Solutions + + + + + + serial-port + false + The name of the serial port used to connect to the Alarm Decoder device + + + + 115200 + Speed of the serial connection + + + + Enable automatic discovery of zones and RF zones + false + + + + + + + + + + + + + Alarm Decoder REL or EXP zone + + + + + + id + + + + + + + + + + + + + + + + + + + + Alarm Decoder RFX zone + + + + + + + + + + + + + + + + + + + + + + + serial + + + + + Serial number of the RF zone + + + + + + + + + + + + + Alarm Decoder keypad thing + + + + + + + + + + + + + + + + + + + + + + + + + + Number of beeps for message + + + + + + + + + + + + + Alarm has occurred in the past + + + + Alarm is currently sounding + + + + + + + + + + + + + + + + + + + + + + + + + + + + Keypad address mask + + + + Allow keypad commands to be sent to the alarm system from openHAB. Enabling this means the alarm system + will be only as secure as your openHAB system. + false + + + + When disarmed, automatically send * character to obtain zone fault information. + false + + + + Comma separated list of key/value pairs mapping integers to command strings for intcommand channel. + 0=0,1=1,2=2,3=3,4=4,5=5,6=6,7=7,8=8,9=9,10=*,11=# + true + + + + + + + + + + + + + + Long range radio message handler + + + + + Partition number (0 = System) + + + + CID event data (user or zone) + + + + SIA Contact ID Protocol message + + + + CID report code + + + + + + + Partition for which to receive LRR events (0=All) + 0 + + + + + + + + + Contact + + Switch + + + + + + Switch + + Switch + + + + + + Number + + Number + + + + + + String + + + + + + + String + + + + + + Number + + + diff --git a/bundles/org.openhab.binding.allplay/pom.xml b/bundles/org.openhab.binding.allplay/pom.xml index bf7c024df9540..aae52deff3f24 100644 --- a/bundles/org.openhab.binding.allplay/pom.xml +++ b/bundles/org.openhab.binding.allplay/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.allplay diff --git a/bundles/org.openhab.binding.allplay/src/main/feature/feature.xml b/bundles/org.openhab.binding.allplay/src/main/feature/feature.xml index 5215b1397b52a..1660ef9ae98eb 100644 --- a/bundles/org.openhab.binding.allplay/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.allplay/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.allplay/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.allplay/${project.version} + diff --git a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/AllPlayAudioSink.java b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/AllPlayAudioSink.java index f33e5c8abae4d..311c0f7ea6c68 100644 --- a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/AllPlayAudioSink.java +++ b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/AllPlayAudioSink.java @@ -145,5 +145,4 @@ public AllPlayCallbackException(String message) { super(message); } } - } diff --git a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/AllPlayHandlerFactory.java b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/AllPlayHandlerFactory.java index 62938017785e1..e82e496b048eb 100644 --- a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/AllPlayHandlerFactory.java +++ b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/AllPlayHandlerFactory.java @@ -158,5 +158,4 @@ private String assembleCallbackUrl() { } return callbackUrl; } - } diff --git a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/discovery/AllPlaySpeakerDiscoveryService.java b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/discovery/AllPlaySpeakerDiscoveryService.java index 0f1c22ab8268e..68a69f6cc667c 100644 --- a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/discovery/AllPlaySpeakerDiscoveryService.java +++ b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/discovery/AllPlaySpeakerDiscoveryService.java @@ -106,7 +106,5 @@ public void onSpeakerAnnounced(Speaker speaker) { DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) .withRepresentationProperty(AllPlayBindingConstants.DEVICE_ID).withLabel(speaker.getName()).build(); thingDiscovered(discoveryResult); - } - } diff --git a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java index 85f7985bfa4e2..20af17dc5d607 100644 --- a/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java +++ b/bundles/org.openhab.binding.allplay/src/main/java/org/openhab/binding/allplay/internal/handler/AllPlayHandler.java @@ -43,6 +43,7 @@ import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.UnDefType; +import org.eclipse.smarthome.io.net.http.HttpUtil; import org.openhab.binding.allplay.internal.AllPlayBindingConstants; import org.openhab.binding.allplay.internal.AllPlayBindingProperties; import org.slf4j.Logger; @@ -398,7 +399,6 @@ public void onPlaylistChanged() { public void onLoopModeChanged(LoopMode loopMode) { logger.debug("{}: LoopMode changed to {}", speaker.getName(), loopMode); updateState(LOOP_MODE, new StringType(loopMode.toString())); - } @Override @@ -496,7 +496,10 @@ private void updateCoverArtState(String coverArtUrl) { logger.debug("{}: Cover art URL changed to {}", speaker.getName(), coverArtUrl); updateState(COVER_ART_URL, new StringType(coverArtUrl)); if (!coverArtUrl.isEmpty()) { - updateState(COVER_ART, new RawType(getRawDataFromUrl(coverArtUrl))); + byte[] bytes = getRawDataFromUrl(coverArtUrl); + String contentType = HttpUtil.guessContentTypeFromData(bytes); + updateState(COVER_ART, new RawType(bytes, + contentType == null || contentType.isEmpty() ? RawType.DEFAULT_MIME_TYPE : contentType)); } else { updateState(COVER_ART, UnDefType.NULL); } diff --git a/bundles/org.openhab.binding.allplay/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.allplay/src/main/resources/ESH-INF/binding/binding.xml index b8c2197b9cc8a..7f5520336ffac 100644 --- a/bundles/org.openhab.binding.allplay/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.allplay/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - AllPlay Binding diff --git a/bundles/org.openhab.binding.allplay/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.allplay/src/main/resources/ESH-INF/thing/thing-types.xml index a2b3e6a9cd593..33f8a72e3ed64 100644 --- a/bundles/org.openhab.binding.allplay/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.allplay/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -8,28 +9,28 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.amazondashbutton/pom.xml b/bundles/org.openhab.binding.amazondashbutton/pom.xml index 689eaf48fbbe9..f07d20da3c201 100644 --- a/bundles/org.openhab.binding.amazondashbutton/pom.xml +++ b/bundles/org.openhab.binding.amazondashbutton/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.amazondashbutton diff --git a/bundles/org.openhab.binding.amazondashbutton/src/main/feature/feature.xml b/bundles/org.openhab.binding.amazondashbutton/src/main/feature/feature.xml index 1947c72512e69..1c51e2dda30d6 100644 --- a/bundles/org.openhab.binding.amazondashbutton/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.amazondashbutton/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-runtime-jna - mvn:org.openhab.addons.bundles/org.openhab.binding.amazondashbutton/${project.version} - + + openhab-runtime-base + openhab-runtime-jna + mvn:org.openhab.addons.bundles/org.openhab.binding.amazondashbutton/${project.version} + diff --git a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/AmazonDashButtonBindingConstants.java b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/AmazonDashButtonBindingConstants.java index f0bbd0088c90d..5ca721a602dc3 100644 --- a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/AmazonDashButtonBindingConstants.java +++ b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/AmazonDashButtonBindingConstants.java @@ -36,5 +36,4 @@ public class AmazonDashButtonBindingConstants { public static final String PROPERTY_MAC_ADDRESS = "macAddress"; public static final String PROPERTY_NETWORK_INTERFACE_NAME = "pcapNetworkInterfaceName"; public static final String PROPERTY_PACKET_INTERVAL = "packetInterval"; - } diff --git a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/config/AmazonDashButtonConfigOptionProvider.java b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/config/AmazonDashButtonConfigOptionProvider.java index 8ed12afcac3cc..82a362bdbce7f 100644 --- a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/config/AmazonDashButtonConfigOptionProvider.java +++ b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/config/AmazonDashButtonConfigOptionProvider.java @@ -96,5 +96,4 @@ private String getLabel(PcapNetworkInterfaceWrapper pcapNetworkInterface) { } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/discovery/AmazonDashButtonDiscoveryService.java b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/discovery/AmazonDashButtonDiscoveryService.java index 736966477d2f7..a324daac25186 100644 --- a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/discovery/AmazonDashButtonDiscoveryService.java +++ b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/discovery/AmazonDashButtonDiscoveryService.java @@ -230,5 +230,4 @@ public void packetCaptured(MacAddress macAddress) { logger.debug("Started capturing for {}.", interfaceName); } } - } diff --git a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/pcap/PcapNetworkInterfaceService.java b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/pcap/PcapNetworkInterfaceService.java index 7808850fb1ad8..5ef84a0e5899c 100644 --- a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/pcap/PcapNetworkInterfaceService.java +++ b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/pcap/PcapNetworkInterfaceService.java @@ -188,5 +188,4 @@ private void updatePollingState() { future = scheduler.scheduleWithFixedDelay(pollingRunnable, 0, 2, TimeUnit.SECONDS); } } - } diff --git a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/pcap/PcapNetworkInterfaceWrapper.java b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/pcap/PcapNetworkInterfaceWrapper.java index 1f73fd9876436..40037fab737c9 100644 --- a/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/pcap/PcapNetworkInterfaceWrapper.java +++ b/bundles/org.openhab.binding.amazondashbutton/src/main/java/org/openhab/binding/amazondashbutton/internal/pcap/PcapNetworkInterfaceWrapper.java @@ -92,5 +92,4 @@ public int hashCode() { public String toString() { return pcapNetworkInterface.toString(); } - } diff --git a/bundles/org.openhab.binding.amazonechocontrol/pom.xml b/bundles/org.openhab.binding.amazonechocontrol/pom.xml index e9966b098970a..22724d0109799 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/pom.xml +++ b/bundles/org.openhab.binding.amazonechocontrol/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.amazonechocontrol diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/feature/feature.xml b/bundles/org.openhab.binding.amazonechocontrol/src/main/feature/feature.xml index 038bb5321e4ce..8b54251981d87 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.amazonechocontrol/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.amazonechocontrol/${project.version} + diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java index c1229f4e94b57..9cef8ad28a221 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlBindingConstants.java @@ -1,112 +1,112 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.amazonechocontrol.internal; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; - -/** - * The {@link AmazonEchoControlBindingConstants} class defines common constants, which are - * used across the whole binding. - * - * @author Michael Geramb - Initial contribution - */ -@NonNullByDefault -public class AmazonEchoControlBindingConstants { - - public static final String BINDING_ID = "amazonechocontrol"; - public static final String BINDING_NAME = "Amazon Echo Control"; - - // List of all Thing Type UIDs - public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account"); - public static final ThingTypeUID THING_TYPE_ECHO = new ThingTypeUID(BINDING_ID, "echo"); - public static final ThingTypeUID THING_TYPE_ECHO_SPOT = new ThingTypeUID(BINDING_ID, "echospot"); - public static final ThingTypeUID THING_TYPE_ECHO_SHOW = new ThingTypeUID(BINDING_ID, "echoshow"); - public static final ThingTypeUID THING_TYPE_ECHO_WHA = new ThingTypeUID(BINDING_ID, "wha"); - - public static final ThingTypeUID THING_TYPE_FLASH_BRIEFING_PROFILE = new ThingTypeUID(BINDING_ID, - "flashbriefingprofile"); - - public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>( - Arrays.asList(THING_TYPE_ACCOUNT, THING_TYPE_ECHO, THING_TYPE_ECHO_SPOT, THING_TYPE_ECHO_SHOW, - THING_TYPE_ECHO_WHA, THING_TYPE_FLASH_BRIEFING_PROFILE)); - - // List of all Channel ids - public static final String CHANNEL_PLAYER = "player"; - public static final String CHANNEL_VOLUME = "volume"; - public static final String CHANNEL_EQUALIZER_TREBLE = "equalizerTreble"; - public static final String CHANNEL_EQUALIZER_MIDRANGE = "equalizerMidrange"; - public static final String CHANNEL_EQUALIZER_BASS = "equalizerBass"; - public static final String CHANNEL_ERROR = "error"; - public static final String CHANNEL_SHUFFLE = "shuffle"; - public static final String CHANNEL_LOOP = "loop"; - public static final String CHANNEL_IMAGE_URL = "imageUrl"; - public static final String CHANNEL_TITLE = "title"; - public static final String CHANNEL_SUBTITLE1 = "subtitle1"; - public static final String CHANNEL_SUBTITLE2 = "subtitle2"; - public static final String CHANNEL_PROVIDER_DISPLAY_NAME = "providerDisplayName"; - public static final String CHANNEL_BLUETOOTH_MAC = "bluetoothMAC"; - public static final String CHANNEL_BLUETOOTH = "bluetooth"; - public static final String CHANNEL_BLUETOOTH_DEVICE_NAME = "bluetoothDeviceName"; - public static final String CHANNEL_RADIO_STATION_ID = "radioStationId"; - public static final String CHANNEL_RADIO = "radio"; - public static final String CHANNEL_AMAZON_MUSIC_TRACK_ID = "amazonMusicTrackId"; - public static final String CHANNEL_AMAZON_MUSIC = "amazonMusic"; - public static final String CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID = "amazonMusicPlayListId"; - public static final String CHANNEL_TEXT_TO_SPEECH = "textToSpeech"; - public static final String CHANNEL_TEXT_TO_SPEECH_VOLUME = "textToSpeechVolume"; - public static final String CHANNEL_REMIND = "remind"; - public static final String CHANNEL_PLAY_ALARM_SOUND = "playAlarmSound"; - public static final String CHANNEL_START_ROUTINE = "startRoutine"; - public static final String CHANNEL_MUSIC_PROVIDER_ID = "musicProviderId"; - public static final String CHANNEL_PLAY_MUSIC_VOICE_COMMAND = "playMusicVoiceCommand"; - public static final String CHANNEL_START_COMMAND = "startCommand"; - public static final String CHANNEL_LAST_VOICE_COMMAND = "lastVoiceCommand"; - public static final String CHANNEL_MEDIA_PROGRESS = "mediaProgress"; - public static final String CHANNEL_MEDIA_LENGTH = "mediaLength"; - public static final String CHANNEL_MEDIA_PROGRESS_TIME = "mediaProgressTime"; - public static final String CHANNEL_ASCENDING_ALARM = "ascendingAlarm"; - public static final String CHANNEL_NOTIFICATION_VOLUME = "notificationVolume"; - public static final String CHANNEL_NEXT_REMINDER = "nextReminder"; - public static final String CHANNEL_NEXT_ALARM = "nextAlarm"; - public static final String CHANNEL_NEXT_MUSIC_ALARM = "nextMusicAlarm"; - public static final String CHANNEL_NEXT_TIMER = "nextTimer"; - - public static final String CHANNEL_SAVE = "save"; - public static final String CHANNEL_ACTIVE = "active"; - public static final String CHANNEL_PLAY_ON_DEVICE = "playOnDevice"; - - // List of channel Type UIDs - public static final ChannelTypeUID CHANNEL_TYPE_BLUETHOOTH_MAC = new ChannelTypeUID(BINDING_ID, "bluetoothMAC"); - public static final ChannelTypeUID CHANNEL_TYPE_AMAZON_MUSIC_PLAY_LIST_ID = new ChannelTypeUID(BINDING_ID, - "amazonMusicPlayListId"); - public static final ChannelTypeUID CHANNEL_TYPE_PLAY_ALARM_SOUND = new ChannelTypeUID(BINDING_ID, "playAlarmSound"); - public static final ChannelTypeUID CHANNEL_TYPE_CHANNEL_PLAY_ON_DEVICE = new ChannelTypeUID(BINDING_ID, - "playOnDevice"); - public static final ChannelTypeUID CHANNEL_TYPE_MUSIC_PROVIDER_ID = new ChannelTypeUID(BINDING_ID, - "musicProviderId"); - public static final ChannelTypeUID CHANNEL_TYPE_START_COMMAND = new ChannelTypeUID(BINDING_ID, "startCommand"); - - // List of all Properties - public static final String DEVICE_PROPERTY_SERIAL_NUMBER = "serialNumber"; - public static final String DEVICE_PROPERTY_FAMILY = "deviceFamily"; - public static final String DEVICE_PROPERTY_FLASH_BRIEFING_PROFILE = "configurationJson"; - - // Other - public static final String FLASH_BRIEFING_COMMAND_PREFIX = "FlashBriefing."; -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.amazonechocontrol.internal; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; + +/** + * The {@link AmazonEchoControlBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Michael Geramb - Initial contribution + */ +@NonNullByDefault +public class AmazonEchoControlBindingConstants { + + public static final String BINDING_ID = "amazonechocontrol"; + public static final String BINDING_NAME = "Amazon Echo Control"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account"); + public static final ThingTypeUID THING_TYPE_ECHO = new ThingTypeUID(BINDING_ID, "echo"); + public static final ThingTypeUID THING_TYPE_ECHO_SPOT = new ThingTypeUID(BINDING_ID, "echospot"); + public static final ThingTypeUID THING_TYPE_ECHO_SHOW = new ThingTypeUID(BINDING_ID, "echoshow"); + public static final ThingTypeUID THING_TYPE_ECHO_WHA = new ThingTypeUID(BINDING_ID, "wha"); + + public static final ThingTypeUID THING_TYPE_FLASH_BRIEFING_PROFILE = new ThingTypeUID(BINDING_ID, + "flashbriefingprofile"); + + public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>( + Arrays.asList(THING_TYPE_ACCOUNT, THING_TYPE_ECHO, THING_TYPE_ECHO_SPOT, THING_TYPE_ECHO_SHOW, + THING_TYPE_ECHO_WHA, THING_TYPE_FLASH_BRIEFING_PROFILE)); + + // List of all Channel ids + public static final String CHANNEL_PLAYER = "player"; + public static final String CHANNEL_VOLUME = "volume"; + public static final String CHANNEL_EQUALIZER_TREBLE = "equalizerTreble"; + public static final String CHANNEL_EQUALIZER_MIDRANGE = "equalizerMidrange"; + public static final String CHANNEL_EQUALIZER_BASS = "equalizerBass"; + public static final String CHANNEL_ERROR = "error"; + public static final String CHANNEL_SHUFFLE = "shuffle"; + public static final String CHANNEL_LOOP = "loop"; + public static final String CHANNEL_IMAGE_URL = "imageUrl"; + public static final String CHANNEL_TITLE = "title"; + public static final String CHANNEL_SUBTITLE1 = "subtitle1"; + public static final String CHANNEL_SUBTITLE2 = "subtitle2"; + public static final String CHANNEL_PROVIDER_DISPLAY_NAME = "providerDisplayName"; + public static final String CHANNEL_BLUETOOTH_MAC = "bluetoothMAC"; + public static final String CHANNEL_BLUETOOTH = "bluetooth"; + public static final String CHANNEL_BLUETOOTH_DEVICE_NAME = "bluetoothDeviceName"; + public static final String CHANNEL_RADIO_STATION_ID = "radioStationId"; + public static final String CHANNEL_RADIO = "radio"; + public static final String CHANNEL_AMAZON_MUSIC_TRACK_ID = "amazonMusicTrackId"; + public static final String CHANNEL_AMAZON_MUSIC = "amazonMusic"; + public static final String CHANNEL_AMAZON_MUSIC_PLAY_LIST_ID = "amazonMusicPlayListId"; + public static final String CHANNEL_TEXT_TO_SPEECH = "textToSpeech"; + public static final String CHANNEL_TEXT_TO_SPEECH_VOLUME = "textToSpeechVolume"; + public static final String CHANNEL_REMIND = "remind"; + public static final String CHANNEL_PLAY_ALARM_SOUND = "playAlarmSound"; + public static final String CHANNEL_START_ROUTINE = "startRoutine"; + public static final String CHANNEL_MUSIC_PROVIDER_ID = "musicProviderId"; + public static final String CHANNEL_PLAY_MUSIC_VOICE_COMMAND = "playMusicVoiceCommand"; + public static final String CHANNEL_START_COMMAND = "startCommand"; + public static final String CHANNEL_LAST_VOICE_COMMAND = "lastVoiceCommand"; + public static final String CHANNEL_MEDIA_PROGRESS = "mediaProgress"; + public static final String CHANNEL_MEDIA_LENGTH = "mediaLength"; + public static final String CHANNEL_MEDIA_PROGRESS_TIME = "mediaProgressTime"; + public static final String CHANNEL_ASCENDING_ALARM = "ascendingAlarm"; + public static final String CHANNEL_NOTIFICATION_VOLUME = "notificationVolume"; + public static final String CHANNEL_NEXT_REMINDER = "nextReminder"; + public static final String CHANNEL_NEXT_ALARM = "nextAlarm"; + public static final String CHANNEL_NEXT_MUSIC_ALARM = "nextMusicAlarm"; + public static final String CHANNEL_NEXT_TIMER = "nextTimer"; + + public static final String CHANNEL_SAVE = "save"; + public static final String CHANNEL_ACTIVE = "active"; + public static final String CHANNEL_PLAY_ON_DEVICE = "playOnDevice"; + + // List of channel Type UIDs + public static final ChannelTypeUID CHANNEL_TYPE_BLUETHOOTH_MAC = new ChannelTypeUID(BINDING_ID, "bluetoothMAC"); + public static final ChannelTypeUID CHANNEL_TYPE_AMAZON_MUSIC_PLAY_LIST_ID = new ChannelTypeUID(BINDING_ID, + "amazonMusicPlayListId"); + public static final ChannelTypeUID CHANNEL_TYPE_PLAY_ALARM_SOUND = new ChannelTypeUID(BINDING_ID, "playAlarmSound"); + public static final ChannelTypeUID CHANNEL_TYPE_CHANNEL_PLAY_ON_DEVICE = new ChannelTypeUID(BINDING_ID, + "playOnDevice"); + public static final ChannelTypeUID CHANNEL_TYPE_MUSIC_PROVIDER_ID = new ChannelTypeUID(BINDING_ID, + "musicProviderId"); + public static final ChannelTypeUID CHANNEL_TYPE_START_COMMAND = new ChannelTypeUID(BINDING_ID, "startCommand"); + + // List of all Properties + public static final String DEVICE_PROPERTY_SERIAL_NUMBER = "serialNumber"; + public static final String DEVICE_PROPERTY_FAMILY = "deviceFamily"; + public static final String DEVICE_PROPERTY_FLASH_BRIEFING_PROFILE = "configurationJson"; + + // Other + public static final String FLASH_BRIEFING_COMMAND_PREFIX = "FlashBriefing."; +} diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java index 47242988769f2..69bb3d816e778 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/AmazonEchoControlHandlerFactory.java @@ -1,178 +1,177 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.amazonechocontrol.internal; - -import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*; - -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.config.discovery.DiscoveryService; -import org.eclipse.smarthome.core.storage.Storage; -import org.eclipse.smarthome.core.storage.StorageService; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; -import org.openhab.binding.amazonechocontrol.internal.discovery.AmazonEchoDiscovery; -import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler; -import org.openhab.binding.amazonechocontrol.internal.handler.EchoHandler; -import org.openhab.binding.amazonechocontrol.internal.handler.FlashBriefingProfileHandler; -import org.osgi.framework.ServiceRegistration; -import org.osgi.service.component.ComponentContext; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; -import org.osgi.service.component.annotations.ReferenceCardinality; -import org.osgi.service.component.annotations.ReferencePolicy; -import org.osgi.service.http.HttpService; - -import com.google.gson.Gson; - -/** - * The {@link AmazonEchoControlHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Michael Geramb - Initial contribution - */ -@Component(service = ThingHandlerFactory.class, configurationPid = "binding.amazonechocontrol") -@NonNullByDefault -public class AmazonEchoControlHandlerFactory extends BaseThingHandlerFactory { - - private final Map> discoveryServiceRegistrations = new HashMap<>(); - - @Nullable - HttpService httpService; - @Nullable - StorageService storageService; - @Nullable - BindingServlet bindingServlet; - @Nullable - Gson gson; - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected void activate(ComponentContext componentContext) { - super.activate(componentContext); - HttpService httpService = this.httpService; - if (bindingServlet == null && httpService != null) { - bindingServlet = new BindingServlet(httpService); - } - } - - @Override - protected void deactivate(ComponentContext componentContext) { - BindingServlet bindingServlet = this.bindingServlet; - this.bindingServlet = null; - if (bindingServlet != null) { - bindingServlet.dispose(); - } - super.deactivate(componentContext); - } - - @Override - protected @Nullable ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - HttpService httpService = this.httpService; - if (httpService == null) { - return null; - } - StorageService storageService = this.storageService; - if (storageService == null) { - return null; - } - Gson gson = this.gson; - if (gson == null) - { - gson = new Gson(); - this.gson = gson; - } - - if (thingTypeUID.equals(THING_TYPE_ACCOUNT)) { - Storage storage = storageService.getStorage(thing.getUID().toString(), - String.class.getClassLoader()); - AccountHandler bridgeHandler = new AccountHandler((Bridge) thing, httpService, storage, gson); - registerDiscoveryService(bridgeHandler); - BindingServlet bindingServlet = this.bindingServlet; - if (bindingServlet != null) { - bindingServlet.addAccountThing(thing); - } - return bridgeHandler; - } - if (thingTypeUID.equals(THING_TYPE_FLASH_BRIEFING_PROFILE)) { - Storage storage = storageService.getStorage(thing.getUID().toString(), - String.class.getClassLoader()); - return new FlashBriefingProfileHandler(thing, storage); - } - if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { - return new EchoHandler(thing, gson); - } - return null; - } - - private synchronized void registerDiscoveryService(AccountHandler bridgeHandler) { - AmazonEchoDiscovery discoveryService = new AmazonEchoDiscovery(bridgeHandler); - discoveryService.activate(); - this.discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), bundleContext - .registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>())); - } - - @Override - protected synchronized void removeHandler(ThingHandler thingHandler) { - if (thingHandler instanceof AccountHandler) { - BindingServlet bindingServlet = this.bindingServlet; - if (bindingServlet != null) { - bindingServlet.removeAccountThing(thingHandler.getThing()); - } - - ServiceRegistration serviceReg = this.discoveryServiceRegistrations - .remove(thingHandler.getThing().getUID()); - if (serviceReg != null) { - // remove discovery service, if bridge handler is removed - AmazonEchoDiscovery service = (AmazonEchoDiscovery) bundleContext.getService(serviceReg.getReference()); - serviceReg.unregister(); - if (service != null) { - service.deactivate(); - } - } - } - } - - @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC) - protected void setHttpService(HttpService httpService) { - this.httpService = httpService; - } - - protected void unsetHttpService(HttpService httpService) { - this.httpService = null; - } - - @Reference - protected void setStorageService(StorageService storageService) { - this.storageService = storageService; - } - - protected void unsetStorageService(StorageService storageService) { - this.storageService = null; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.amazonechocontrol.internal; + +import static org.openhab.binding.amazonechocontrol.internal.AmazonEchoControlBindingConstants.*; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.core.storage.Storage; +import org.eclipse.smarthome.core.storage.StorageService; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.amazonechocontrol.internal.discovery.AmazonEchoDiscovery; +import org.openhab.binding.amazonechocontrol.internal.handler.AccountHandler; +import org.openhab.binding.amazonechocontrol.internal.handler.EchoHandler; +import org.openhab.binding.amazonechocontrol.internal.handler.FlashBriefingProfileHandler; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.osgi.service.http.HttpService; + +import com.google.gson.Gson; + +/** + * The {@link AmazonEchoControlHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Michael Geramb - Initial contribution + */ +@Component(service = ThingHandlerFactory.class, configurationPid = "binding.amazonechocontrol") +@NonNullByDefault +public class AmazonEchoControlHandlerFactory extends BaseThingHandlerFactory { + + private final Map> discoveryServiceRegistrations = new HashMap<>(); + + @Nullable + HttpService httpService; + @Nullable + StorageService storageService; + @Nullable + BindingServlet bindingServlet; + @Nullable + Gson gson; + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected void activate(ComponentContext componentContext) { + super.activate(componentContext); + HttpService httpService = this.httpService; + if (bindingServlet == null && httpService != null) { + bindingServlet = new BindingServlet(httpService); + } + } + + @Override + protected void deactivate(ComponentContext componentContext) { + BindingServlet bindingServlet = this.bindingServlet; + this.bindingServlet = null; + if (bindingServlet != null) { + bindingServlet.dispose(); + } + super.deactivate(componentContext); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + HttpService httpService = this.httpService; + if (httpService == null) { + return null; + } + StorageService storageService = this.storageService; + if (storageService == null) { + return null; + } + Gson gson = this.gson; + if (gson == null) { + gson = new Gson(); + this.gson = gson; + } + + if (thingTypeUID.equals(THING_TYPE_ACCOUNT)) { + Storage storage = storageService.getStorage(thing.getUID().toString(), + String.class.getClassLoader()); + AccountHandler bridgeHandler = new AccountHandler((Bridge) thing, httpService, storage, gson); + registerDiscoveryService(bridgeHandler); + BindingServlet bindingServlet = this.bindingServlet; + if (bindingServlet != null) { + bindingServlet.addAccountThing(thing); + } + return bridgeHandler; + } + if (thingTypeUID.equals(THING_TYPE_FLASH_BRIEFING_PROFILE)) { + Storage storage = storageService.getStorage(thing.getUID().toString(), + String.class.getClassLoader()); + return new FlashBriefingProfileHandler(thing, storage); + } + if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { + return new EchoHandler(thing, gson); + } + return null; + } + + private synchronized void registerDiscoveryService(AccountHandler bridgeHandler) { + AmazonEchoDiscovery discoveryService = new AmazonEchoDiscovery(bridgeHandler); + discoveryService.activate(); + this.discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), + bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>())); + } + + @Override + protected synchronized void removeHandler(ThingHandler thingHandler) { + if (thingHandler instanceof AccountHandler) { + BindingServlet bindingServlet = this.bindingServlet; + if (bindingServlet != null) { + bindingServlet.removeAccountThing(thingHandler.getThing()); + } + + ServiceRegistration serviceReg = this.discoveryServiceRegistrations + .remove(thingHandler.getThing().getUID()); + if (serviceReg != null) { + // remove discovery service, if bridge handler is removed + AmazonEchoDiscovery service = (AmazonEchoDiscovery) bundleContext.getService(serviceReg.getReference()); + serviceReg.unregister(); + if (service != null) { + service.deactivate(); + } + } + } + } + + @Reference(cardinality = ReferenceCardinality.MANDATORY, policy = ReferencePolicy.DYNAMIC) + protected void setHttpService(HttpService httpService) { + this.httpService = httpService; + } + + protected void unsetHttpService(HttpService httpService) { + this.httpService = null; + } + + @Reference + protected void setStorageService(StorageService storageService) { + this.storageService = storageService; + } + + protected void unsetStorageService(StorageService storageService) { + this.storageService = null; + } +} diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/WebSocketConnection.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/WebSocketConnection.java index ec996bfde5a43..5c64e94533afc 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/WebSocketConnection.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/WebSocketConnection.java @@ -409,7 +409,6 @@ public void onWebSocketBinary(byte @Nullable [] data, int offset, int len) { logger.debug("Handling of push notification failed", e); } } - } @Override @@ -426,7 +425,6 @@ public void onWebSocketClose(int code, @Nullable String reason) { public void onWebSocketError(@Nullable Throwable error) { logger.info("Web Socket error", error); WebSocketConnection.this.close(); - } public void sendPing() { @@ -555,7 +553,7 @@ void encode(byte[] data, long b, int offset, int len) { } byte[] encodePing() { - // MSG 0x00000065 0x0e414e47 f 0x00000001 0xbc2fbb5f 0x00000062 PIN� ��� ��RegularFABE + // MSG 0x00000065 0x0e414e47 f 0x00000001 0xbc2fbb5f 0x00000062 this.messageId++; String msg = "MSG 0x00000065 "; // Message-type and Channel = CHANNEL_FOR_HEARTBEAT; msg += this.encodeNumber(this.messageId) + " f 0x00000001 "; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandler.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandler.java index b24bb64594f48..1c947956975b4 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandler.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandler.java @@ -55,6 +55,5 @@ protected ChannelHandler(IAmazonThingHandler thingHandler, Gson gson) { protected @Nullable T parseJson(String json, Class type) throws JsonSyntaxException { return gson.fromJson(json, type); - } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandlerSendMessage.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandlerSendMessage.java index 75893ec405310..5d1be525be3bd 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandlerSendMessage.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/channelhandler/ChannelHandlerSendMessage.java @@ -124,5 +124,4 @@ static class Payload { public @Nullable String text; } } - } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/AccountHandler.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/AccountHandler.java index 5f70a4216f7e1..b7ef5d9207156 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/AccountHandler.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/handler/AccountHandler.java @@ -436,7 +436,6 @@ private void refreshNotifications(@Nullable JsonCommandPayloadPushNotificationCh for (EchoHandler child : echoHandlers) { child.updateNotifications(timeStamp, timeStampNow, pushPayload, notifications); } - } private void refreshData() { @@ -699,7 +698,6 @@ private void updateFlashBriefingProfiles(Connection currentConnection) { } catch (HttpException | JsonSyntaxException | IOException | URISyntaxException | ConnectionException e) { logger.warn("get flash briefing profiles fails", e); } - } @Override diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java index 7892ce1300ce3..321ab282bd21d 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonActivities.java @@ -49,7 +49,6 @@ public static class SourceDeviceId { public @Nullable String deviceAccountId; public @Nullable String deviceType; public @Nullable String serialNumber; - } public static class Description { @@ -57,7 +56,6 @@ public static class Description { public @Nullable String summary; public @Nullable String firstUtteranceId; public @Nullable String firstStreamId; - } public Description ParseDescription() { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementContent.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementContent.java index 9d94cd5d84f6d..c5a0386ea7834 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementContent.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonAnnouncementContent.java @@ -31,12 +31,10 @@ public class JsonAnnouncementContent { public static class Display { public @Nullable String title; public @Nullable String body; - } public static class Speak { public String type = "text"; public @Nullable String value; - } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java index db8d256ba6770..fef529fe76b39 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonBluetoothStates.java @@ -50,7 +50,6 @@ public static class PairedDevice { public @Nullable String deviceClass; public @Nullable String friendlyName; public @Nullable String @Nullable [] profiles; - } public static class BluetoothState { @@ -60,6 +59,5 @@ public static class BluetoothState { public boolean gadgetPaired; public boolean online; public @Nullable PairedDevice @Nullable [] pairedDeviceList; - } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushAudioPlayerState.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushAudioPlayerState.java index d33188b4372a4..0382ab2dcf578 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushAudioPlayerState.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonCommandPayloadPushAudioPlayerState.java @@ -27,5 +27,4 @@ public class JsonCommandPayloadPushAudioPlayerState extends JsonCommandPayloadPu public @Nullable Boolean error; public @Nullable String audioPlayerState; public @Nullable String errorMessage; - } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java index 37e074e3e4112..6d6733ff1d839 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonDevices.java @@ -33,7 +33,6 @@ public static class Device { public @Nullable String softwareVersion; public boolean online; public @Nullable String @Nullable [] capabilities; - } public @Nullable Device @Nullable [] devices; diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonEnabledFeeds.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonEnabledFeeds.java index b2976238f2f5e..b7764d3e787de 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonEnabledFeeds.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonEnabledFeeds.java @@ -23,5 +23,4 @@ @NonNullByDefault public class JsonEnabledFeeds { public @Nullable JsonFeed @Nullable [] enabledFeeds; - } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java index 559837d514779..dc357c3cac3c7 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonExchangeTokenResponse.java @@ -41,6 +41,5 @@ public static class Cookie { public @Nullable String Expires; public @Nullable Boolean HttpOnly; public @Nullable String Name; - } } diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java index dd106fd811623..a1ad89ecde326 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonPlayerState.java @@ -42,7 +42,6 @@ public static class InfoText { public @Nullable String subText1; public @Nullable String subText2; public @Nullable String title; - } public static class Provider { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java index 42e5d2d94e1e5..878ce532d9a3d 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppRequest.java @@ -43,7 +43,6 @@ public static class Cookies { public JsonWebSiteCookie @Nullable [] website_cookies; @Nullable public String domain = ".amazon.com"; - } public static class RegistrationData { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java index 8a7391b4c3fce..277e815d03b30 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/java/org/openhab/binding/amazonechocontrol/internal/jsons/JsonRegisterAppResponse.java @@ -59,7 +59,6 @@ public static class DeviceInfo { public String device_serial_number; @Nullable public String device_type; - } public static class CustomerInfo { diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/binding/binding.xml index b6c76c2bd9f9a..6036baea74da3 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/binding/binding.xml @@ -1,9 +1,11 @@ - - - - Amazon Echo Control Binding - Binding to control Amazon Echo devices (Alexa). This binding enables openHAB to control the volume, playing state, bluetooth connection of your amazon echo devices or allow to use it as TTS device. - Michael Geramb - - + + + + Amazon Echo Control Binding + Binding to control Amazon Echo devices (Alexa). This binding enables openHAB to control the volume, + playing state, bluetooth connection of your amazon echo devices or allow to use it as TTS device. + Michael Geramb + + diff --git a/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/thing/thing-types.xml index ae8b0443f071b..0618a2b93f8ce 100644 --- a/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.amazonechocontrol/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,485 +1,471 @@ - - - - - Amazon Account where the amazon echo devices are registered. - - - - - - - - - - Amazon Echo device (Amazon Echo, Amazon Echo Dot, Amazon Echo Plus...) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - serialNumber - - - - The serial number of the device from the Alexa app - - - - - - - - - Amazon Echo Spot device - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - serialNumber - - - - The serial number of the device from the Alexa app - - - - - - - - - Amazon Echo Show device - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - serialNumber - - - - The serial number of the device from the Alexa app - - - - - - - - - Amazon Multiroom Music - - - - - - - - - - - - - - - - - - serialNumber - - - - The serial number of the device from the Alexa app - - - - - - - - - - Store and load a flash briefing configuration - - - - - - - - Switch - - Save the current flash briefing configuration (Write only) - - - Switch - - Activate this flash briefing configuration - - - String - - Plays the briefing on the device (serial number or name, write only) - - - String - - Connected bluetooth device - - - - String - - Id of the radio station - - - String - - Speak the reminder and send a notification to the Alexa app - - - String - - The command which must be spoken to active the routing without the preceding "Alexa," (Write Only) - - - - String - - Plays an alarm sound - - - String - - Id of the amazon music track - - - Switch - - Amazon Music turned on - - - String - - Amazon Music play list id (Write only, no current state) - - - String - - Id of the playlist which was started with openHAB - - - String - - Name of music provider - - - - String - - MAC-Address of the bluetooth connected device - - - String - - Url of the album image or radio station logo - - - - String - - Title - - - - String - - Subtitle 1 - - - - String - - Subtitle 2 - - - - Switch - - Radio turned on - - - Switch - - Connect to last used device - - - Switch - - Loop - - - Switch - - Shuffle play - - - Player - - Music Player - - - Dimmer - - Volume of the sound - - - Number - - Equalizer Treble - - - - Number - - Equalizer Midrange - - - - Number - - Equalizer Bass - - - - String - - Music provider - - - String - - Voice command as text. E.g. 'Yesterday from the Beatles' (Write only) - - - String - - Sends a message to the Echo devices (Write only). - - - String - - Display the announcement message on the display (Write only). See in the tutorial section of the binding description to learn how it's possible to set the title and turn off the sound. - - - String - - Speak the text (Write only). It is possible to use plain text or SSML: <speak>I want to tell you a secret.<amazon:effect name="whispered">I am not a real human.</amazon:effect>.Can you believe it?</speak> - - - Dimmer - - Volume of the Speak channel. If 0, the current volume will be used. - - - String - - Last voice command spoken to the device. Writing to the channel starts voice output. - - - - Dimmer - - Media progress in percent - - - - Number:Time - - Media play time - - - - Number:Time - - Media length - - - - String - - Start information (Write only) - - - - - - - - - - - - - Dimmer - - Notification Volume - - - - Switch - - Ascending alarm up to the configured volume - - - - DateTime - - Next Reminder - - - - DateTime - - Next alarm - - - - DateTime - - Next music alarm - - - - DateTime - - Next timer - - - + + + + + Amazon Account where the amazon echo devices are registered. + + + + + + + + + + Amazon Echo device (Amazon Echo, Amazon Echo Dot, Amazon Echo Plus...) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + serialNumber + + + + The serial number of the device from the Alexa app + + + + + + + + + Amazon Echo Spot device + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + serialNumber + + + + The serial number of the device from the Alexa app + + + + + + + + + Amazon Echo Show device + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + serialNumber + + + + The serial number of the device from the Alexa app + + + + + + + + + Amazon Multiroom Music + + + + + + + + + + + + + + + + + + serialNumber + + + + The serial number of the device from the Alexa app + + + + + + + + + + Store and load a flash briefing configuration + + + + + + + + Switch + + Save the current flash briefing configuration (Write only) + + + Switch + + Activate this flash briefing configuration + + + String + + Plays the briefing on the device (serial number or name, write only) + + + String + + Connected bluetooth device + + + + String + + Id of the radio station + + + String + + Speak the reminder and send a notification to the Alexa app + + + String + + The command which must be spoken to active the routing without the preceding "Alexa," (Write Only) + + + + String + + Plays an alarm sound + + + String + + Id of the amazon music track + + + Switch + + Amazon Music turned on + + + String + + Amazon Music play list id (Write only, no current state) + + + String + + Id of the playlist which was started with openHAB + + + String + + Name of music provider + + + + String + + MAC-Address of the bluetooth connected device + + + String + + Url of the album image or radio station logo + + + + String + + Title + + + + String + + Subtitle 1 + + + + String + + Subtitle 2 + + + + Switch + + Radio turned on + + + Switch + + Connect to last used device + + + Switch + + Loop + + + Switch + + Shuffle play + + + Player + + Music Player + + + Dimmer + + Volume of the sound + + + Number + + Equalizer Treble + + + + Number + + Equalizer Midrange + + + + Number + + Equalizer Bass + + + + String + + Music provider + + + String + + Voice command as text. E.g. 'Yesterday from the Beatles' (Write only) + + + String + + Sends a message to the Echo devices (Write only). + + + String + + Display the announcement message on the display (Write only). See in the tutorial section of the binding + description to learn how it's possible to set the title and turn off the sound. + + + String + + Speak the text (Write only). It is possible to use plain text or SSML: <speak>I want to tell you a + secret.<amazon:effect name="whispered">I am not a real human.</amazon:effect>.Can you believe + it?</speak> + + + Dimmer + + Volume of the Speak channel. If 0, the current volume will be used. + + + String + + Last voice command spoken to the device. Writing to the channel starts voice output. + + + + Dimmer + + Media progress in percent + + + + Number:Time + + Media play time + + + + Number:Time + + Media length + + + + String + + Start information (Write only) + + + + + + + + + + + + + Dimmer + + Notification Volume + + + + Switch + + Ascending alarm up to the configured volume + + + + DateTime + + Next Reminder + + + + DateTime + + Next alarm + + + + DateTime + + Next music alarm + + + + DateTime + + Next timer + + + diff --git a/bundles/org.openhab.binding.ambientweather/pom.xml b/bundles/org.openhab.binding.ambientweather/pom.xml index 619685fe4576a..81935b417c679 100644 --- a/bundles/org.openhab.binding.ambientweather/pom.xml +++ b/bundles/org.openhab.binding.ambientweather/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.ambientweather diff --git a/bundles/org.openhab.binding.ambientweather/src/main/java/org/openhab/binding/ambientweather/internal/processor/Ws8482Processor.java b/bundles/org.openhab.binding.ambientweather/src/main/java/org/openhab/binding/ambientweather/internal/processor/Ws8482Processor.java index 4f7be14d2ac88..c108bf16de471 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/java/org/openhab/binding/ambientweather/internal/processor/Ws8482Processor.java +++ b/bundles/org.openhab.binding.ambientweather/src/main/java/org/openhab/binding/ambientweather/internal/processor/Ws8482Processor.java @@ -58,8 +58,8 @@ public void processWeatherData(AmbientWeatherStationHandler handler, String stat // Update the weather data channels handler.updateDate(channelGroupId, CH_OBSERVATION_TIME, data.date); handler.updateString(channelGroupId, CH_BATTERY_INDICATOR, data.battout); - handler.updateQuantity(channelGroupId, CH_TEMPERATURE, data.tempf, ImperialUnits.FAHRENHEIT); - handler.updateQuantity(channelGroupId, CH_HUMIDITY, data.humidity, SmartHomeUnits.PERCENT); + handler.updateQuantity(channelGroupId, CH_TEMPERATURE, data.tempinf, ImperialUnits.FAHRENHEIT); + handler.updateQuantity(channelGroupId, CH_HUMIDITY, data.humidityin, SmartHomeUnits.PERCENT); // Update the remote sensor channels remoteSensor.updateChannels(handler, jsonData); diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/config/bridge-config.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/config/bridge-config.xml index b7700982f44dc..5c3cccb479790 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/config/bridge-config.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/config/bridge-config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/config/station-config.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/config/station-config.xml index 3f8f31c13303f..a3a0fc6a40a70 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/config/station-config.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/config/station-config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/bridge.xml index bd26988812923..edb6c133e4e06 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,5 +1,6 @@ - @@ -7,6 +8,6 @@ Represents an account at Ambient Weather (ambientweather.net) - + diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/channel-group-types.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/channel-group-types.xml index 6d9310a214598..43f6f4c7a9cc1 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/channel-group-types.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/channel-group-types.xml @@ -1,5 +1,6 @@ - @@ -9,8 +10,8 @@ Station Information - - + + @@ -18,9 +19,9 @@ Indoor Sensor - - - + + + @@ -28,14 +29,14 @@ Remote Sensor - - - - - - - - + + + + + + + + diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/channels.xml index a18e7e5860a5b..e5abee109cf81 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/channels.xml @@ -1,5 +1,6 @@ - @@ -29,7 +30,7 @@ Temperature Temperature - + @@ -37,7 +38,7 @@ Dew Point temperature Temperature - + @@ -45,7 +46,7 @@ Feeling temperature Temperature - + @@ -53,7 +54,7 @@ Forecast relative humidity Humidity - + @@ -61,7 +62,7 @@ Barometric Pressure Pressure - + @@ -69,7 +70,7 @@ Pressure evolution trend (up, down, stable) Pressure - + @@ -77,7 +78,7 @@ Rain fall hourly rate Rain - + @@ -85,7 +86,7 @@ Rain fall during the day Rain - + @@ -93,7 +94,7 @@ Rain fall amount for the week Rain - + @@ -101,7 +102,7 @@ Rain fall amount for the month Rain - + @@ -109,7 +110,7 @@ Rain fall amount for the year Rain - + @@ -117,7 +118,7 @@ Rain fall total amount since factpry reset Rain - + @@ -125,7 +126,7 @@ Rain fall in last 24 hours Rain - + @@ -133,7 +134,7 @@ Rain fall total for last rain event Rain - + @@ -148,7 +149,7 @@ Wind speed Wind - + @@ -156,21 +157,21 @@ Maximum daily wind speed Wind - + Number:Angle Wind direction in degrees - + String Wind direction - + @@ -178,21 +179,21 @@ Wind gust Wind - + Number:Angle Wind gust direction in degrees - + String Wind gust direction - + @@ -200,7 +201,7 @@ Maximum daily wind gust Wind - + @@ -208,21 +209,21 @@ Wind speed 2-minute average Wind - + Number:Angle Wind direction 2-minute average in degrees - + String Wind direction 2-minute Average - + @@ -230,42 +231,42 @@ Wind speed 10-minute average Wind - + Number:Angle Wind direction 10-minute average in degrees - + String Wind direction 10-minute Average - + Number:Intensity Solar radiation - + Number:Dimensionless Ultraviolet radiation index - + String Ultraviolet radiation danger level - + @@ -273,7 +274,7 @@ Temperature of the soil Sensor - + @@ -281,7 +282,7 @@ Amount of moisture in the soil Sensor - + @@ -289,7 +290,7 @@ Soil moisture level from Very Dry to Very Wet Sensor - + @@ -297,7 +298,7 @@ Amount of carbon dioxide Sensor - + @@ -305,7 +306,7 @@ Relay Switch - + @@ -313,7 +314,7 @@ Indicates if battery is good or needs replacing Battery - + diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws0265.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws0265.xml index 9a2a8869367fb..cb9a59e3026a6 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws0265.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws0265.xml @@ -1,12 +1,13 @@ - - + @@ -49,15 +50,15 @@ - + Weather Data - - + + diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws0900.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws0900.xml index c6a73c55705e6..9d471e0f3c4be 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws0900.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws0900.xml @@ -1,12 +1,13 @@ - - + @@ -25,7 +26,7 @@ - + @@ -33,25 +34,25 @@ Weather Data - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws1400ip.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws1400ip.xml index 13fbd28271e10..6dfa79d56ef32 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws1400ip.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws1400ip.xml @@ -1,12 +1,13 @@ - - + @@ -57,7 +58,7 @@ - + @@ -65,31 +66,31 @@ Weather Data - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws2902a.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws2902a.xml index e91c25130d7e3..29d33f92362af 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws2902a.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws2902a.xml @@ -1,12 +1,13 @@ - - + @@ -25,7 +26,7 @@ - + @@ -33,31 +34,31 @@ Weather Data - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws8482.xml b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws8482.xml index 11d02807e81e5..b27e8558ca8c3 100644 --- a/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws8482.xml +++ b/bundles/org.openhab.binding.ambientweather/src/main/resources/ESH-INF/thing/ws8482.xml @@ -1,12 +1,13 @@ - - + @@ -49,17 +50,17 @@ - + Weather Data - - - - + + + + diff --git a/bundles/org.openhab.binding.astro/README.md b/bundles/org.openhab.binding.astro/README.md index 2de237b309078..26c3fb531b513 100644 --- a/bundles/org.openhab.binding.astro/README.md +++ b/bundles/org.openhab.binding.astro/README.md @@ -46,7 +46,8 @@ Optionally, a refresh `interval` (in seconds) can be defined to also calculate p * **group** `season` * **channel**: * `spring, summer, autumn, winter` (DateTime) - * `name` (String), values `SPRING, SUMMER, AUTUMN, WINTER` + * `name`,`nextName` (String), values `SPRING, SUMMER, AUTUMN, WINTER` + * `timeLeft` (Number:Time) * **group** `eclipse` * **channel**: * `total, partial, ring` (DateTime) diff --git a/bundles/org.openhab.binding.astro/pom.xml b/bundles/org.openhab.binding.astro/pom.xml index 14bf0a65d68b3..823e5cf24e8dc 100644 --- a/bundles/org.openhab.binding.astro/pom.xml +++ b/bundles/org.openhab.binding.astro/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.astro diff --git a/bundles/org.openhab.binding.astro/src/main/feature/feature.xml b/bundles/org.openhab.binding.astro/src/main/feature/feature.xml index ea697a208bd43..31d8250d95783 100644 --- a/bundles/org.openhab.binding.astro/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.astro/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.astro/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.astro/${project.version} + diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroBindingConstants.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroBindingConstants.java index 702ac09d70b71..2b5c24308617a 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroBindingConstants.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroBindingConstants.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.astro.internal; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.ThingTypeUID; /** @@ -21,6 +22,7 @@ * @author Gerhard Riegler - Initial contribution * @author Amit Kumar Mondal - Made non-Instantiable */ +@NonNullByDefault public final class AstroBindingConstants { /** Constructor */ diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroHandlerFactory.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroHandlerFactory.java index 590971da7fc6e..ce6886a1db0f1 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroHandlerFactory.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/AstroHandlerFactory.java @@ -20,6 +20,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.i18n.TimeZoneProvider; import org.eclipse.smarthome.core.scheduler.CronScheduler; import org.eclipse.smarthome.core.thing.Thing; @@ -31,6 +33,7 @@ import org.openhab.binding.astro.internal.handler.MoonHandler; import org.openhab.binding.astro.internal.handler.SunHandler; import org.openhab.binding.astro.internal.util.PropertyUtils; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -39,6 +42,7 @@ * * @author Gerhard Riegler - Initial contribution */ +@NonNullByDefault @Component(configurationPid = "binding.astro", service = ThingHandlerFactory.class) public class AstroHandlerFactory extends BaseThingHandlerFactory { @@ -46,7 +50,13 @@ public class AstroHandlerFactory extends BaseThingHandlerFactory { .concat(SunHandler.SUPPORTED_THING_TYPES.stream(), MoonHandler.SUPPORTED_THING_TYPES.stream()) .collect(Collectors.toSet()); private static final Map ASTRO_THING_HANDLERS = new HashMap<>(); - private CronScheduler scheduler; + private final CronScheduler scheduler; + + @Activate + public AstroHandlerFactory(final @Reference CronScheduler scheduler, final @Reference TimeZoneProvider timeZone) { + this.scheduler = scheduler; + PropertyUtils.setTimeZone(timeZone); + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -54,7 +64,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); AstroThingHandler thingHandler = null; if (thingTypeUID.equals(THING_TYPE_SUN)) { @@ -74,26 +84,7 @@ public void unregisterHandler(Thing thing) { ASTRO_THING_HANDLERS.remove(thing.getUID().toString()); } - @Reference - protected void setTimeZoneProvider(TimeZoneProvider timeZone) { - PropertyUtils.setTimeZone(timeZone); - } - - protected void unsetTimeZoneProvider(TimeZoneProvider timeZone) { - PropertyUtils.unsetTimeZone(); - } - public static AstroThingHandler getHandler(String thingUid) { return ASTRO_THING_HANDLERS.get(thingUid); } - - @Reference - protected void setCronScheduler(CronScheduler scheduler) { - this.scheduler = scheduler; - } - - protected void unsetCronScheduler(CronScheduler scheduler) { - this.scheduler = null; - } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/calc/SeasonCalc.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/calc/SeasonCalc.java index fe8971bee9b30..e95954c257de1 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/calc/SeasonCalc.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/calc/SeasonCalc.java @@ -160,5 +160,4 @@ private double periodic24(double T) { private double cosDeg(double deg) { return Math.cos(deg * Math.PI / 180); } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/config/AstroChannelConfig.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/config/AstroChannelConfig.java index e9f501829fc6a..17696174d037d 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/config/AstroChannelConfig.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/config/AstroChannelConfig.java @@ -64,5 +64,4 @@ public String getLatest() { public void setLatest(String latest) { this.latest = latest; } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/discovery/AstroDiscoveryService.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/discovery/AstroDiscoveryService.java index e67a27b642c76..10bab4f550a53 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/discovery/AstroDiscoveryService.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/discovery/AstroDiscoveryService.java @@ -155,5 +155,4 @@ protected void setTranslationProvider(TranslationProvider i18nProvider) { protected void unsetTranslationProvider(TranslationProvider i18nProvider) { this.i18nProvider = null; } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java index 20eb9e5543a91..ca7ee6a025ef9 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/AstroThingHandler.java @@ -66,7 +66,7 @@ public abstract class AstroThingHandler extends BaseThingHandler { protected AstroThingConfig thingConfig; private final Lock monitor = new ReentrantLock(); - private ScheduledCompletableFuture dailyJob; + private ScheduledCompletableFuture dailyJob; private final Set> scheduledFutures = new HashSet<>(); public AstroThingHandler(Thing thing, CronScheduler scheduler) { diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java index 380bbd149fd05..46d84a1d69629 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/MoonHandler.java @@ -87,5 +87,4 @@ protected Job getDailyJob() { private void initializeMoon() { moon = moonCalc.getMoonInfo(Calendar.getInstance(), thingConfig.getLatitude(), thingConfig.getLongitude()); } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java index 60fee63061ae5..1c6cdcca5108c 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/handler/SunHandler.java @@ -89,5 +89,4 @@ private void initializeSun() { sun = sunCalc.getSunInfo(Calendar.getInstance(), thingConfig.getLatitude(), thingConfig.getLongitude(), thingConfig.getAltitude()); } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/AbstractJob.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/AbstractJob.java index 67ecc35a226fa..85dc0a0555875 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/AbstractJob.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/AbstractJob.java @@ -44,5 +44,4 @@ public static void checkArgument(boolean expression, String errorMessage) { throw new IllegalArgumentException(errorMessage); } } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/DailyJobMoon.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/DailyJobMoon.java index 3123afa440122..9090b652df23f 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/DailyJobMoon.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/DailyJobMoon.java @@ -79,5 +79,4 @@ public void run() { public String toString() { return "Daily job moon " + getThingUID(); } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/DailyJobSun.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/DailyJobSun.java index 62314f9ced43e..e0c258f874431 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/DailyJobSun.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/DailyJobSun.java @@ -97,5 +97,4 @@ public void run() { public String toString() { return "Daily job sun " + getThingUID(); } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/EventJob.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/EventJob.java index 649654735c119..c2a62e2257116 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/EventJob.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/EventJob.java @@ -58,5 +58,4 @@ public void run() { public String toString() { return "Event job " + getThingUID() + "/" + channelID + "/" + event; } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/Job.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/Job.java index 9f4c0638f5059..348a6f0ad43bc 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/Job.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/Job.java @@ -231,5 +231,4 @@ public static boolean checkNull(T obj, String message) { * Returns the thing UID that is associated with this {@link Job} (cannot be {@code null}) */ public String getThingUID(); - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/PositionalJob.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/PositionalJob.java index f1caa38f612fa..939dd387349c9 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/PositionalJob.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/PositionalJob.java @@ -49,5 +49,4 @@ public void run() { public String toString() { return "Positional job " + getThingUID(); } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/PublishPlanetJob.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/PublishPlanetJob.java index 63eff15deabe0..17297dae6667a 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/PublishPlanetJob.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/PublishPlanetJob.java @@ -49,5 +49,4 @@ public void run() { public String toString() { return "Publish planet job " + getThingUID(); } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/SunPhaseJob.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/SunPhaseJob.java index 2614190ce427d..12a52ebb50a7f 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/SunPhaseJob.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/job/SunPhaseJob.java @@ -68,5 +68,4 @@ public void run() { public String toString() { return "Sun phase job " + getThingUID() + "/" + sunPhaseName; } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/Eclipse.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/Eclipse.java index e3d50dab066b1..7e0dce6baf082 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/Eclipse.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/Eclipse.java @@ -60,5 +60,4 @@ public String toString() { .append("total", total == null ? null : total.getTime()) .append("partial", partial == null ? null : partial.getTime()).toString(); } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/RiseSet.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/RiseSet.java index 7c6e1ecdddac7..03af22228cf11 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/RiseSet.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/RiseSet.java @@ -48,5 +48,4 @@ public Range getSet() { public void setSet(Range set) { this.set = set; } - } diff --git a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/Season.java b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/Season.java index d298aefeea07c..4a66133a5e4ad 100644 --- a/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/Season.java +++ b/bundles/org.openhab.binding.astro/src/main/java/org/openhab/binding/astro/internal/model/Season.java @@ -12,8 +12,14 @@ */ package org.openhab.binding.astro.internal.model; +import static org.eclipse.smarthome.core.library.unit.MetricPrefix.MILLI; + import java.util.Calendar; +import javax.measure.quantity.Time; + +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.openhab.binding.astro.internal.util.DateTimeUtils; /** @@ -105,4 +111,25 @@ public void setName(SeasonName name) { public Calendar getNextSeason() { return DateTimeUtils.getNext(spring, summer, autumn, winter); } + + /** + * Returns the next season name. + */ + public SeasonName getNextName() { + int ordinal = name.ordinal() + 1; + if (ordinal > 3) { + ordinal = 0; + } + return SeasonName.values()[ordinal]; + } + + /** + * Returns the time left for current season + */ + public QuantityType - + Moves an event or datetime value forward or backward (in minutes) 0 diff --git a/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/channels.xml index f8ad8d84c14af..8f53ba14349c4 100644 --- a/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/channels.xml @@ -9,9 +9,9 @@ The position of the planet - - - + + + @@ -19,9 +19,9 @@ The radiation level of the sun - - - + + + @@ -29,42 +29,42 @@ Number:Angle The azimuth of the planet - + Number:Angle The elevation of the planet - + Number Projected shade length ratio (derived from Elevation) - + Number:Intensity Level of radiation after penetration of the atmospheric layer - + Number:Intensity Level of radiation diffracted by clouds and atmosphere - + Number:Intensity Total quantity of radiation on the ground - + @@ -72,10 +72,10 @@ Range for a sun event - - - - + + + + @@ -83,9 +83,9 @@ Range for a moon event - - - + + + @@ -93,23 +93,23 @@ DateTime The start time of the event - - + + DateTime The end time of the event - - + + Number:Time The duration of the event - + @@ -122,7 +122,7 @@ - + @@ -130,9 +130,9 @@ The zodiac of the sun - - - + + + @@ -163,11 +163,19 @@ The seasons this year - - - - - + + + + + + + + The name of the next season + + + + The time remaining before season change + @@ -189,28 +197,28 @@ DateTime The beginning of spring - + DateTime The beginning of summer - + DateTime The beginning of autumn - + DateTime The beginning of winter - + @@ -218,10 +226,10 @@ The DateTime of the next sun eclipses - - - - + + + + @@ -229,21 +237,21 @@ DateTime The DateTime of the next total eclipse - + DateTime The DateTime of the next partial eclipse - + DateTime The DateTime of the next ring eclipse - + @@ -257,7 +265,7 @@ - + @@ -265,7 +273,7 @@ The details of the current sun phase - + @@ -295,16 +303,16 @@ The details of the current and next moon phases - - - - - - - - - - + + + + + + + + + + @@ -312,56 +320,56 @@ DateTime The DateTime the moon is in the first quarter - + DateTime The DateTime the moon is in the third quarter - + DateTime The DateTime for full moon - + DateTime The DateTime for new moon - + Number:Time The age of the moon in days - + Number:Angle The age of the moon - + Number:Dimensionless The age of the moon - + Number:Dimensionless The illumination of the moon - + @@ -394,7 +402,7 @@ - + @@ -403,9 +411,9 @@ The DateTime of the next moon eclipses - - - + + + @@ -419,7 +427,7 @@ - + @@ -427,9 +435,9 @@ Distance data - - - + + + @@ -437,14 +445,14 @@ DateTime The DateTime when the distance is reached - + Number:Length The distance of the object - + @@ -457,7 +465,7 @@ - + @@ -465,7 +473,7 @@ The zodiac of the moon - + diff --git a/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/moon.xml b/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/moon.xml index 7e8918b151584..9c11bd7f00351 100644 --- a/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/moon.xml +++ b/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/moon.xml @@ -17,8 +17,8 @@ The moonset event range - - + + The distance to the moon @@ -33,12 +33,12 @@ The position of the moon - + geolocation - + diff --git a/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/sun.xml b/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/sun.xml index 79d07f7704606..da90fa9e4ef8e 100644 --- a/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/sun.xml +++ b/bundles/org.openhab.binding.astro/src/main/resources/ESH-INF/thing/sun.xml @@ -64,16 +64,16 @@ The position of the sun - - - - - + + + + + geolocation - + diff --git a/bundles/org.openhab.binding.atlona/pom.xml b/bundles/org.openhab.binding.atlona/pom.xml index bd6764ec33827..a3a2cda673c22 100644 --- a/bundles/org.openhab.binding.atlona/pom.xml +++ b/bundles/org.openhab.binding.atlona/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.atlona diff --git a/bundles/org.openhab.binding.atlona/src/main/feature/feature.xml b/bundles/org.openhab.binding.atlona/src/main/feature/feature.xml index 602ed7fc48665..cbc8bdfea1806 100644 --- a/bundles/org.openhab.binding.atlona/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.atlona/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.atlona/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.atlona/${project.version} + diff --git a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/AtlonaBindingConstants.java b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/AtlonaBindingConstants.java index c4faa20669b2f..f2abaf1ca4d0b 100644 --- a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/AtlonaBindingConstants.java +++ b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/AtlonaBindingConstants.java @@ -47,5 +47,4 @@ public class AtlonaBindingConstants { * Thing ID for the AT-UHD-PRO3-1616m (16x16 hdbaset matrix) */ public static final ThingTypeUID THING_TYPE_PRO3_1616M = new ThingTypeUID(BINDING_ID, "pro3-1616m"); - } diff --git a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/discovery/AtlonaDiscovery.java b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/discovery/AtlonaDiscovery.java index 0146b870e584a..e7c172943a91e 100644 --- a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/discovery/AtlonaDiscovery.java +++ b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/discovery/AtlonaDiscovery.java @@ -156,7 +156,6 @@ protected void startScan() { } catch (IOException e) { logger.debug("Error getting ip addresses: {}", e.getMessage(), e); } - } /** diff --git a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/net/SocketSession.java b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/net/SocketSession.java index cd8b3e33d3b32..ec89dc412211c 100644 --- a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/net/SocketSession.java +++ b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/net/SocketSession.java @@ -75,5 +75,4 @@ public interface SocketSession { * @throws java.io.IOException an exception that occurred while sending */ void sendCommand(String command) throws IOException; - } diff --git a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/pro3/AtlonaPro3Constants.java b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/pro3/AtlonaPro3Constants.java index 94eda2fa6e0c9..be930fb41fa81 100644 --- a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/pro3/AtlonaPro3Constants.java +++ b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/pro3/AtlonaPro3Constants.java @@ -58,5 +58,4 @@ class AtlonaPro3Constants { static final String CMD_MATRIXRESET = "resetmatrix"; static final String CMD_MATRIXRESETPORTS = "resetports"; static final String CMD_MATRIXPORTALL = "allports"; - } diff --git a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/pro3/AtlonaPro3PortocolHandler.java b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/pro3/AtlonaPro3PortocolHandler.java index e2637d0e32130..fbb6be623e977 100644 --- a/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/pro3/AtlonaPro3PortocolHandler.java +++ b/bundles/org.openhab.binding.atlona/src/main/java/org/openhab/binding/atlona/internal/pro3/AtlonaPro3PortocolHandler.java @@ -1111,7 +1111,6 @@ public void responseException(Exception e) { callback.statusChanged(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Exception occurred reading from Atlona: " + e); } - } /** @@ -1162,8 +1161,6 @@ public void responseException(Exception e) { responses.put(e); } catch (InterruptedException e1) { } - } - } } diff --git a/bundles/org.openhab.binding.atlona/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.atlona/src/main/resources/ESH-INF/binding/binding.xml index 5cd32a208d642..ab992b79b7ee4 100644 --- a/bundles/org.openhab.binding.atlona/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.atlona/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Atlona Products Binding for Atlona PRO3 HDBaseT Matrix switches. diff --git a/bundles/org.openhab.binding.atlona/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.atlona/src/main/resources/ESH-INF/thing/thing-types.xml index 4bd479432f5a8..40a4ed2f7bcfe 100644 --- a/bundles/org.openhab.binding.atlona/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.atlona/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -529,8 +529,8 @@ Output Port Channels - - + + @@ -539,8 +539,8 @@ HDMI Port Mirroring Channels - - + + @@ -548,8 +548,8 @@ Volume channels - - + + diff --git a/bundles/org.openhab.binding.autelis/pom.xml b/bundles/org.openhab.binding.autelis/pom.xml index 4259b830deba1..a91d351a8ff7f 100644 --- a/bundles/org.openhab.binding.autelis/pom.xml +++ b/bundles/org.openhab.binding.autelis/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.autelis diff --git a/bundles/org.openhab.binding.autelis/src/main/feature/feature.xml b/bundles/org.openhab.binding.autelis/src/main/feature/feature.xml index 53541e4096688..06423ebc6d0a3 100644 --- a/bundles/org.openhab.binding.autelis/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.autelis/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.autelis/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.autelis/${project.version} + diff --git a/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/binding/binding.xml index f73636fadddfb..22e1cc6bf7dfe 100644 --- a/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Autelis Pool Control Binding This is the binding for a Autelis pool controller. diff --git a/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/thing/jandy.xml b/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/thing/jandy.xml index c2dd522bbd228..dd220c4121cfe 100644 --- a/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/thing/jandy.xml +++ b/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/thing/jandy.xml @@ -1,18 +1,19 @@ - A Jandy pool control thing represents a Autelis pool controller for Jandy systems - - - - - - - + + + + + + + The current state of the pump @@ -173,27 +174,27 @@ The current solar temperature - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - + network-address diff --git a/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/thing/pentair.xml b/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/thing/pentair.xml index 93e1d8f0140bc..8dcf058185314 100644 --- a/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/thing/pentair.xml +++ b/bundles/org.openhab.binding.autelis/src/main/resources/ESH-INF/thing/pentair.xml @@ -1,16 +1,17 @@ - A Pentair pool control thing represents an Autelis pool controller for Pentair systems - - - - - + + + + + The state of sensor 1 (water sensor) @@ -31,8 +32,8 @@ The state of sensor 5 (water sensor) - - + + The current state of circuit 1 (Spa or Lo-Temp) @@ -121,21 +122,21 @@ The current spa/hi-temp heater settings - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + Pump 2 @@ -164,15 +165,15 @@ Pump 8 - - - - - - - - - + + + + + + + + + diff --git a/bundles/org.openhab.binding.avmfritz/README.md b/bundles/org.openhab.binding.avmfritz/README.md index 62085ed13c814..51721207009d7 100644 --- a/bundles/org.openhab.binding.avmfritz/README.md +++ b/bundles/org.openhab.binding.avmfritz/README.md @@ -114,6 +114,10 @@ If the FRITZ!Powerline 546E is added via auto-discovery it determines its own `a - `ain` (mandatory), no default (AIN number of the device) +### Finding The AIN ### + +The AIN (actor identification number) can be found in the FRITZ!Box interface -> Home Network -> SmartHome. When opening the details view for a device with the edit button, the AIN is shown. Use the AIN without the blank. + ## Supported Channels | Channel Type ID | Item Type | Description | Available on thing | @@ -186,6 +190,7 @@ Bridge avmfritz:fritzbox:1 "FRITZ!Box" [ ipAddress="192.168.x.x", password="xxx" Thing Comet_DECT aaaaaabbbbbb "Comet DECT #3" [ ain="aaaaaabbbbbb" ] Thing HAN_FUN_CONTACT zzzzzzzzzzzz_1 "HAN-FUN Contact #4" [ ain="zzzzzzzzzzzz-1" ] Thing HAN_FUN_SWITCH zzzzzzzzzzzz_2 "HAN-FUN Switch #5" [ ain=zzzzzzzzzzzz-2" ] + Thing FRITZ_DECT_Repeater_100 rrrrrrrrrrrr "DECT Repeater 100 #6" [ ain="rrrrrrrrrrrr" ] Thing FRITZ_GROUP_HEATING AA_AA_AA_900 "Heating group" [ ain="AA:AA:AA-900" ] Thing FRITZ_GROUP_SWITCH BB_BB_BB_900 "Switch group" [ ain="BB:BB:BB-900" ] } @@ -214,6 +219,8 @@ Contact HANFUNContactState "Status [%s]" { channel="avmfritz:HAN_FUN_CONTACT:1:z DateTime HANFUNSwitchLastChanged "Last change" { channel="avmfritz:HAN_FUN_SWITCH:1:zzzzzzzzzzzz_2:last_change" } +Number:Temperature Temperature1 "Current measured temperature [%.1f %unit%]" { channel="avmfritz:FRITZ_DECT_Repeater_100:1:rrrrrrrrrrrr:temperature" } + Number:Temperature FRITZ_GROUP_HEATINGSetTemperature "Group temperature set point [%.1f %unit%]" { channel="avmfritz:FRITZ_GROUP_HEATING:1:AA_AA_AA_900:set_temp" } Switch Outlet3 "Group switch" { channel="avmfritz:FRITZ_GROUP_SWITCH:1:BB_BB_BB_900:outlet" } diff --git a/bundles/org.openhab.binding.avmfritz/pom.xml b/bundles/org.openhab.binding.avmfritz/pom.xml index ffdf2d86d1e99..4b0ab69ea7c68 100644 --- a/bundles/org.openhab.binding.avmfritz/pom.xml +++ b/bundles/org.openhab.binding.avmfritz/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.avmfritz diff --git a/bundles/org.openhab.binding.avmfritz/src/main/feature/feature.xml b/bundles/org.openhab.binding.avmfritz/src/main/feature/feature.xml index 73e0fc4f79453..23952103eaa19 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.avmfritz/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - openhab.tp-jaxb - mvn:org.openhab.addons.bundles/org.openhab.binding.avmfritz/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + openhab.tp-jaxb + mvn:org.openhab.addons.bundles/org.openhab.binding.avmfritz/${project.version} + diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzHandlerFactory.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzHandlerFactory.java index 1c61ff3a03d99..39fcb543fe4fa 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzHandlerFactory.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/AVMFritzHandlerFactory.java @@ -14,28 +14,21 @@ import static org.openhab.binding.avmfritz.internal.BindingConstants.*; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; - -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; -import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.eclipse.smarthome.io.net.http.HttpClientFactory; -import org.openhab.binding.avmfritz.internal.discovery.AVMFritzDiscoveryService; -import org.openhab.binding.avmfritz.internal.handler.AVMFritzBaseBridgeHandler; import org.openhab.binding.avmfritz.internal.handler.BoxHandler; import org.openhab.binding.avmfritz.internal.handler.DeviceHandler; import org.openhab.binding.avmfritz.internal.handler.GroupHandler; import org.openhab.binding.avmfritz.internal.handler.Powerline546EHandler; -import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; @@ -47,27 +40,26 @@ * @author Robert Bausdorf - Initial contribution */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.avmfritz") +@NonNullByDefault public class AVMFritzHandlerFactory extends BaseThingHandlerFactory { - /** - * Logger - */ - private final Logger logger = LoggerFactory.getLogger(getClass()); - /** - * Service registration map - */ - private Map> discoveryServiceRegs = new HashMap<>(); - /** - * shared instance of HTTP client for asynchronous calls - */ - private HttpClient httpClient; - private AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider; + private final Logger logger = LoggerFactory.getLogger(AVMFritzHandlerFactory.class); + + private final HttpClient httpClient; + private final AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider; + + @Activate + public AVMFritzHandlerFactory(final @Reference HttpClientFactory httpClientFactory, + final @Reference AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + this.stateDescriptionProvider = stateDescriptionProvider; + } /** * Provides the supported thing types */ @Override - public boolean supportsThingType(@NonNull ThingTypeUID thingTypeUID) { + public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); } @@ -75,74 +67,19 @@ public boolean supportsThingType(@NonNull ThingTypeUID thingTypeUID) { * Create handler of things. */ @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (BRIDGE_THING_TYPE.equals(thingTypeUID)) { - BoxHandler handler = new BoxHandler((Bridge) thing, httpClient, stateDescriptionProvider); - registerDeviceDiscoveryService(handler); - return handler; + return new BoxHandler((Bridge) thing, httpClient, stateDescriptionProvider); } else if (PL546E_STANDALONE_THING_TYPE.equals(thingTypeUID)) { - Powerline546EHandler handler = new Powerline546EHandler((Bridge) thing, httpClient, - stateDescriptionProvider); - registerDeviceDiscoveryService(handler); - return handler; - } else if (SUPPORTED_DEVICE_THING_TYPES_UIDS.contains(thing.getThingTypeUID())) { + return new Powerline546EHandler((Bridge) thing, httpClient, stateDescriptionProvider); + } else if (SUPPORTED_DEVICE_THING_TYPES_UIDS.contains(thingTypeUID)) { return new DeviceHandler(thing); } else if (SUPPORTED_GROUP_THING_TYPES_UIDS.contains(thingTypeUID)) { return new GroupHandler(thing); } else { - logger.error("ThingHandler not found for {}", thing.getThingTypeUID()); + logger.error("ThingHandler not found for {}", thingTypeUID); } return null; } - - /** - * Remove handler of things. - */ - @Override - protected synchronized void removeHandler(@NonNull ThingHandler thingHandler) { - if (thingHandler instanceof AVMFritzBaseBridgeHandler) { - ServiceRegistration serviceReg = discoveryServiceRegs.remove(thingHandler.getThing().getUID()); - if (serviceReg != null) { - // remove discovery service, if bridge handler is removed - AVMFritzDiscoveryService service = (AVMFritzDiscoveryService) bundleContext - .getService(serviceReg.getReference()); - serviceReg.unregister(); - if (service != null) { - service.deactivate(); - } - } - } - } - - /** - * Register a new discovery service for a new FRITZ!Box. - * - * @param handler - */ - private synchronized void registerDeviceDiscoveryService(AVMFritzBaseBridgeHandler handler) { - AVMFritzDiscoveryService discoveryService = new AVMFritzDiscoveryService(handler); - discoveryServiceRegs.put(handler.getThing().getUID(), - bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>())); - } - - @Reference - protected void setHttpClientFactory(HttpClientFactory httpClientFactory) { - this.httpClient = httpClientFactory.getCommonHttpClient(); - } - - protected void unsetHttpClientFactory(HttpClientFactory httpClientFactory) { - this.httpClient = null; - } - - @Reference - protected void setDynamicStateDescriptionProvider( - AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider) { - this.stateDescriptionProvider = stateDescriptionProvider; - } - - protected void unsetDynamicStateDescriptionProvider( - AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider) { - this.stateDescriptionProvider = null; - } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzBoxConfiguration.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzBoxConfiguration.java new file mode 100644 index 0000000000000..13f72779444a9 --- /dev/null +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzBoxConfiguration.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.avmfritz.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * Bean holding configuration data for FRITZ! Box. + * + * @author Robert Bausdorf - Initial contribution + */ +@NonNullByDefault +public class AVMFritzBoxConfiguration { + + public @NonNullByDefault({}) String ipAddress; + public @Nullable Integer port; + public String protocol = "http"; + + public @Nullable String user; + public @NonNullByDefault({}) String password; + + public long pollingInterval = 15; + public long asyncTimeout = 10000; + public long syncTimeout = 2000; + + @Override + public String toString() { + return new StringBuilder().append("[IP=").append(ipAddress).append(",port=").append(port).append(",protocol=") + .append(protocol).append(",user=").append(user).append(",pollingInterval=").append(pollingInterval) + .append(",asyncTimeout=").append(asyncTimeout).append(",syncTimeout=").append(syncTimeout).append("]") + .toString(); + } +} diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzConfiguration.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzConfiguration.java deleted file mode 100644 index 9c81cec6b4cea..0000000000000 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzConfiguration.java +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.avmfritz.internal.config; - -import org.apache.commons.lang.builder.ToStringBuilder; - -/** - * Bean holding configuration data according to bridge.xml - * - * @author Robert Bausdorf - Initial contribution - */ -public class AVMFritzConfiguration { - - private String ipAddress; - private Integer port; - private String protocol; - - private String user; - private String password; - - private Integer asyncTimeout; - private Integer syncTimeout; - private Integer pollingInterval; - - public String getIpAddress() { - return ipAddress; - } - - public void setIpAddress(String ipAddress) { - this.ipAddress = ipAddress; - } - - public Integer getPort() { - return port; - } - - public void setPort(Integer port) { - this.port = port; - } - - public String getProtocol() { - return protocol; - } - - public void setProtocol(String protocol) { - this.protocol = protocol; - } - - public String getUser() { - return user; - } - - public void setUser(String user) { - this.user = user; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Integer getAsyncTimeout() { - return asyncTimeout; - } - - public void setAsyncTimeout(Integer asyncTimeout) { - this.asyncTimeout = asyncTimeout; - } - - public Integer getSyncTimeout() { - return syncTimeout; - } - - public void setSyncTimeout(Integer syncTimeout) { - this.syncTimeout = syncTimeout; - } - - public Integer getPollingInterval() { - return pollingInterval; - } - - public void setPollingInterval(Integer pollingInterval) { - this.pollingInterval = pollingInterval; - } - - @Override - public String toString() { - return new ToStringBuilder(this).append("IP", getIpAddress()).append("port", getPort()) - .append("proto", getProtocol()).append("user", getUser()) - .append("pollingInterval", getPollingInterval()).append("asyncTimeout", getAsyncTimeout()) - .append("syncTimeout", getSyncTimeout()).toString(); - } -} diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzTemperatureChannelConfig.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzDeviceConfiguration.java similarity index 59% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzTemperatureChannelConfig.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzDeviceConfiguration.java index 7e1a962f020f5..5fd167d9a06d5 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzTemperatureChannelConfig.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/config/AVMFritzDeviceConfiguration.java @@ -12,27 +12,21 @@ */ package org.openhab.binding.avmfritz.internal.config; -import org.apache.commons.lang.builder.ToStringBuilder; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; /** - * Channel configuration from openHAB. + * Bean holding configuration data for FRITZ! devices. * * @author Christoph Weitkamp - Initial contribution */ -public class AVMFritzTemperatureChannelConfig { +@NonNullByDefault +public class AVMFritzDeviceConfiguration { - private int offset; - - public int getOffset() { - return offset; - } - - public void setOffset(int offset) { - this.offset = offset; - } + public @Nullable String ain; @Override public String toString() { - return new ToStringBuilder(this).append("offset", getOffset()).toString(); + return new StringBuilder().append("[identifier=").append(ain).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/discovery/AVMFritzDiscoveryService.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/discovery/AVMFritzDiscoveryService.java index bbe1a73bad3bf..e5653bdca366a 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/discovery/AVMFritzDiscoveryService.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/discovery/AVMFritzDiscoveryService.java @@ -18,21 +18,23 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; -import org.openhab.binding.avmfritz.internal.ahamodel.AVMFritzBaseModel; -import org.openhab.binding.avmfritz.internal.ahamodel.GroupModel; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; +import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel; +import org.openhab.binding.avmfritz.internal.dto.GroupModel; import org.openhab.binding.avmfritz.internal.handler.AVMFritzBaseBridgeHandler; -import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; -import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaDiscoveryCallback; +import org.openhab.binding.avmfritz.internal.hardware.FritzAhaStatusListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,83 +44,83 @@ * @author Robert Bausdorf - Initial contribution * @author Christoph Weitkamp - Added support for groups */ -public class AVMFritzDiscoveryService extends AbstractDiscoveryService { +@NonNullByDefault +public class AVMFritzDiscoveryService extends AbstractDiscoveryService + implements FritzAhaStatusListener, DiscoveryService, ThingHandlerService { private final Logger logger = LoggerFactory.getLogger(AVMFritzDiscoveryService.class); - - /** - * Maximum time to search for devices. - */ - private static final int SEARCH_TIME = 30; - /** - * Initial delay in s for scanning job. - */ - private static final int INITIAL_DELAY = 5; - /** - * Scan interval in s for scanning job. - */ - private static final int SCAN_INTERVAL = 180; /** * Handler of the bridge of which devices have to be discovered. */ - private AVMFritzBaseBridgeHandler bridgeHandler; - /** - * Schedule for scanning - */ - private ScheduledFuture scanningJob; + private @NonNullByDefault({}) AVMFritzBaseBridgeHandler bridgeHandler; - public AVMFritzDiscoveryService(AVMFritzBaseBridgeHandler bridgeHandler) { + public AVMFritzDiscoveryService() { super(Collections.unmodifiableSet( Stream.concat(SUPPORTED_DEVICE_THING_TYPES_UIDS.stream(), SUPPORTED_GROUP_THING_TYPES_UIDS.stream()) .collect(Collectors.toSet())), - SEARCH_TIME); - logger.debug("initialize discovery service"); - this.bridgeHandler = bridgeHandler; - if (bridgeHandler == null) { - logger.debug("no bridge handler for scan given"); - } - this.activate(null); + 30); + } + + @Override + public void activate() { + super.activate(null); + bridgeHandler.registerStatusListener(this); } @Override public void deactivate() { + bridgeHandler.unregisterStatusListener(this); super.deactivate(); } - /** - * Called from the UI when starting a search. - */ @Override public void startScan() { - FritzAhaWebInterface webInterface = bridgeHandler.getWebInterface(); - if (webInterface != null) { - logger.debug("start manual scan on bridge {}", bridgeHandler.getThing().getUID()); - FritzAhaDiscoveryCallback callback = new FritzAhaDiscoveryCallback(webInterface, this); - webInterface.asyncGet(callback); - } + logger.debug("Start manual scan on bridge {}", bridgeHandler.getThing().getUID()); + bridgeHandler.handleRefreshCommand(); } - /** - * Stops a running scan. - */ @Override protected synchronized void stopScan() { - logger.debug("stop manual scan on bridge {}", bridgeHandler.getThing().getUID()); + logger.debug("Stop manual scan on bridge {}", bridgeHandler.getThing().getUID()); super.stopScan(); } - /** - * Add one discovered AHA device to inbox. - * - * @param device Device model received from a FRITZ!Box - */ - public void onDeviceAddedInternal(AVMFritzBaseModel device) { - ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, bridgeHandler.getThingTypeId(device)); + @Override + public void setThingHandler(@NonNullByDefault({}) ThingHandler handler) { + if (handler instanceof AVMFritzBaseBridgeHandler) { + bridgeHandler = (AVMFritzBaseBridgeHandler) handler; + } + } + @Override + public @Nullable ThingHandler getThingHandler() { + return bridgeHandler; + } + + @Override + public void onDeviceAdded(AVMFritzBaseModel device) { + ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, bridgeHandler.getThingTypeId(device)); if (getSupportedThingTypes().contains(thingTypeUID)) { - ThingUID bridgeUID = bridgeHandler.getThing().getUID(); - ThingUID thingUID = new ThingUID(thingTypeUID, bridgeUID, bridgeHandler.getThingName(device)); + ThingUID thingUID = new ThingUID(thingTypeUID, bridgeHandler.getThing().getUID(), + bridgeHandler.getThingName(device)); + onDeviceAddedInternal(thingUID, device); + } else { + logger.debug("Discovered unsupported device: {}", device); + } + } + @Override + public void onDeviceUpdated(ThingUID thingUID, AVMFritzBaseModel device) { + onDeviceAddedInternal(thingUID, device); + } + + @Override + public void onDeviceGone(ThingUID thingUID) { + // nothing to do + } + + private void onDeviceAddedInternal(ThingUID thingUID, AVMFritzBaseModel device) { + if (device.getPresent() == 1) { Map properties = new HashMap<>(); properties.put(CONFIG_AIN, device.getIdentifier()); properties.put(PROPERTY_VENDOR, device.getManufacturer()); @@ -131,37 +133,12 @@ public void onDeviceAddedInternal(AVMFritzBaseModel device) { } DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) - .withRepresentationProperty(CONFIG_AIN).withBridge(bridgeUID).withLabel(device.getName()).build(); + .withRepresentationProperty(CONFIG_AIN).withBridge(bridgeHandler.getThing().getUID()) + .withLabel(device.getName()).build(); thingDiscovered(discoveryResult); } else { - logger.debug("discovered unsupported device: {}", device); - } - } - - /** - * Starts background scanning for attached devices. - */ - @Override - protected void startBackgroundDiscovery() { - if (scanningJob == null || scanningJob.isCancelled()) { - logger.debug("start background scanning job at interval {}s", SCAN_INTERVAL); - scanningJob = scheduler.scheduleWithFixedDelay(this::startScan, INITIAL_DELAY, SCAN_INTERVAL, - TimeUnit.SECONDS); - } else { - logger.debug("scanningJob active"); - } - } - - /** - * Stops background scanning for attached devices. - */ - @Override - protected void stopBackgroundDiscovery() { - if (scanningJob != null && !scanningJob.isCancelled()) { - logger.debug("stop background scanning job"); - scanningJob.cancel(true); - scanningJob = null; + thingRemoved(thingUID); } } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzBaseModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzBaseModel.java similarity index 74% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzBaseModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzBaseModel.java index aa2c3f3e40212..f041b5106c481 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzBaseModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzBaseModel.java @@ -10,29 +10,27 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link DeviceListModel}. * * In the functionbitmask element value the following bits are used: * *
    - *
  1. Bit 0: HAN-FUN Gerät
  2. - *
  3. Bit 3: Button
  4. - *
  5. Bit 4: Alarm-Sensor
  6. - *
  7. Bit 6: Comet DECT, Heizkostenregler
  8. - *
  9. Bit 7: Energie Messgerät
  10. - *
  11. Bit 8: Temperatursensor
  12. - *
  13. Bit 9: Schaltsteckdose
  14. - *
  15. Bit 10: AVM DECT Repeater
  16. - *
  17. Bit 11: Mikrofon
  18. - *
  19. Bit 13: HAN-FUN Unit
  20. + *
  21. Bit 0: HAN-FUN Gerät
  22. + *
  23. Bit 3: Button
  24. + *
  25. Bit 4: Alarm-Sensor
  26. + *
  27. Bit 6: Comet DECT, Heizkostenregler
  28. + *
  29. Bit 7: Energie Messgerät
  30. + *
  31. Bit 8: Temperatursensor
  32. + *
  33. Bit 9: Schaltsteckdose
  34. + *
  35. Bit 10: AVM DECT Repeater
  36. + *
  37. Bit 11: Mikrofon
  38. + *
  39. Bit 13: HAN-FUN Unit
  40. *
* * @author Robert Bausdorf - Initial contribution @@ -182,15 +180,15 @@ public String getName() { @Override public String toString() { - return new ToStringBuilder(this).append("ain", getIdentifier()).append("bitmask", bitmask) - .append("isHANFUNDevice", isHANFUNDevice()).append("isButton", isButton()) - .append("isAlarmSensor", isAlarmSensor()).append("isSwitchableOutlet", isSwitchableOutlet()) - .append("isTempSensor", isTempSensor()).append("isPowermeter", isPowermeter()) - .append("isDectRepeater", isDectRepeater()).append("isHeatingThermostat", isHeatingThermostat()) - .append("isMicrophone", isMicrophone()).append("isHANFUNUnit", isHANFUNUnit()) - .append("id", getDeviceId()).append("manufacturer", getManufacturer()) - .append("productname", getProductName()).append("fwversion", getFirmwareVersion()) - .append("present", getPresent()).append("name", getName()).append(getSwitch()).append(getPowermeter()) - .append(getHkr()).toString(); + return new StringBuilder().append("[ain=").append(ident).append(",bitmask=").append(bitmask) + .append(",isHANFUNDevice=").append(isHANFUNDevice()).append(",isButton=").append(isButton()) + .append(",isAlarmSensor=").append(isAlarmSensor()).append(",isSwitchableOutlet=") + .append(isSwitchableOutlet()).append(",isTempSensor=").append(isTempSensor()).append(",isPowermeter=") + .append(isPowermeter()).append(",isDectRepeater=").append(isDectRepeater()) + .append(",isHeatingThermostat=").append(isHeatingThermostat()).append(",isMicrophone=") + .append(isMicrophone()).append(",isHANFUNUnit=").append(isHANFUNUnit()).append(",id=").append(deviceId) + .append(",manufacturer=").append(deviceManufacturer).append(",productname=").append(productName) + .append(",fwversion=").append(firmwareVersion).append(",present=").append(present).append(",name=") + .append(name).append(getSwitch()).append(getPowermeter()).append(getHkr()).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/AlertModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AlertModel.java similarity index 78% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/AlertModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AlertModel.java index 09b27253e7b57..cadd0493cc22f 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/AlertModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/AlertModel.java @@ -10,22 +10,23 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import java.math.BigDecimal; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link DeviceListModel}. * * @author Christoph Weitkamp - Initial contribution */ -@XmlRootElement(name = "alert") +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "state" }) +@XmlRootElement(name = "alert") public class AlertModel { public static final BigDecimal ON = BigDecimal.ONE; public static final BigDecimal OFF = BigDecimal.ZERO; @@ -42,6 +43,6 @@ public void setState(BigDecimal state) { @Override public String toString() { - return new ToStringBuilder(this).append("state", getState()).toString(); + return new StringBuilder().append("[state=").append(state).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/ButtonModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/ButtonModel.java similarity index 76% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/ButtonModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/ButtonModel.java index 5b5aa6f47f3f3..a36474ac0b085 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/ButtonModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/ButtonModel.java @@ -10,20 +10,21 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link DeviceListModel}. * * @author Christoph Weitkamp - Initial contribution */ -@XmlRootElement(name = "button") +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "lastpressedtimestamp" }) +@XmlRootElement(name = "button") public class ButtonModel { private int lastpressedtimestamp; @@ -38,6 +39,6 @@ public void setLastpressedtimestamp(int lastpressedtimestamp) { @Override public String toString() { - return new ToStringBuilder(this).append("lastpressedtimestamp", getLastpressedtimestamp()).toString(); + return new StringBuilder().append("[lastpressedtimestamp=").append(lastpressedtimestamp).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/DeviceListModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceListModel.java similarity index 79% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/DeviceListModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceListModel.java index d2c52088a8cab..c94270c10c521 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/DeviceListModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceListModel.java @@ -10,15 +10,18 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import java.util.Collections; import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; /** * This JAXB model class maps the XML response to an getdevicelistinfos @@ -76,14 +79,20 @@ * @author Robert Bausdorf - Initial contribution * @author Christoph Weitkamp - Added support for groups */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType @XmlRootElement(name = "devicelist") public class DeviceListModel { @XmlAttribute(name = "version") private String apiVersion; - @XmlElements({ @XmlElement(name = "device", type = DeviceModel.class), - @XmlElement(name = "group", type = GroupModel.class) }) + //@formatter:off + @XmlElements({ + @XmlElement(name = "device", type = DeviceModel.class), + @XmlElement(name = "group", type = GroupModel.class) + }) + //@formatter:on private List devices; public List getDevicelist() { @@ -98,6 +107,12 @@ public void setDevicelist(List devicelist) { } public String getXmlApiVersion() { - return this.apiVersion; + return apiVersion; + } + + @Override + public String toString() { + return new StringBuilder().append("[devices=").append(devices).append(",version=").append(apiVersion) + .append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/DeviceModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceModel.java similarity index 84% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/DeviceModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceModel.java index b729ad4e35040..f2df66a87a234 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/DeviceModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/DeviceModel.java @@ -10,18 +10,19 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link AVMFritzBaseModel}. * * @author Robert Bausdorf - Initial contribution * @author Christoph Weitkamp - Added support for groups */ +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "device") public class DeviceModel extends AVMFritzBaseModel { @@ -64,10 +65,11 @@ public void setEtsiunitinfo(ETSUnitInfoModel etsiunitinfo) { @Override public String toString() { - return new ToStringBuilder(this).append(super.toString()).append(getTemperature()).append(getAlert()) - .append(getButton()).append(getEtsiunitinfo()).toString(); + return new StringBuilder().append(super.toString()).append(temperature).append(alert).append(button) + .append(etsiunitinfo).toString(); } + @XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "etsideviceid", "unittype", "interfaces" }) public static class ETSUnitInfoModel { public static final String HAN_FUN_UNITTYPE_SIMPLE_BUTTON = "273"; @@ -114,8 +116,8 @@ public void setInterfaces(String interfaces) { @Override public String toString() { - return new ToStringBuilder(this).append("etsideviceid", getEtsideviceid()).append("unittype", getUnittype()) - .append("interfaces", getInterfaces()).toString(); + return new StringBuilder().append("[etsideviceid=").append(etsideviceid).append(",unittype=") + .append(unittype).append(",interfaces=").append(interfaces).append("]").toString(); } } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/GroupModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/GroupModel.java similarity index 75% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/GroupModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/GroupModel.java index a4e3b01612c66..e8de2ff0a9338 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/GroupModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/GroupModel.java @@ -10,17 +10,18 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link AVMFritzBaseModel}. * * @author Christoph Weitkamp - Initial contribution */ +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "group") public class GroupModel extends AVMFritzBaseModel { @@ -36,9 +37,10 @@ public void setGroupinfo(GroupInfoModel groupinfo) { @Override public String toString() { - return new ToStringBuilder(this).append(super.toString()).append(getGroupinfo()).toString(); + return new StringBuilder().append(super.toString()).append(groupinfo).toString(); } + @XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "masterdeviceid", "members" }) public static class GroupInfoModel { private String masterdeviceid; @@ -62,8 +64,8 @@ public void setMembers(String members) { @Override public String toString() { - return new ToStringBuilder(this).append("masterdeviceid", getMasterdeviceid()) - .append("members", getMembers()).toString(); + return new StringBuilder().append("[masterdeviceid=").append(masterdeviceid).append(",members=") + .append(members).append("]").toString(); } } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/HeatingModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/HeatingModel.java similarity index 88% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/HeatingModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/HeatingModel.java index 90c27cc57da72..ccdb79b962677 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/HeatingModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/HeatingModel.java @@ -10,18 +10,18 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import static org.openhab.binding.avmfritz.internal.BindingConstants.*; import java.math.BigDecimal; import java.math.RoundingMode; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link DeviceListModel}. * @@ -29,9 +29,10 @@ * @author Christoph Weitkamp - Added support for AVM FRITZ!DECT 300 and Comet DECT * @author Christoph Weitkamp - Added channel 'battery_level' */ -@XmlRootElement(name = "hkr") +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "tist", "tsoll", "absenk", "komfort", "lock", "devicelock", "errorcode", "batterylow", "windowopenactiv", "battery", "nextchange", "summeractive", "holidayactive" }) +@XmlRootElement(name = "hkr") public class HeatingModel { public static final BigDecimal TEMP_FACTOR = new BigDecimal("0.5"); public static final BigDecimal BIG_DECIMAL_TWO = new BigDecimal("2.0"); @@ -195,12 +196,12 @@ public void setHolidayactive(BigDecimal holidayactive) { @Override public String toString() { - return new ToStringBuilder(this).append("tist", getTist()).append("tsoll", getTsoll()) - .append("absenk", getAbsenk()).append("komfort", getKomfort()).append("lock", getLock()) - .append("devicelock", getDevicelock()).append("errorcode", getErrorcode()) - .append("batterylow", getBatterylow()).append("windowopenactiv", getWindowopenactiv()) - .append("battery", getBattery()).append("nextchange", getNextchange()) - .append("summeractive", getSummeractive()).append("holidayactive", getHolidayactive()).toString(); + return new StringBuilder().append("[tist=").append(tist).append(",tsoll=").append(tsoll).append(",absenk=") + .append(absenk).append(",komfort=").append(komfort).append(",lock=").append(lock).append(",devicelock=") + .append(devicelock).append(",errorcode=").append(errorcode).append(",batterylow=").append(batterylow) + .append(",windowopenactiv=").append(windowopenactiv).append(",battery=").append(battery) + .append(",nextchange=").append(nextchange).append(",summeractive=").append(summeractive) + .append(",holidayactive=").append(holidayactive).append("]").toString(); } /** @@ -253,6 +254,7 @@ public static BigDecimal normalizeCelsius(BigDecimal celsiusValue) { return TEMP_FACTOR.multiply(divisor); } + @XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "endperiod", "tchange" }) public static class NextChangeModel { private int endperiod; @@ -276,8 +278,8 @@ public void setTchange(BigDecimal tchange) { @Override public String toString() { - return new ToStringBuilder(this).append("endperiod", getEndperiod()).append("tchange", getTchange()) - .toString(); + return new StringBuilder().append("[endperiod=").append(endperiod).append(",tchange=").append(tchange) + .append("]").toString(); } } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/PowerMeterModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/PowerMeterModel.java similarity index 81% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/PowerMeterModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/PowerMeterModel.java index c90e50d5ec9c7..055a5cedae456 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/PowerMeterModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/PowerMeterModel.java @@ -10,23 +10,24 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import java.math.BigDecimal; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link DeviceListModel}. * * @author Robert Bausdorf - Initial contribution * @author Christoph Weitkamp - Added channel 'voltage' */ -@XmlRootElement(name = "powermeter") +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "voltage", "power", "energy" }) +@XmlRootElement(name = "powermeter") public class PowerMeterModel { public static final BigDecimal VOLTAGE_FACTOR = new BigDecimal("0.001"); public static final BigDecimal POWER_FACTOR = new BigDecimal("0.001"); @@ -61,7 +62,7 @@ public void setEnergy(BigDecimal energy) { @Override public String toString() { - return new ToStringBuilder(this).append("voltage", getVoltage()).append("power", this.getPower()) - .append("energy", this.getEnergy()).toString(); + return new StringBuilder().append("[voltage=").append(getVoltage()).append(",power=").append(getPower()) + .append(",energy=").append(getEnergy()).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/SwitchModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/SwitchModel.java similarity index 83% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/SwitchModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/SwitchModel.java index d6fa3473ea09c..53282612ecbd2 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/SwitchModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/SwitchModel.java @@ -10,17 +10,17 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import static org.openhab.binding.avmfritz.internal.BindingConstants.*; import java.math.BigDecimal; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link DeviceListModel}. * @@ -28,8 +28,9 @@ * @author Christoph Weitkamp - Added new channels `locked`, `mode` and `radiator_mode` * */ -@XmlRootElement(name = "switch") +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "state", "mode", "lock", "devicelock" }) +@XmlRootElement(name = "switch") public class SwitchModel { public static final BigDecimal ON = BigDecimal.ONE; public static final BigDecimal OFF = BigDecimal.ZERO; @@ -79,7 +80,7 @@ public void setDevicelock(BigDecimal devicelock) { @Override public String toString() { - return new ToStringBuilder(this).append("state", getState()).append("mode", getMode()).append("lock", getLock()) - .append("devicelock", getDevicelock()).toString(); + return new StringBuilder().append("[state=").append(state).append(",mode=").append(getMode()).append(",lock=") + .append(lock).append(",devicelock=").append(devicelock).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/TemperatureModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/TemperatureModel.java similarity index 80% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/TemperatureModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/TemperatureModel.java index 98826ffd56d42..fa9380e88cdab 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/TemperatureModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/TemperatureModel.java @@ -10,23 +10,24 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import java.math.BigDecimal; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link DeviceListModel}. * * @author Robert Bausdorf - Initial contribution * @author Christoph Weitkamp - Refactoring of temperature conversion from celsius to FRITZ!Box values */ -@XmlRootElement(name = "temperature") +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(propOrder = { "celsius", "offset" }) +@XmlRootElement(name = "temperature") public class TemperatureModel { public static final BigDecimal TEMP_FACTOR = new BigDecimal("0.1"); @@ -51,6 +52,7 @@ public void setOffset(BigDecimal offset) { @Override public String toString() { - return new ToStringBuilder(this).append("celsius", getCelsius()).append("offset", getOffset()).toString(); + return new StringBuilder().append("[celsius=").append(getCelsius()).append(",offset=").append(getOffset()) + .append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/ApplyMaskListModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/ApplyMaskListModel.java similarity index 71% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/ApplyMaskListModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/ApplyMaskListModel.java index 508991e858020..185f763987d05 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/ApplyMaskListModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/ApplyMaskListModel.java @@ -10,22 +10,23 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel.templates; +package org.openhab.binding.avmfritz.internal.dto.templates; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@ TemplateModel}. * * @author Christoph Weitkamp - Initial contribution */ +@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "applymask") public class ApplyMaskListModel { @Override public String toString() { - return new ToStringBuilder(this).toString(); + return new StringBuilder().append("[]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/DeviceListModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/DeviceListModel.java similarity index 76% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/DeviceListModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/DeviceListModel.java index 3e509e5d6621b..29d7335b2c692 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/DeviceListModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/DeviceListModel.java @@ -10,21 +10,22 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel.templates; +package org.openhab.binding.avmfritz.internal.dto.templates; import java.util.Collections; import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@ TemplateModel}. * * @author Christoph Weitkamp - Initial contribution */ +@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "devices") public class DeviceListModel { @@ -40,6 +41,6 @@ public List getDevices() { @Override public String toString() { - return new ToStringBuilder(this).append(getDevices()).toString(); + return new StringBuilder().append("[devices=").append(devices).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/DeviceModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/DeviceModel.java similarity index 74% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/DeviceModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/DeviceModel.java index c76c4399488f4..be87391e641e8 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/DeviceModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/DeviceModel.java @@ -10,18 +10,19 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel.templates; +package org.openhab.binding.avmfritz.internal.dto.templates; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link DeviceListModel}. * * @author Christoph Weitkamp - Initial contribution */ +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "device") public class DeviceModel { @@ -34,6 +35,6 @@ public String getIdentifier() { @Override public String toString() { - return new ToStringBuilder(this).append("identifier", getIdentifier()).toString(); + return new StringBuilder().append("[identifier=").append(identifier).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/TemplateListModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateListModel.java similarity index 72% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/TemplateListModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateListModel.java index b3be020a88df3..39f661cf44b20 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/TemplateListModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateListModel.java @@ -10,20 +10,25 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel.templates; +package org.openhab.binding.avmfritz.internal.dto.templates; import java.util.Collections; import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; /** * This JAXB model class maps the XML response to an gettemplatelistinfos command on a FRITZ!Box device. * * @author Christoph Weitkamp - Initial contribution */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType @XmlRootElement(name = "templatelist") public class TemplateListModel { @@ -43,4 +48,10 @@ public List getTemplates() { public String getVersion() { return version; } + + @Override + public String toString() { + return new StringBuilder().append("[templates=").append(templates).append(",version=").append(version) + .append("]").toString(); + } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/TemplateModel.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateModel.java similarity index 73% rename from bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/TemplateModel.java rename to bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateModel.java index 10042d216909c..75822a89f0560 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/ahamodel/templates/TemplateModel.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/dto/templates/TemplateModel.java @@ -10,19 +10,20 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel.templates; +package org.openhab.binding.avmfritz.internal.dto.templates; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; -import org.apache.commons.lang.builder.ToStringBuilder; - /** * See {@link TemplateListModel}. * * @author Christoph Weitkamp - Initial contribution */ +@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "template") public class TemplateModel { @@ -69,8 +70,9 @@ public ApplyMaskListModel getApplyMaskList() { @Override public String toString() { - return new ToStringBuilder(this).append("identifier", getIdentifier()).append("id", getTemplateId()) - .append("functionbitmask", functionbitmask).append("applymask", applymask).append("name", getName()) - .append("devices", getDeviceList()).append("applymasks", getApplyMaskList()).toString(); + return new StringBuilder().append("[identifier=").append(identifier).append(",id=").append(templateId) + .append(",functionbitmask=").append(functionbitmask).append(",applymask=").append(applymask) + .append(",name=").append(name).append(",devices=").append(deviceList).append(",applymasks=") + .append(applyMaskList).append("]").toString(); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java index c9e9a7d092068..47ee8ed27f606 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseBridgeHandler.java @@ -12,38 +12,27 @@ */ package org.openhab.binding.avmfritz.internal.handler; -import static org.eclipse.smarthome.core.library.unit.SIUnits.CELSIUS; -import static org.eclipse.smarthome.core.thing.CommonTriggerEvents.PRESSED; -import static org.eclipse.smarthome.core.thing.Thing.PROPERTY_FIRMWARE_VERSION; import static org.openhab.binding.avmfritz.internal.BindingConstants.*; -import static org.openhab.binding.avmfritz.internal.ahamodel.DeviceModel.ETSUnitInfoModel.*; -import static org.openhab.binding.avmfritz.internal.ahamodel.HeatingModel.*; +import static org.openhab.binding.avmfritz.internal.dto.DeviceModel.ETSUnitInfoModel.*; -import java.math.BigDecimal; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; -import org.eclipse.smarthome.config.core.Configuration; -import org.eclipse.smarthome.core.library.types.DateTimeType; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.OpenClosedType; -import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; @@ -52,20 +41,20 @@ import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.StateOption; import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.avmfritz.internal.AVMFritzDynamicStateDescriptionProvider; import org.openhab.binding.avmfritz.internal.BindingConstants; -import org.openhab.binding.avmfritz.internal.ahamodel.AVMFritzBaseModel; -import org.openhab.binding.avmfritz.internal.ahamodel.AlertModel; -import org.openhab.binding.avmfritz.internal.ahamodel.DeviceModel; -import org.openhab.binding.avmfritz.internal.ahamodel.GroupModel; -import org.openhab.binding.avmfritz.internal.ahamodel.SwitchModel; -import org.openhab.binding.avmfritz.internal.ahamodel.templates.TemplateModel; -import org.openhab.binding.avmfritz.internal.config.AVMFritzConfiguration; +import org.openhab.binding.avmfritz.internal.config.AVMFritzBoxConfiguration; +import org.openhab.binding.avmfritz.internal.discovery.AVMFritzDiscoveryService; +import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel; +import org.openhab.binding.avmfritz.internal.dto.DeviceModel; +import org.openhab.binding.avmfritz.internal.dto.GroupModel; +import org.openhab.binding.avmfritz.internal.dto.templates.TemplateModel; +import org.openhab.binding.avmfritz.internal.hardware.FritzAhaStatusListener; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaApplyTemplateCallback; import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaUpdateCallback; @@ -108,6 +97,8 @@ public abstract class AVMFritzBaseBridgeHandler extends BaseBridgeHandler { private final AVMFritzDynamicStateDescriptionProvider stateDescriptionProvider; + protected final List listeners = new CopyOnWriteArrayList<>(); + /** * keeps track of the {@link ChannelUID} for the 'apply_tamplate' {@link Channel} */ @@ -127,41 +118,77 @@ public AVMFritzBaseBridgeHandler(Bridge bridge, HttpClient httpClient, applyTemplateChannelUID = new ChannelUID(bridge.getUID(), CHANNEL_APPLY_TEMPLATE); } - /** - * Initializes the bridge. - */ @Override public void initialize() { - logger.debug("About to initialize FRITZ!Box {}", BRIDGE_FRITZBOX); - AVMFritzConfiguration config = getConfigAs(AVMFritzConfiguration.class); + boolean configValid = true; + + AVMFritzBoxConfiguration config = getConfigAs(AVMFritzBoxConfiguration.class); - logger.debug("Discovered FRITZ!Box initialized: {}", config); + String localIpAddress = config.ipAddress; + if (localIpAddress == null || localIpAddress.trim().isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "The 'ipAddress' parameter must be configured."); + configValid = false; + } + String localPassword = config.password; + if (localPassword == null || localPassword.trim().isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No password set."); + configValid = false; + } + refreshInterval = config.pollingInterval; + if (refreshInterval < 5) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "The 'pollingInterval' parameter must be greater then at least 5 seconds."); + configValid = false; + } + + if (configValid) { + this.connection = new FritzAhaWebInterface(config, this, httpClient); - this.refreshInterval = config.getPollingInterval(); - this.connection = new FritzAhaWebInterface(config, this, httpClient); - if (config.getPassword() != null) { stopPolling(); startPolling(); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "no password set"); } } - /** - * Disposes the bridge. - */ @Override public void dispose() { - logger.debug("Handler disposed."); stopPolling(); } + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof FritzAhaStatusListener) { + registerStatusListener((FritzAhaStatusListener) childHandler); + } + } + + @Override + public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof FritzAhaStatusListener) { + unregisterStatusListener((FritzAhaStatusListener) childHandler); + } + } + + @Override + public Collection> getServices() { + return Collections.singleton(AVMFritzDiscoveryService.class); + } + + public boolean registerStatusListener(FritzAhaStatusListener listener) { + return listeners.add(listener); + } + + public boolean unregisterStatusListener(FritzAhaStatusListener listener) { + return listeners.remove(listener); + } + /** * Start the polling. */ private void startPolling() { - if (pollingJob == null || pollingJob.isCancelled()) { - logger.debug("start polling job at interval {}s", refreshInterval); + ScheduledFuture localPollingJob = pollingJob; + if (localPollingJob == null || localPollingJob.isCancelled()) { + logger.debug("Start polling job at interval {}s", refreshInterval); pollingJob = scheduler.scheduleWithFixedDelay(this::poll, INITIAL_DELAY, refreshInterval, TimeUnit.SECONDS); } } @@ -170,9 +197,10 @@ private void startPolling() { * Stops the polling. */ private void stopPolling() { - if (pollingJob != null && !pollingJob.isCancelled()) { - logger.debug("stop polling job"); - pollingJob.cancel(true); + ScheduledFuture localPollingJob = pollingJob; + if (localPollingJob != null && !localPollingJob.isCancelled()) { + logger.debug("Stop polling job"); + localPollingJob.cancel(true); pollingJob = null; } } @@ -183,11 +211,11 @@ private void stopPolling() { private void poll() { FritzAhaWebInterface webInterface = getWebInterface(); if (webInterface != null) { - logger.debug("Poll FRITZ!Box for updates {}", getThing().getUID()); + logger.debug("Poll FRITZ!Box for updates {}", thing.getUID()); FritzAhaUpdateCallback updateCallback = new FritzAhaUpdateCallback(webInterface, this); webInterface.asyncGet(updateCallback); if (isLinked(applyTemplateChannelUID)) { - logger.debug("Poll FRITZ!Box for templates {}", getThing().getUID()); + logger.debug("Poll FRITZ!Box for templates {}", thing.getUID()); FritzAhaUpdateTemplatesCallback templateCallback = new FritzAhaUpdateTemplatesCallback(webInterface, this); webInterface.asyncGet(templateCallback); @@ -222,209 +250,32 @@ public void addTemplateList(List templateList) { } /** - * Called from {@link FritzAhaUpdateCallback} to provide new values for things. + * Called from {@link FritzAhaUpdateCallback} to provide new devices. * - * @param deviceList list of device models + * @param deviceList list of devices */ - public void addDeviceList(List deviceList) { - for (Thing thing : getThing().getThings()) { - AVMFritzBaseThingHandler handler = (AVMFritzBaseThingHandler) thing.getHandler(); - if (handler != null) { - Optional optionalDevice = deviceList.stream() - .filter(it -> it.getIdentifier().equals(handler.getIdentifier())).findFirst(); + public void onDeviceListAdded(List deviceList) { + final Map deviceIdentifierMap = deviceList.stream() + .collect(Collectors.toMap(it -> it.getIdentifier(), Function.identity())); + getThing().getThings().forEach(childThing -> { + final AVMFritzBaseThingHandler childHandler = (AVMFritzBaseThingHandler) childThing.getHandler(); + if (childHandler != null) { + final Optional optionalDevice = Optional + .ofNullable(deviceIdentifierMap.get(childHandler.getIdentifier())); if (optionalDevice.isPresent()) { - AVMFritzBaseModel device = optionalDevice.get(); - logger.debug("update thing '{}' with device model: {}", thing.getUID(), device); - handler.setState(device); - if (device.getPresent() == 1) { - handler.setStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null); - updateThingFromDevice(thing, device); - } else { - handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Device not present"); - } - } else { - handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.GONE, - "Device not present in response"); - } - } else { - logger.debug("handler missing for thing '{}'", thing.getUID()); - } - } - } - - /** - * Updates thing from device model. - * - * @param thing Thing to be updated. - * @param device Device model with new data. - */ - protected void updateThingFromDevice(Thing thing, AVMFritzBaseModel device) { - thing.setProperty(PROPERTY_FIRMWARE_VERSION, device.getFirmwareVersion()); - if (device instanceof GroupModel && ((GroupModel) device).getGroupinfo() != null) { - thing.setProperty(PROPERTY_MASTER, ((GroupModel) device).getGroupinfo().getMasterdeviceid()); - thing.setProperty(PROPERTY_MEMBERS, ((GroupModel) device).getGroupinfo().getMembers()); - } - if (device instanceof DeviceModel && device.isTempSensor() && ((DeviceModel) device).getTemperature() != null) { - updateThingChannelState(thing, CHANNEL_TEMPERATURE, - new QuantityType<>(((DeviceModel) device).getTemperature().getCelsius(), CELSIUS)); - updateThingChannelConfiguration(thing, CHANNEL_TEMPERATURE, CONFIG_CHANNEL_TEMP_OFFSET, - ((DeviceModel) device).getTemperature().getOffset()); - } - if (device.isPowermeter() && device.getPowermeter() != null) { - updateThingChannelState(thing, CHANNEL_ENERGY, - new QuantityType<>(device.getPowermeter().getEnergy(), SmartHomeUnits.WATT_HOUR)); - updateThingChannelState(thing, CHANNEL_POWER, - new QuantityType<>(device.getPowermeter().getPower(), SmartHomeUnits.WATT)); - updateThingChannelState(thing, CHANNEL_VOLTAGE, - new QuantityType<>(device.getPowermeter().getVoltage(), SmartHomeUnits.VOLT)); - } - if (device.isSwitchableOutlet() && device.getSwitch() != null) { - updateThingChannelState(thing, CHANNEL_MODE, new StringType(device.getSwitch().getMode())); - updateThingChannelState(thing, CHANNEL_LOCKED, - BigDecimal.ZERO.equals(device.getSwitch().getLock()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); - updateThingChannelState(thing, CHANNEL_DEVICE_LOCKED, - BigDecimal.ZERO.equals(device.getSwitch().getDevicelock()) ? OpenClosedType.OPEN - : OpenClosedType.CLOSED); - if (device.getSwitch().getState() == null) { - updateThingChannelState(thing, CHANNEL_OUTLET, UnDefType.UNDEF); - } else { - updateThingChannelState(thing, CHANNEL_OUTLET, - SwitchModel.ON.equals(device.getSwitch().getState()) ? OnOffType.ON : OnOffType.OFF); - } - } - if (device.isHeatingThermostat() && device.getHkr() != null) { - updateThingChannelState(thing, CHANNEL_MODE, new StringType(device.getHkr().getMode())); - updateThingChannelState(thing, CHANNEL_LOCKED, - BigDecimal.ZERO.equals(device.getHkr().getLock()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); - updateThingChannelState(thing, CHANNEL_DEVICE_LOCKED, - BigDecimal.ZERO.equals(device.getHkr().getDevicelock()) ? OpenClosedType.OPEN - : OpenClosedType.CLOSED); - updateThingChannelState(thing, CHANNEL_ACTUALTEMP, - new QuantityType<>(toCelsius(device.getHkr().getTist()), CELSIUS)); - updateThingChannelState(thing, CHANNEL_SETTEMP, - new QuantityType<>(toCelsius(device.getHkr().getTsoll()), CELSIUS)); - updateThingChannelState(thing, CHANNEL_ECOTEMP, - new QuantityType<>(toCelsius(device.getHkr().getAbsenk()), CELSIUS)); - updateThingChannelState(thing, CHANNEL_COMFORTTEMP, - new QuantityType<>(toCelsius(device.getHkr().getKomfort()), CELSIUS)); - updateThingChannelState(thing, CHANNEL_RADIATOR_MODE, new StringType(device.getHkr().getRadiatorMode())); - if (device.getHkr().getNextchange() != null) { - if (device.getHkr().getNextchange().getEndperiod() == 0) { - updateThingChannelState(thing, CHANNEL_NEXT_CHANGE, UnDefType.UNDEF); - } else { - updateThingChannelState(thing, CHANNEL_NEXT_CHANGE, - new DateTimeType(ZonedDateTime.ofInstant( - Instant.ofEpochSecond(device.getHkr().getNextchange().getEndperiod()), - ZoneId.systemDefault()))); - } - if (TEMP_FRITZ_UNDEFINED.equals(device.getHkr().getNextchange().getTchange())) { - updateThingChannelState(thing, CHANNEL_NEXTTEMP, UnDefType.UNDEF); + final AVMFritzBaseModel device = optionalDevice.get(); + deviceList.remove(device); + listeners.forEach(listener -> listener.onDeviceUpdated(childThing.getUID(), device)); } else { - updateThingChannelState(thing, CHANNEL_NEXTTEMP, - new QuantityType<>(toCelsius(device.getHkr().getNextchange().getTchange()), CELSIUS)); + listeners.forEach(listener -> listener.onDeviceGone(childThing.getUID())); } - } - if (device.getHkr().getBattery() == null) { - updateThingChannelState(thing, CHANNEL_BATTERY, UnDefType.UNDEF); - } else { - updateThingChannelState(thing, CHANNEL_BATTERY, new DecimalType(device.getHkr().getBattery())); - } - if (device.getHkr().getBatterylow() == null) { - updateThingChannelState(thing, CHANNEL_BATTERY_LOW, UnDefType.UNDEF); - } else { - updateThingChannelState(thing, CHANNEL_BATTERY_LOW, - BATTERY_ON.equals(device.getHkr().getBatterylow()) ? OnOffType.ON : OnOffType.OFF); - } - } - if (device instanceof DeviceModel && device.isAlarmSensor() && ((DeviceModel) device).getAlert() != null) { - updateThingChannelState(thing, CHANNEL_CONTACT_STATE, - AlertModel.ON.equals(((DeviceModel) device).getAlert().getState()) ? OpenClosedType.OPEN - : OpenClosedType.CLOSED); - } - if (device instanceof DeviceModel && device.isButton() && ((DeviceModel) device).getButton() != null) { - if (((DeviceModel) device).getButton().getLastpressedtimestamp() == 0) { - updateThingChannelState(thing, CHANNEL_LAST_CHANGE, UnDefType.UNDEF); } else { - ZoneId zoneId = ZoneId.systemDefault(); - ZonedDateTime timestamp = ZonedDateTime.ofInstant( - Instant.ofEpochSecond(((DeviceModel) device).getButton().getLastpressedtimestamp()), zoneId); - Instant then = timestamp.toInstant(); - ZonedDateTime now = ZonedDateTime.now(zoneId); - Instant someSecondsEarlier = now.minusSeconds(refreshInterval).toInstant(); - if (then.isAfter(someSecondsEarlier) && then.isBefore(now.toInstant())) { - triggerThingChannel(thing, CHANNEL_PRESS, PRESSED); - } - updateThingChannelState(thing, CHANNEL_LAST_CHANGE, new DateTimeType(timestamp)); + logger.debug("Handler missing for thing '{}'", childThing.getUID()); } - } - } - - /** - * Updates thing channels. - * - * @param thing Thing which channels should be updated. - * @param channelId ID of the channel to be updated. - * @param state State to be set. - */ - private void updateThingChannelState(Thing thing, String channelId, State state) { - Channel channel = thing.getChannel(channelId); - if (channel != null) { - updateState(channel.getUID(), state); - } else { - logger.debug("Channel '{}' in thing '{}' does not exist, recreating thing.", channelId, thing.getUID()); - ThingHandler handler = thing.getHandler(); - if (handler != null) { - if (handler instanceof AVMFritzBaseThingHandler) { - ((AVMFritzBaseThingHandler) handler).createChannel(channelId); - } else if (handler instanceof Powerline546EHandler) { - ((Powerline546EHandler) handler).createChannel(channelId); - } - } - } - } - - /** - * Triggers thing channels. - * - * @param thing Thing which channels should be triggered. - * @param channelId ID of the channel to be triggered. - * @param event Event to emit - */ - private void triggerThingChannel(Thing thing, String channelId, String event) { - Channel channel = thing.getChannel(channelId); - if (channel != null) { - triggerChannel(channel.getUID(), event); - } else { - logger.debug("Channel '{}' in thing '{}' does not exist.", channelId, thing.getUID()); - } - } - - /** - * Updates thing channel configurations. - * - * @param thing Thing which channel configuration should be updated. - * @param channelId ID of the channel which configuration to be updated. - * @param configId ID of the configuration to be updated. - * @param value Value to be set. - */ - private void updateThingChannelConfiguration(Thing thing, String channelId, String configId, Object value) { - Channel channel = thing.getChannel(channelId); - if (channel != null) { - Configuration config = channel.getConfiguration(); - Configuration editConfig = new Configuration(new HashMap<>(config.getProperties())); - editConfig.put(configId, value); - config.setProperties(editConfig.getProperties()); - } - } - - /** - * Provides the web interface object. - * - * @return The web interface object - */ - @Nullable - public FritzAhaWebInterface getWebInterface() { - return connection; + }); + deviceList.forEach(device -> { + listeners.forEach(listener -> listener.onDeviceAdded(device)); + }); } /** @@ -435,10 +286,9 @@ public FritzAhaWebInterface getWebInterface() { * @param device Discovered device model * @return ThingUID without illegal characters. */ - @Nullable - public ThingUID getThingUID(AVMFritzBaseModel device) { + public @Nullable ThingUID getThingUID(AVMFritzBaseModel device) { ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, getThingTypeId(device)); - ThingUID bridgeUID = getThing().getUID(); + ThingUID bridgeUID = thing.getUID(); String thingName = getThingName(device); if (SUPPORTED_DEVICE_THING_TYPES_UIDS.contains(thingTypeUID)) { @@ -491,20 +341,42 @@ public void handleCommand(ChannelUID channelUID, Command command) { logger.debug("Handle command '{}' for channel {}", command, channelId); if (command == RefreshType.REFRESH) { handleRefreshCommand(); + return; } FritzAhaWebInterface fritzBox = getWebInterface(); if (fritzBox == null) { logger.debug("Cannot handle command '{}' because connection is missing", command); return; } - if (CHANNEL_APPLY_TEMPLATE.equals(channelId)) { - if (command instanceof StringType) { - fritzBox.applyTemplate(command.toString()); - } - updateState(CHANNEL_APPLY_TEMPLATE, UnDefType.UNDEF); + switch (channelId) { + case CHANNEL_APPLY_TEMPLATE: + applyTemplate(command, fritzBox); + break; + default: + logger.debug("Received unknown channel {}", channelId); + break; + } + } + + protected void applyTemplate(Command command, FritzAhaWebInterface fritzBox) { + if (command instanceof StringType) { + fritzBox.applyTemplate(command.toString()); } + updateState(CHANNEL_APPLY_TEMPLATE, UnDefType.UNDEF); + } + + /** + * Provides the web interface object. + * + * @return The web interface object + */ + public @Nullable FritzAhaWebInterface getWebInterface() { + return connection; } + /** + * Handles a refresh command. + */ public void handleRefreshCommand() { scheduler.submit(this::poll); } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseThingHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseThingHandler.java index de752c698766b..ed75edf2d55b0 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseThingHandler.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/AVMFritzBaseThingHandler.java @@ -12,35 +12,57 @@ */ package org.openhab.binding.avmfritz.internal.handler; -import static org.eclipse.smarthome.core.library.unit.SIUnits.CELSIUS; import static org.openhab.binding.avmfritz.internal.BindingConstants.*; -import static org.openhab.binding.avmfritz.internal.ahamodel.HeatingModel.*; +import static org.openhab.binding.avmfritz.internal.dto.HeatingModel.*; import java.math.BigDecimal; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Map; import javax.measure.quantity.Temperature; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.library.types.DateTimeType; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.library.unit.SIUnits; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.CommonTriggerEvents; +import org.eclipse.smarthome.core.thing.DefaultSystemChannelTypeProvider; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.thing.binding.BridgeHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerCallback; import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.avmfritz.internal.ahamodel.AVMFritzBaseModel; -import org.openhab.binding.avmfritz.internal.ahamodel.SwitchModel; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.avmfritz.internal.config.AVMFritzDeviceConfiguration; +import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel; +import org.openhab.binding.avmfritz.internal.dto.AlertModel; +import org.openhab.binding.avmfritz.internal.dto.ButtonModel; +import org.openhab.binding.avmfritz.internal.dto.DeviceModel; +import org.openhab.binding.avmfritz.internal.dto.HeatingModel; +import org.openhab.binding.avmfritz.internal.dto.HeatingModel.NextChangeModel; +import org.openhab.binding.avmfritz.internal.dto.PowerMeterModel; +import org.openhab.binding.avmfritz.internal.dto.SwitchModel; +import org.openhab.binding.avmfritz.internal.dto.TemperatureModel; +import org.openhab.binding.avmfritz.internal.hardware.FritzAhaStatusListener; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,15 +75,15 @@ * @author Christoph Weitkamp - Added support for groups */ @NonNullByDefault -public abstract class AVMFritzBaseThingHandler extends BaseThingHandler { +public abstract class AVMFritzBaseThingHandler extends BaseThingHandler implements FritzAhaStatusListener { private final Logger logger = LoggerFactory.getLogger(AVMFritzBaseThingHandler.class); /** * keeps track of the current state for handling of increase/decrease */ - @Nullable - private AVMFritzBaseModel state; + private @Nullable AVMFritzBaseModel state; + private @NonNullByDefault({}) AVMFritzDeviceConfiguration config; /** * Constructor @@ -74,19 +96,238 @@ public AVMFritzBaseThingHandler(Thing thing) { @Override public void initialize() { - logger.debug("Initializing handler for {}", getClass().getName()); - updateStatus(ThingStatus.UNKNOWN); + config = getConfigAs(AVMFritzDeviceConfiguration.class); + + String newIdentifier = config.ain; + if (newIdentifier == null || newIdentifier.trim().isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "The 'ain' parameter must be configured."); + } else { + updateStatus(ThingStatus.UNKNOWN); + } + } + + @Override + public void onDeviceAdded(AVMFritzBaseModel device) { + // nothing to do + } + + @Override + public void onDeviceUpdated(ThingUID thingUID, AVMFritzBaseModel device) { + if (thing.getUID().equals(thingUID)) { + logger.debug("Update thing '{}' with device model: {}", thingUID, device); + if (device.getPresent() == 1) { + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Device not present"); + } + state = device; + + updateProperties(device, editProperties()); + + if (device.isPowermeter()) { + updatePowermeter(device.getPowermeter()); + } + if (device.isSwitchableOutlet()) { + updateSwitchableOutlet(device.getSwitch()); + } + if (device.isHeatingThermostat()) { + updateHeatingThermostat(device.getHkr()); + } + if (device instanceof DeviceModel) { + DeviceModel deviceModel = (DeviceModel) device; + if (deviceModel.isTempSensor()) { + updateTemperatureSensor(deviceModel.getTemperature()); + } + if (deviceModel.isAlarmSensor()) { + updateAlarmSensor(deviceModel.getAlert()); + } + if (deviceModel.isButton()) { + updateButton(deviceModel.getButton()); + } + } + } + } + + private void updateButton(@Nullable ButtonModel buttonModel) { + if (buttonModel != null) { + int lastPressedTimestamp = buttonModel.getLastpressedtimestamp(); + if (lastPressedTimestamp == 0) { + updateThingChannelState(CHANNEL_LAST_CHANGE, UnDefType.UNDEF); + } else { + ZoneId zoneId = ZoneId.systemDefault(); + ZonedDateTime timestamp = ZonedDateTime.ofInstant(Instant.ofEpochSecond(lastPressedTimestamp), zoneId); + Instant then = timestamp.toInstant(); + ZonedDateTime now = ZonedDateTime.now(zoneId); + Instant someSecondsEarlier = now.minusSeconds(15).toInstant(); + if (then.isAfter(someSecondsEarlier) && then.isBefore(now.toInstant())) { + triggerThingChannel(CHANNEL_PRESS, CommonTriggerEvents.PRESSED); + } + updateThingChannelState(CHANNEL_LAST_CHANGE, new DateTimeType(timestamp)); + } + } + } + + private void updateAlarmSensor(@Nullable AlertModel alertModel) { + if (alertModel != null) { + updateThingChannelState(CHANNEL_CONTACT_STATE, + AlertModel.ON.equals(alertModel.getState()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + } + } + + private void updateTemperatureSensor(@Nullable TemperatureModel temperatureModel) { + if (temperatureModel != null) { + updateThingChannelState(CHANNEL_TEMPERATURE, + new QuantityType<>(temperatureModel.getCelsius(), SIUnits.CELSIUS)); + updateThingChannelConfiguration(CHANNEL_TEMPERATURE, CONFIG_CHANNEL_TEMP_OFFSET, + temperatureModel.getOffset()); + } + } + + private void updateHeatingThermostat(@Nullable HeatingModel heatingModel) { + if (heatingModel != null) { + updateThingChannelState(CHANNEL_MODE, new StringType(heatingModel.getMode())); + updateThingChannelState(CHANNEL_LOCKED, + BigDecimal.ZERO.equals(heatingModel.getLock()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + updateThingChannelState(CHANNEL_DEVICE_LOCKED, + BigDecimal.ZERO.equals(heatingModel.getDevicelock()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + updateThingChannelState(CHANNEL_ACTUALTEMP, + new QuantityType<>(toCelsius(heatingModel.getTist()), SIUnits.CELSIUS)); + updateThingChannelState(CHANNEL_SETTEMP, + new QuantityType<>(toCelsius(heatingModel.getTsoll()), SIUnits.CELSIUS)); + updateThingChannelState(CHANNEL_ECOTEMP, + new QuantityType<>(toCelsius(heatingModel.getAbsenk()), SIUnits.CELSIUS)); + updateThingChannelState(CHANNEL_COMFORTTEMP, + new QuantityType<>(toCelsius(heatingModel.getKomfort()), SIUnits.CELSIUS)); + updateThingChannelState(CHANNEL_RADIATOR_MODE, new StringType(heatingModel.getRadiatorMode())); + NextChangeModel nextChange = heatingModel.getNextchange(); + if (nextChange != null) { + int endPeriod = nextChange.getEndperiod(); + updateThingChannelState(CHANNEL_NEXT_CHANGE, endPeriod == 0 ? UnDefType.UNDEF + : new DateTimeType( + ZonedDateTime.ofInstant(Instant.ofEpochSecond(endPeriod), ZoneId.systemDefault()))); + BigDecimal nextTemperature = nextChange.getTchange(); + updateThingChannelState(CHANNEL_NEXTTEMP, TEMP_FRITZ_UNDEFINED.equals(nextTemperature) ? UnDefType.UNDEF + : new QuantityType<>(toCelsius(nextTemperature), SIUnits.CELSIUS)); + } + BigDecimal batteryLevel = heatingModel.getBattery(); + updateThingChannelState(CHANNEL_BATTERY, + batteryLevel == null ? UnDefType.UNDEF : new DecimalType(batteryLevel)); + BigDecimal lowBattery = heatingModel.getBatterylow(); + if (lowBattery == null) { + updateThingChannelState(CHANNEL_BATTERY_LOW, UnDefType.UNDEF); + } else { + updateThingChannelState(CHANNEL_BATTERY_LOW, + BATTERY_ON.equals(lowBattery) ? OnOffType.ON : OnOffType.OFF); + } + } + } + + private void updateSwitchableOutlet(@Nullable SwitchModel switchModel) { + if (switchModel != null) { + updateThingChannelState(CHANNEL_MODE, new StringType(switchModel.getMode())); + updateThingChannelState(CHANNEL_LOCKED, + BigDecimal.ZERO.equals(switchModel.getLock()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + updateThingChannelState(CHANNEL_DEVICE_LOCKED, + BigDecimal.ZERO.equals(switchModel.getDevicelock()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + BigDecimal state = switchModel.getState(); + if (state == null) { + updateThingChannelState(CHANNEL_OUTLET, UnDefType.UNDEF); + } else { + updateThingChannelState(CHANNEL_OUTLET, SwitchModel.ON.equals(state) ? OnOffType.ON : OnOffType.OFF); + } + } + } + + private void updatePowermeter(@Nullable PowerMeterModel powerMeterModel) { + if (powerMeterModel != null) { + updateThingChannelState(CHANNEL_ENERGY, + new QuantityType<>(powerMeterModel.getEnergy(), SmartHomeUnits.WATT_HOUR)); + updateThingChannelState(CHANNEL_POWER, new QuantityType<>(powerMeterModel.getPower(), SmartHomeUnits.WATT)); + updateThingChannelState(CHANNEL_VOLTAGE, + new QuantityType<>(powerMeterModel.getVoltage(), SmartHomeUnits.VOLT)); + } } /** - * Called from {@link AVMFritzBaseBridgeHandler)} to update the thing status because updateStatus is protected. + * Updates thing properties. * - * @param status Thing status - * @param statusDetail Thing status detail - * @param description Thing status description + * @param device the {@link AVMFritzBaseModel} + * @param editProperties map of existing properties */ - public void setStatusInfo(ThingStatus status, ThingStatusDetail statusDetail, @Nullable String description) { - updateStatus(status, statusDetail, description); + protected void updateProperties(AVMFritzBaseModel device, Map editProperties) { + editProperties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.getFirmwareVersion()); + updateProperties(editProperties); + } + + /** + * Updates thing channels and creates dynamic channels if missing. + * + * @param channelId ID of the channel to be updated. + * @param state State to be set. + */ + private void updateThingChannelState(String channelId, State state) { + Channel channel = thing.getChannel(channelId); + if (channel != null) { + updateState(channel.getUID(), state); + } else { + logger.debug("Channel '{}' in thing '{}' does not exist, recreating thing.", channelId, thing.getUID()); + createChannel(channelId); + } + } + + /** + * Creates new channels for the thing. + * + * @param channelId ID of the channel to be created. + */ + private void createChannel(String channelId) { + ThingHandlerCallback callback = getCallback(); + if (callback != null) { + ChannelUID channelUID = new ChannelUID(thing.getUID(), channelId); + ChannelTypeUID channelTypeUID = CHANNEL_BATTERY.equals(channelId) + ? DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_BATTERY_LEVEL.getUID() + : new ChannelTypeUID(BINDING_ID, channelId); + Channel channel = callback.createChannelBuilder(channelUID, channelTypeUID).build(); + updateThing(editThing().withoutChannel(channelUID).withChannel(channel).build()); + } + } + + /** + * Triggers thing channels. + * + * @param channelId ID of the channel to be triggered. + * @param event Event to emit + */ + private void triggerThingChannel(String channelId, String event) { + Channel channel = thing.getChannel(channelId); + if (channel != null) { + triggerChannel(channel.getUID(), event); + } else { + logger.debug("Channel '{}' in thing '{}' does not exist.", channelId, thing.getUID()); + } + } + + /** + * Updates thing channel configurations. + * + * @param channelId ID of the channel which configuration to be updated. + * @param configId ID of the configuration to be updated. + * @param value Value to be set. + */ + private void updateThingChannelConfiguration(String channelId, String configId, Object value) { + Channel channel = thing.getChannel(channelId); + if (channel != null) { + Configuration editConfig = channel.getConfiguration(); + editConfig.put(configId, value); + } + } + + @Override + public void onDeviceGone(ThingUID thingUID) { + if (thing.getUID().equals(thingUID)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.GONE, "Device not present in response"); + } } @Override @@ -94,14 +335,8 @@ public void handleCommand(ChannelUID channelUID, Command command) { String channelId = channelUID.getIdWithoutGroup(); logger.debug("Handle command '{}' for channel {}", command, channelId); if (command == RefreshType.REFRESH) { - Bridge bridge = getBridge(); - if (bridge != null) { - BridgeHandler bridgeHandler = bridge.getHandler(); - if (bridgeHandler != null && bridgeHandler instanceof AVMFritzBaseBridgeHandler) { - ((AVMFritzBaseBridgeHandler) bridgeHandler).handleRefreshCommand(); - return; - } - } + handleRefreshCommand(); + return; } FritzAhaWebInterface fritzBox = getWebInterface(); if (fritzBox == null) { @@ -134,74 +369,65 @@ public void handleCommand(ChannelUID channelUID, Command command) { break; case CHANNEL_OUTLET: if (command instanceof OnOffType) { - state.getSwitch().setState(OnOffType.ON.equals(command) ? SwitchModel.ON : SwitchModel.OFF); fritzBox.setSwitch(ain, OnOffType.ON.equals(command)); + if (state != null) { + state.getSwitch().setState(OnOffType.ON.equals(command) ? SwitchModel.ON : SwitchModel.OFF); + } } break; case CHANNEL_SETTEMP: + BigDecimal temperature = null; if (command instanceof DecimalType) { - BigDecimal temperature = normalizeCelsius(((DecimalType) command).toBigDecimal()); - state.getHkr().setTsoll(temperature); - fritzBox.setSetTemp(ain, fromCelsius(temperature)); - updateState(CHANNEL_RADIATOR_MODE, new StringType(state.getHkr().getRadiatorMode())); + temperature = normalizeCelsius(((DecimalType) command).toBigDecimal()); } else if (command instanceof QuantityType) { - BigDecimal temperature = normalizeCelsius( - ((QuantityType) command).toUnit(CELSIUS).toBigDecimal()); - state.getHkr().setTsoll(temperature); - fritzBox.setSetTemp(ain, fromCelsius(temperature)); - updateState(CHANNEL_RADIATOR_MODE, new StringType(state.getHkr().getRadiatorMode())); + temperature = normalizeCelsius( + ((QuantityType) command).toUnit(SIUnits.CELSIUS).toBigDecimal()); } else if (command instanceof IncreaseDecreaseType) { - BigDecimal temperature = state.getHkr().getTsoll(); + temperature = state.getHkr().getTsoll(); if (IncreaseDecreaseType.INCREASE.equals(command)) { temperature.add(BigDecimal.ONE); } else { temperature.subtract(BigDecimal.ONE); } - state.getHkr().setTsoll(temperature); - fritzBox.setSetTemp(ain, temperature); - updateState(CHANNEL_RADIATOR_MODE, new StringType(state.getHkr().getRadiatorMode())); } else if (command instanceof OnOffType) { - BigDecimal temperature = OnOffType.ON.equals(command) ? TEMP_FRITZ_ON : TEMP_FRITZ_OFF; - state.getHkr().setTsoll(temperature); - fritzBox.setSetTemp(ain, temperature); - updateState(CHANNEL_RADIATOR_MODE, new StringType(state.getHkr().getRadiatorMode())); + temperature = OnOffType.ON.equals(command) ? TEMP_FRITZ_ON : TEMP_FRITZ_OFF; + } + if (temperature != null) { + fritzBox.setSetTemp(ain, fromCelsius(temperature)); + HeatingModel heatingModel = state.getHkr(); + heatingModel.setTsoll(temperature); + updateState(CHANNEL_RADIATOR_MODE, new StringType(heatingModel.getRadiatorMode())); } break; case CHANNEL_RADIATOR_MODE: + BigDecimal targetTemperature = null; if (command instanceof StringType) { switch (command.toString()) { case MODE_ON: - state.getHkr().setTsoll(TEMP_FRITZ_ON); - fritzBox.setSetTemp(ain, TEMP_FRITZ_ON); - updateState(CHANNEL_SETTEMP, new QuantityType<>(toCelsius(TEMP_FRITZ_ON), CELSIUS)); + targetTemperature = TEMP_FRITZ_ON; break; case MODE_OFF: - state.getHkr().setTsoll(TEMP_FRITZ_OFF); - fritzBox.setSetTemp(ain, TEMP_FRITZ_OFF); - updateState(CHANNEL_SETTEMP, new QuantityType<>(toCelsius(TEMP_FRITZ_OFF), CELSIUS)); + targetTemperature = TEMP_FRITZ_OFF; break; case MODE_COMFORT: - BigDecimal comfortTemperature = state.getHkr().getKomfort(); - state.getHkr().setTsoll(comfortTemperature); - fritzBox.setSetTemp(ain, comfortTemperature); - updateState(CHANNEL_SETTEMP, new QuantityType<>(toCelsius(comfortTemperature), CELSIUS)); + targetTemperature = state.getHkr().getKomfort(); break; case MODE_ECO: - BigDecimal ecoTemperature = state.getHkr().getAbsenk(); - state.getHkr().setTsoll(ecoTemperature); - fritzBox.setSetTemp(ain, ecoTemperature); - updateState(CHANNEL_SETTEMP, new QuantityType<>(toCelsius(ecoTemperature), CELSIUS)); + targetTemperature = state.getHkr().getAbsenk(); break; case MODE_BOOST: - state.getHkr().setTsoll(TEMP_FRITZ_MAX); - fritzBox.setSetTemp(ain, TEMP_FRITZ_MAX); - updateState(CHANNEL_SETTEMP, new QuantityType<>(toCelsius(TEMP_FRITZ_MAX), CELSIUS)); + targetTemperature = TEMP_FRITZ_MAX; break; case MODE_UNKNOWN: case MODE_WINDOW_OPEN: logger.debug("Command '{}' is a read-only command for channel {}.", command, channelId); break; } + if (targetTemperature != null) { + fritzBox.setSetTemp(ain, targetTemperature); + state.getHkr().setTsoll(targetTemperature); + updateState(CHANNEL_SETTEMP, new QuantityType<>(toCelsius(targetTemperature), SIUnits.CELSIUS)); + } } break; default: @@ -210,52 +436,41 @@ public void handleCommand(ChannelUID channelUID, Command command) { } } - /** - * Creates new channels for the thing. - * - * @param channelId ID of the channel to be created. - */ - public void createChannel(String channelId) { - ThingHandlerCallback callback = getCallback(); - if (callback != null) { - ChannelUID channelUID = new ChannelUID(thing.getUID(), channelId); - ChannelTypeUID channelTypeUID = CHANNEL_BATTERY.equals(channelId) - ? new ChannelTypeUID("system:battery-level") - : new ChannelTypeUID(BINDING_ID, channelId); - Channel channel = callback.createChannelBuilder(channelUID, channelTypeUID).build(); - updateThing(editThing().withoutChannel(channelUID).withChannel(channel).build()); - } - } - /** * Provides the web interface object. * * @return The web interface object */ - @Nullable - protected FritzAhaWebInterface getWebInterface() { + private @Nullable FritzAhaWebInterface getWebInterface() { Bridge bridge = getBridge(); if (bridge != null) { BridgeHandler handler = bridge.getHandler(); - if (handler != null && handler instanceof AVMFritzBaseBridgeHandler) { + if (handler instanceof AVMFritzBaseBridgeHandler) { return ((AVMFritzBaseBridgeHandler) handler).getWebInterface(); } } return null; } - @Nullable - public String getIdentifier() { - Object ain = getThing().getConfiguration().get(CONFIG_AIN); - return ain != null ? ain.toString() : null; - } - - @Nullable - public AVMFritzBaseModel getState() { - return state; + /** + * Handles a refresh command. + */ + private void handleRefreshCommand() { + Bridge bridge = getBridge(); + if (bridge != null) { + BridgeHandler handler = bridge.getHandler(); + if (handler instanceof AVMFritzBaseBridgeHandler) { + ((AVMFritzBaseBridgeHandler) handler).handleRefreshCommand(); + } + } } - public void setState(AVMFritzBaseModel state) { - this.state = state; + /** + * Returns the AIN. + * + * @return the AIN + */ + public @Nullable String getIdentifier() { + return config.ain; } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/GroupHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/GroupHandler.java index ba5048ef77914..fde74878a8d32 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/GroupHandler.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/GroupHandler.java @@ -12,8 +12,14 @@ */ package org.openhab.binding.avmfritz.internal.handler; +import static org.openhab.binding.avmfritz.internal.BindingConstants.*; + +import java.util.Map; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.Thing; +import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel; +import org.openhab.binding.avmfritz.internal.dto.GroupModel; /** * Handler for a FRITZ! group. Handles commands, which are sent to one of the channels. @@ -31,4 +37,16 @@ public class GroupHandler extends AVMFritzBaseThingHandler { public GroupHandler(Thing thing) { super(thing); } + + @Override + protected void updateProperties(AVMFritzBaseModel device, Map editProperties) { + if (device instanceof GroupModel) { + GroupModel groupModel = (GroupModel) device; + if (groupModel.getGroupinfo() != null) { + editProperties.put(PROPERTY_MASTER, groupModel.getGroupinfo().getMasterdeviceid()); + editProperties.put(PROPERTY_MEMBERS, groupModel.getGroupinfo().getMembers()); + } + } + super.updateProperties(device, editProperties); + } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java index d9ae2584f05a6..d741ef497b525 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/handler/Powerline546EHandler.java @@ -14,18 +14,25 @@ import static org.openhab.binding.avmfritz.internal.BindingConstants.*; +import java.math.BigDecimal; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.function.Predicate; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.DefaultSystemChannelTypeProvider; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; @@ -35,12 +42,16 @@ import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.avmfritz.internal.AVMFritzDynamicStateDescriptionProvider; import org.openhab.binding.avmfritz.internal.BindingConstants; -import org.openhab.binding.avmfritz.internal.ahamodel.AVMFritzBaseModel; -import org.openhab.binding.avmfritz.internal.ahamodel.SwitchModel; -import org.openhab.binding.avmfritz.internal.config.AVMFritzConfiguration; +import org.openhab.binding.avmfritz.internal.config.AVMFritzBoxConfiguration; +import org.openhab.binding.avmfritz.internal.config.AVMFritzDeviceConfiguration; +import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel; +import org.openhab.binding.avmfritz.internal.dto.PowerMeterModel; +import org.openhab.binding.avmfritz.internal.dto.SwitchModel; +import org.openhab.binding.avmfritz.internal.hardware.FritzAhaStatusListener; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,15 +64,15 @@ * @author Christoph Weitkamp - Added support for groups */ @NonNullByDefault -public class Powerline546EHandler extends AVMFritzBaseBridgeHandler { +public class Powerline546EHandler extends AVMFritzBaseBridgeHandler implements FritzAhaStatusListener { private final Logger logger = LoggerFactory.getLogger(Powerline546EHandler.class); /** * keeps track of the current state for handling of increase/decrease */ - @Nullable - private AVMFritzBaseModel state; + private @Nullable AVMFritzBaseModel state; + private @Nullable AVMFritzDeviceConfiguration config; /** * Constructor @@ -74,41 +85,155 @@ public Powerline546EHandler(Bridge bridge, HttpClient httpClient, } @Override - public void addDeviceList(List devicelist) { - String identifier = getIdentifier(); - Predicate predicate = identifier == null ? it -> getThing().getUID().equals(getThingUID(it)) - : it -> it.getIdentifier().equals(identifier); - Optional optionalDevice = devicelist.stream().filter(predicate).findFirst(); + public void initialize() { + config = getConfigAs(AVMFritzDeviceConfiguration.class); + + registerStatusListener(this); + + super.initialize(); + } + + @Override + public void dispose() { + unregisterStatusListener(this); + + super.dispose(); + } + + @Override + public void onDeviceListAdded(List devicelist) { + final String identifier = getIdentifier(); + final Predicate predicate = identifier == null ? it -> thing.getUID().equals(getThingUID(it)) + : it -> identifier.equals(it.getIdentifier()); + final Optional optionalDevice = devicelist.stream().filter(predicate).findFirst(); if (optionalDevice.isPresent()) { - AVMFritzBaseModel device = optionalDevice.get(); + final AVMFritzBaseModel device = optionalDevice.get(); devicelist.remove(device); - logger.debug("update self '{}' with device model: {}", getThing().getUID(), device); - setState(device); + listeners.stream().forEach(listener -> listener.onDeviceUpdated(thing.getUID(), device)); + } else { + listeners.stream().forEach(listener -> listener.onDeviceGone(thing.getUID())); + } + super.onDeviceListAdded(devicelist); + } + + @Override + public void onDeviceAdded(AVMFritzBaseModel device) { + // nothing to do + } + + @Override + public void onDeviceUpdated(ThingUID thingUID, AVMFritzBaseModel device) { + if (thing.getUID().equals(thingUID)) { + // save AIN to config for FRITZ!Powerline 546E stand-alone + if (config == null) { + updateConfiguration(device); + } + + logger.debug("Update self '{}' with device model: {}", thingUID, device); if (device.getPresent() == 1) { - setStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, null); - updateThingFromDevice(getThing(), device); + updateStatus(ThingStatus.ONLINE); } else { - setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Device not present"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Device not present"); } + state = device; + + updateProperties(device); + + if (device.isPowermeter()) { + updatePowermeter(device.getPowermeter()); + } + if (device.isSwitchableOutlet()) { + updateSwitchableOutlet(device.getSwitch()); + } + } + } + + private void updateSwitchableOutlet(@Nullable SwitchModel switchModel) { + if (switchModel != null) { + updateThingChannelState(CHANNEL_MODE, new StringType(switchModel.getMode())); + updateThingChannelState(CHANNEL_LOCKED, + BigDecimal.ZERO.equals(switchModel.getLock()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + updateThingChannelState(CHANNEL_DEVICE_LOCKED, + BigDecimal.ZERO.equals(switchModel.getDevicelock()) ? OpenClosedType.OPEN : OpenClosedType.CLOSED); + BigDecimal state = switchModel.getState(); + if (state == null) { + updateThingChannelState(CHANNEL_OUTLET, UnDefType.UNDEF); + } else { + updateThingChannelState(CHANNEL_OUTLET, SwitchModel.ON.equals(state) ? OnOffType.ON : OnOffType.OFF); + } + } + } + + private void updatePowermeter(@Nullable PowerMeterModel powerMeterModel) { + if (powerMeterModel != null) { + updateThingChannelState(CHANNEL_ENERGY, + new QuantityType<>(powerMeterModel.getEnergy(), SmartHomeUnits.WATT_HOUR)); + updateThingChannelState(CHANNEL_POWER, new QuantityType<>(powerMeterModel.getPower(), SmartHomeUnits.WATT)); + updateThingChannelState(CHANNEL_VOLTAGE, + new QuantityType<>(powerMeterModel.getVoltage(), SmartHomeUnits.VOLT)); + } + } + + /** + * Updates thing properties. + * + * @param device the {@link AVMFritzBaseModel} + */ + private void updateProperties(AVMFritzBaseModel device) { + Map editProperties = editProperties(); + editProperties.put(Thing.PROPERTY_FIRMWARE_VERSION, device.getFirmwareVersion()); + updateProperties(editProperties); + } + + /** + * Updates thing configuration. + * + * @param device the {@link AVMFritzBaseModel} + */ + private void updateConfiguration(AVMFritzBaseModel device) { + Configuration editConfig = editConfiguration(); + editConfig.put(CONFIG_AIN, device.getIdentifier()); + updateConfiguration(editConfig); + } + + /** + * Updates thing channels and creates dynamic channels if missing. + * + * @param channelId ID of the channel to be updated. + * @param state State to be set. + */ + private void updateThingChannelState(String channelId, State state) { + Channel channel = thing.getChannel(channelId); + if (channel != null) { + updateState(channel.getUID(), state); } else { - setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.GONE, "Device not present in response"); + logger.debug("Channel '{}' in thing '{}' does not exist, recreating thing.", channelId, thing.getUID()); + createChannel(channelId); } - super.addDeviceList(devicelist); } /** - * Updates things from device model. + * Creates new channels for the thing. * - * @param thing Thing to be updated. - * @param device Device model with new data. + * @param channelId ID of the channel to be created. */ + private void createChannel(String channelId) { + ThingHandlerCallback callback = getCallback(); + if (callback != null) { + ChannelUID channelUID = new ChannelUID(thing.getUID(), channelId); + ChannelTypeUID channelTypeUID = CHANNEL_BATTERY.equals(channelId) + ? DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_BATTERY_LEVEL.getUID() + : new ChannelTypeUID(BINDING_ID, channelId); + Channel channel = callback.createChannelBuilder(channelUID, channelTypeUID).build(); + updateThing(editThing().withoutChannel(channelUID).withChannel(channel).build()); + } + } + @Override - protected void updateThingFromDevice(Thing thing, AVMFritzBaseModel device) { - // save AIN to config for FRITZ!Powerline 546E stand-alone - if (thing.getConfiguration().get(CONFIG_AIN) == null) { - thing.getConfiguration().put(CONFIG_AIN, device.getIdentifier()); + public void onDeviceGone(ThingUID thingUID) { + if (thing.getUID().equals(thingUID)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.GONE, "Device not present in response"); } - super.updateThingFromDevice(thing, device); } /** @@ -121,10 +246,9 @@ protected void updateThingFromDevice(Thing thing, AVMFritzBaseModel device) { * @return ThingUID without illegal characters. */ @Override - @Nullable - public ThingUID getThingUID(AVMFritzBaseModel device) { + public @Nullable ThingUID getThingUID(AVMFritzBaseModel device) { ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, getThingTypeId(device).concat("_Solo")); - String ipAddress = getConfigAs(AVMFritzConfiguration.class).getIpAddress(); + String ipAddress = getConfigAs(AVMFritzBoxConfiguration.class).ipAddress; if (PL546E_STANDALONE_THING_TYPE.equals(thingTypeUID)) { String thingName = "fritz.powerline".equals(ipAddress) ? ipAddress @@ -163,15 +287,14 @@ public void handleCommand(ChannelUID channelUID, Command command) { logger.debug("Channel {} is a read-only channel and cannot handle command '{}'", channelId, command); break; case CHANNEL_APPLY_TEMPLATE: - if (command instanceof StringType) { - fritzBox.applyTemplate(command.toString()); - } - updateState(CHANNEL_APPLY_TEMPLATE, UnDefType.UNDEF); + applyTemplate(command, fritzBox); break; case CHANNEL_OUTLET: + fritzBox.setSwitch(ain, OnOffType.ON.equals(command)); if (command instanceof OnOffType) { - state.getSwitch().setState(OnOffType.ON.equals(command) ? SwitchModel.ON : SwitchModel.OFF); - fritzBox.setSwitch(ain, OnOffType.ON.equals(command)); + if (state != null) { + state.getSwitch().setState(OnOffType.ON.equals(command) ? SwitchModel.ON : SwitchModel.OFF); + } } break; default: @@ -181,35 +304,12 @@ public void handleCommand(ChannelUID channelUID, Command command) { } /** - * Creates new channels for the thing. + * Returns the AIN. * - * @param channelId ID of the channel to be created. + * @return the AIN */ - public void createChannel(String channelId) { - ThingHandlerCallback callback = getCallback(); - if (callback != null) { - ChannelUID channelUID = new ChannelUID(thing.getUID(), channelId); - ChannelTypeUID channelTypeUID = CHANNEL_BATTERY.equals(channelId) - ? new ChannelTypeUID("system:battery-level") - : new ChannelTypeUID(BINDING_ID, channelId); - - Channel channel = callback.createChannelBuilder(channelUID, channelTypeUID).build(); - updateThing(editThing().withoutChannel(channelUID).withChannel(channel).build()); - } - } - - @Nullable - public String getIdentifier() { - Object ain = getThing().getConfiguration().get(CONFIG_AIN); - return ain != null ? ain.toString() : null; - } - - @Nullable - public AVMFritzBaseModel getState() { - return state; - } - - public void setState(AVMFritzBaseModel state) { - this.state = state; + public @Nullable String getIdentifier() { + AVMFritzDeviceConfiguration localConfig = config; + return localConfig != null ? localConfig.ain : null; } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaContentExchange.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaContentExchange.java index 8245c7ad8481c..ac2fb61083d2a 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaContentExchange.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaContentExchange.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.avmfritz.internal.hardware; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response.CompleteListener; import org.eclipse.jetty.client.api.Response.ContentListener; @@ -28,17 +29,16 @@ * * @author Robert Bausdorf - Initial contribution */ +@NonNullByDefault public class FritzAhaContentExchange extends BufferingResponseListener implements SuccessListener, FailureListener, ContentListener, CompleteListener { - /** - * logger - */ - private final Logger logger = LoggerFactory.getLogger(getClass()); + + private final Logger logger = LoggerFactory.getLogger(FritzAhaContentExchange.class); /** * Callback to execute on complete response */ - private FritzAhaCallback callback; + private final FritzAhaCallback callback; /** * Constructor @@ -49,28 +49,20 @@ public FritzAhaContentExchange(FritzAhaCallback callback) { this.callback = callback; } - /** - * Log request success - */ @Override - public void onSuccess(Response response) { + public void onSuccess(@NonNullByDefault({}) Response response) { logger.debug("{} response: {}", response.getRequest().getScheme().toUpperCase(), response.getStatus()); } - /** - * Log request failure - */ @Override - public void onFailure(Response response, Throwable failure) { - logger.debug("response failed: {}", failure.getLocalizedMessage()); + public void onFailure(@NonNullByDefault({}) Response response, @NonNullByDefault({}) Throwable failure) { + logger.debug("response failed: {}", failure.getLocalizedMessage(), failure); } - /** - * Call the callbacks execute method on request completion. - */ @Override - public void onComplete(Result result) { - logger.debug("response complete: {}", this.getContentAsString()); - this.callback.execute(result.getResponse().getStatus(), this.getContentAsString()); + public void onComplete(@NonNullByDefault({}) Result result) { + String content = getContentAsString(); + logger.debug("response complete: {}", content); + callback.execute(result.getResponse().getStatus(), content); } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaStatusListener.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaStatusListener.java new file mode 100644 index 0000000000000..40c3ec86aa758 --- /dev/null +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaStatusListener.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.avmfritz.internal.hardware; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.avmfritz.internal.dto.AVMFritzBaseModel; + +/** + * The {@link FritzAhaStatusListener} is notified when a new device has been added, removed or its status has changed. + * + * @author Christoph Weitkamp - Initial contribution + */ +@NonNullByDefault +public interface FritzAhaStatusListener { + + /** + * This method is called whenever a device is added. + * + * @param device the {@link AVMFritzBaseModel} + */ + void onDeviceAdded(AVMFritzBaseModel device); + + /** + * This method is called whenever a device is updated. + * + * @param thingUID the {@link ThingUID} + * @param device the {@link AVMFritzBaseModel} + */ + void onDeviceUpdated(ThingUID thingUID, AVMFritzBaseModel device); + + /** + * This method is called whenever a device is gone. + * + * @param thingUID the {@link ThingUID} + */ + void onDeviceGone(ThingUID thingUID); +} diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaWebInterface.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaWebInterface.java index c7fe6b40f9cd7..936b0a8c2eb1b 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaWebInterface.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/FritzAhaWebInterface.java @@ -24,13 +24,14 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.util.StringContentProvider; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.openhab.binding.avmfritz.internal.config.AVMFritzConfiguration; +import org.openhab.binding.avmfritz.internal.config.AVMFritzBoxConfiguration; import org.openhab.binding.avmfritz.internal.handler.AVMFritzBaseBridgeHandler; import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaApplyTemplateCallback; import org.openhab.binding.avmfritz.internal.hardware.callbacks.FritzAhaCallback; @@ -48,110 +49,110 @@ * DECT * @author Christoph Weitkamp - Added support for groups */ +@NonNullByDefault public class FritzAhaWebInterface { - private final Logger logger = LoggerFactory.getLogger(FritzAhaWebInterface.class); + private static final String WEBSERVICE_PATH = "login_sid.lua"; /** - * Configuration of the bridge from {@link AVMFritzBaseBridgeHandler} + * RegEx Pattern to grab the session ID from a login XML response */ - protected AVMFritzConfiguration config; + private static final Pattern SID_PATTERN = Pattern.compile("([a-fA-F0-9]*)"); /** - * Current session ID + * RegEx Pattern to grab the challenge from a login XML response */ - protected String sid; + private static final Pattern CHALLENGE_PATTERN = Pattern.compile("(\\w*)"); /** - * Shared instance of HTTP client for asynchronous calls + * RegEx Pattern to grab the access privilege for home automation functions from a login XML response */ - protected HttpClient httpClient; + private static final Pattern ACCESS_PATTERN = Pattern.compile("HomeAuto\\s*?([0-9])"); + + private final Logger logger = LoggerFactory.getLogger(FritzAhaWebInterface.class); /** - * Bridge thing handler for updating thing status + * Configuration of the bridge from {@link AVMFritzBaseBridgeHandler} */ - protected AVMFritzBaseBridgeHandler handler; - - private static final String WEBSERVICE_PATH = "login_sid.lua"; - // Uses RegEx to handle bad FRITZ!Box XML + private final AVMFritzBoxConfiguration config; /** - * RegEx Pattern to grab the session ID from a login XML response + * Bridge thing handler for updating thing status */ - protected static final Pattern SID_PATTERN = Pattern.compile("([a-fA-F0-9]*)"); + private final AVMFritzBaseBridgeHandler handler; /** - * RegEx Pattern to grab the challenge from a login XML response + * Shared instance of HTTP client for asynchronous calls */ - protected static final Pattern CHALLENGE_PATTERN = Pattern.compile("(\\w*)"); + private final HttpClient httpClient; /** - * RegEx Pattern to grab the access privilege for home automation functions from a login XML response + * Current session ID */ - protected static final Pattern ACCESS_PATTERN = Pattern - .compile("HomeAuto\\s*?([0-9])"); + private @Nullable String sid; /** * This method authenticates with the FRITZ!OS Web Interface and updates the session ID accordingly - * - * @return New session ID */ - @Nullable - public String authenticate() { + public void authenticate() { sid = null; - if (config.getPassword() == null) { + String localPassword = config.password; + if (localPassword == null || localPassword.trim().isEmpty()) { handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Please configure password first"); - return null; + return; } String loginXml = syncGet(getURL(WEBSERVICE_PATH, addSID(""))); if (loginXml == null) { handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "FRITZ!Box does not respond"); - return null; + return; } Matcher sidmatch = SID_PATTERN.matcher(loginXml); if (!sidmatch.find()) { handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "FRITZ!Box does not respond with SID"); - return null; + return; } - sid = sidmatch.group(1); + String localSid = sidmatch.group(1); Matcher accmatch = ACCESS_PATTERN.matcher(loginXml); if (accmatch.find()) { if ("2".equals(accmatch.group(1))) { + sid = localSid; handler.setStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, - "Resuming FRITZ!Box connection with SID " + sid); - return sid; + "Resuming FRITZ!Box connection with SID: " + localSid); + return; } } Matcher challengematch = CHALLENGE_PATTERN.matcher(loginXml); if (!challengematch.find()) { handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "FRITZ!Box does not respond with challenge for authentication"); - return null; + return; } String challenge = challengematch.group(1); String response = createResponse(challenge); + String localUser = config.user; loginXml = syncGet(getURL(WEBSERVICE_PATH, - (config.getUser() != null && !"".equals(config.getUser()) ? ("username=" + config.getUser() + "&") : "") - + "response=" + response)); + (localUser == null || localUser.isEmpty() ? "" : ("username=" + localUser + "&")) + "response=" + + response)); if (loginXml == null) { handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "FRITZ!Box does not respond"); - return null; + return; } sidmatch = SID_PATTERN.matcher(loginXml); if (!sidmatch.find()) { handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "FRITZ!Box does not respond with SID"); - return null; + return; } - sid = sidmatch.group(1); + localSid = sidmatch.group(1); accmatch = ACCESS_PATTERN.matcher(loginXml); if (accmatch.find()) { if ("2".equals(accmatch.group(1))) { + sid = localSid; handler.setStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.NONE, - "Established FRITZ!Box connection with SID " + sid); - return sid; + "Established FRITZ!Box connection with SID: " + localSid); + return; } } - handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "User " + config.getUser() + " has no access to FRITZ!Box home automation functions"); - return null; + handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "User " + + (localUser == null ? "" : localUser) + " has no access to FRITZ!Box home automation functions"); + return; } /** @@ -160,15 +161,7 @@ public String authenticate() { * @return */ public boolean isAuthenticated() { - return !(sid == null); - } - - public AVMFritzConfiguration getConfig() { - return config; - } - - public void setConfig(AVMFritzConfiguration config) { - this.config = config; + return sid != null; } /** @@ -178,7 +171,8 @@ public void setConfig(AVMFritzConfiguration config) { * @return Response to the challenge */ protected String createResponse(String challenge) { - String handshake = challenge.concat("-").concat(config.getPassword()); + String response = challenge.concat("-"); + String handshake = response.concat(config.password); MessageDigest md5; try { md5 = MessageDigest.getInstance("MD5"); @@ -187,7 +181,6 @@ protected String createResponse(String challenge) { return ""; } byte[] handshakeHash = md5.digest(handshake.getBytes(StandardCharsets.UTF_16LE)); - String response = challenge.concat("-"); for (byte handshakeByte : handshakeHash) { response = response.concat(String.format("%02x", handshakeByte)); } @@ -199,12 +192,11 @@ protected String createResponse(String challenge) { * * @param config Bridge configuration */ - public FritzAhaWebInterface(AVMFritzConfiguration config, AVMFritzBaseBridgeHandler handler, + public FritzAhaWebInterface(AVMFritzBoxConfiguration config, AVMFritzBaseBridgeHandler handler, HttpClient httpClient) { this.config = config; this.handler = handler; this.httpClient = httpClient; - sid = null; authenticate(); logger.debug("Starting with SID {}", sid); } @@ -216,8 +208,7 @@ public FritzAhaWebInterface(AVMFritzConfiguration config, AVMFritzBaseBridgeHand * @return URL */ public String getURL(String path) { - return config.getProtocol() + "://" + config.getIpAddress() - + (config.getPort() != null ? ":" + config.getPort() : "") + "/" + path; + return config.protocol + "://" + config.ipAddress + (config.port == null ? "" : ":" + config.port) + "/" + path; } /** @@ -228,14 +219,14 @@ public String getURL(String path) { * @return URL */ public String getURL(String path, String args) { - return getURL("".equals(args) ? path : path + "?" + args); + return getURL(args.isEmpty() ? path : path + "?" + args); } - public String addSID(@Nullable String args) { + public String addSID(String path) { if (sid == null) { - return args; + return path; } else { - return ("".equals(args) ? ("sid=") : (args + "&sid=")) + sid; + return (path.isEmpty() ? "" : path + "&") + "sid=" + sid; } } @@ -245,16 +236,15 @@ public String addSID(@Nullable String args) { * @param path Path of the requested resource * @return response */ - @Nullable - public String syncGet(String url) { + public @Nullable String syncGet(String url) { try { ContentResponse contentResponse = httpClient.newRequest(url) - .timeout(config.getSyncTimeout(), TimeUnit.MILLISECONDS).method(GET).send(); + .timeout(config.syncTimeout, TimeUnit.MILLISECONDS).method(GET).send(); String content = contentResponse.getContentAsString(); - logger.debug("Response complete: {}", content); + logger.debug("GET response complete: {}", content); return content; } catch (ExecutionException | InterruptedException | TimeoutException e) { - logger.debug("Failed to GET url '{}': {}", url, e.getLocalizedMessage(), e); + logger.debug("response failed: {}", e.getLocalizedMessage(), e); return null; } } @@ -272,8 +262,7 @@ public FritzAhaContentExchange asyncGet(String path, String args, FritzAhaCallba } FritzAhaContentExchange getExchange = new FritzAhaContentExchange(callback); httpClient.newRequest(getURL(path, addSID(args))).method(GET).onResponseSuccess(getExchange) - .onResponseFailure(getExchange) // .onComplete(getExchange) - .send(getExchange); + .onResponseFailure(getExchange).send(getExchange); return getExchange; } @@ -293,8 +282,8 @@ public FritzAhaContentExchange asyncPost(String path, String args, FritzAhaCallb authenticate(); } FritzAhaContentExchange postExchange = new FritzAhaContentExchange(callback); - httpClient.newRequest(getURL(path)).timeout(config.getAsyncTimeout(), TimeUnit.SECONDS).method(POST) - .onResponseSuccess(postExchange).onResponseFailure(postExchange) // .onComplete(postExchange) + httpClient.newRequest(getURL(path)).timeout(config.asyncTimeout, TimeUnit.MILLISECONDS).method(POST) + .onResponseSuccess(postExchange).onResponseFailure(postExchange) .content(new StringContentProvider(addSID(args), StandardCharsets.UTF_8)).send(postExchange); return postExchange; } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaApplyTemplateCallback.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaApplyTemplateCallback.java index 0a9f15bf0f44f..4b752268e5645 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaApplyTemplateCallback.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaApplyTemplateCallback.java @@ -14,6 +14,7 @@ import static org.eclipse.jetty.http.HttpMethod.GET; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,6 +24,7 @@ * * @author Christoph Weitkamp - Initial contribution */ +@NonNullByDefault public class FritzAhaApplyTemplateCallback extends FritzAhaReauthCallback { private final Logger logger = LoggerFactory.getLogger(FritzAhaApplyTemplateCallback.class); diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaCallback.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaCallback.java index 6383e64bf20a3..ee6ea8a500c04 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaCallback.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaCallback.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.avmfritz.internal.hardware.callbacks; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Interface for callbacks in asynchronous requests. * * @author Robert Bausdorf - Initial contribution */ +@NonNullByDefault public interface FritzAhaCallback { /** * Runs callback code after response completion. diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaDiscoveryCallback.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaDiscoveryCallback.java deleted file mode 100644 index e35b97c96cf4c..0000000000000 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaDiscoveryCallback.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.avmfritz.internal.hardware.callbacks; - -import static org.eclipse.jetty.http.HttpMethod.GET; - -import java.io.StringReader; - -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; - -import org.openhab.binding.avmfritz.internal.ahamodel.AVMFritzBaseModel; -import org.openhab.binding.avmfritz.internal.ahamodel.DeviceListModel; -import org.openhab.binding.avmfritz.internal.discovery.AVMFritzDiscoveryService; -import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; -import org.openhab.binding.avmfritz.internal.util.JAXBUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Callback for discovering SmartHome devices connected to a FRITZ!Box - * - * @author Robert Bausdorf - Initial contribution - * @author Christoph Weitkamp - Added support for AVM FRITZ!DECT 300 and Comet - * DECT - * @author Christoph Weitkamp - Added support for groups - */ -public class FritzAhaDiscoveryCallback extends FritzAhaReauthCallback { - - private final Logger logger = LoggerFactory.getLogger(FritzAhaDiscoveryCallback.class); - - /** - * Handler to update - */ - private AVMFritzDiscoveryService service; - - /** - * Constructor - * - * @param webIface Webinterface to FRITZ!Box - * @param service Discovery service to call with result. - */ - public FritzAhaDiscoveryCallback(FritzAhaWebInterface webIface, AVMFritzDiscoveryService service) { - super(WEBSERVICE_PATH, "switchcmd=getdevicelistinfos", webIface, GET, 1); - this.service = service; - } - - @Override - public void execute(int status, String response) { - super.execute(status, response); - logger.trace("Received discovery callback response: {}", response); - if (isValidRequest()) { - try { - Unmarshaller u = JAXBUtils.JAXBCONTEXT_DEVICES.createUnmarshaller(); - DeviceListModel model = (DeviceListModel) u.unmarshal(new StringReader(response)); - if (model != null) { - for (AVMFritzBaseModel device : model.getDevicelist()) { - service.onDeviceAddedInternal(device); - } - } else { - logger.debug("no model in response"); - } - } catch (JAXBException e) { - logger.error("Exception creating Unmarshaller: {}", e.getLocalizedMessage(), e); - } - } else { - logger.debug("request is invalid: {}", status); - } - } -} diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaReauthCallback.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaReauthCallback.java index bb74e93719380..d821afcc7bd22 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaReauthCallback.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaReauthCallback.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.avmfritz.internal.hardware.callbacks; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jetty.http.HttpMethod; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; @@ -20,37 +21,38 @@ * * @author Robert Bausdorf, Christian Brauers - Initial contribution */ +@NonNullByDefault public class FritzAhaReauthCallback implements FritzAhaCallback { public static final String WEBSERVICE_PATH = "webservices/homeautoswitch.lua"; /** * Path to HTTP interface */ - private String path; + private final String path; /** * Arguments to use */ - private String args; + private final String args; /** * Web interface to use */ - private FritzAhaWebInterface webIface; + private final FritzAhaWebInterface webIface; /** * Method used */ - private HttpMethod httpMethod; + private final HttpMethod httpMethod; /** * Number of remaining retries */ private int retries; - /** - * Whether the request returned a valid response - */ - private boolean validRequest; /** * Callback to execute on next retry */ private FritzAhaCallback retryCallback; + /** + * Whether the request returned a valid response + */ + private boolean validRequest; /** * Returns whether the request returned a valid response @@ -71,14 +73,12 @@ public boolean isFinalAttempt() { } /** - * Sets different Callback to use on retry (initial value: same callback - * after decremented retry counter) + * Sets different Callback to use on retry (initial value: same callback after decremented retry counter) * - * @param newRetryCallback - * Callback to retry with + * @param retryCallback Callback to retry with */ - public void setRetryCallback(FritzAhaCallback newRetryCallback) { - retryCallback = newRetryCallback; + public void setRetryCallback(FritzAhaCallback retryCallback) { + this.retryCallback = retryCallback; } @Override diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetHeatingTemperatureCallback.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetHeatingTemperatureCallback.java index 290d8aca7146e..cba76bf380273 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetHeatingTemperatureCallback.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetHeatingTemperatureCallback.java @@ -16,6 +16,7 @@ import java.math.BigDecimal; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,32 +28,32 @@ * @author Christoph Weitkamp - Added support for AVM FRITZ!DECT 300 and Comet * DECT */ +@NonNullByDefault public class FritzAhaSetHeatingTemperatureCallback extends FritzAhaReauthCallback { private final Logger logger = LoggerFactory.getLogger(FritzAhaSetHeatingTemperatureCallback.class); - /** - * Item to update - */ - private String itemName; + private static final String WEBSERVICE_COMMAND = "switchcmd=sethkrtsoll"; + + private final String ain; /** * Constructor * - * @param webIface Interface to FRITZ!Box - * @param ain AIN of the device that should be switched + * @param webIface Interface to FRITZ!Box + * @param ain AIN of the device that should be switched * @param temperature New temperature */ public FritzAhaSetHeatingTemperatureCallback(FritzAhaWebInterface webIface, String ain, BigDecimal temperature) { - super(WEBSERVICE_PATH, "ain=" + ain + "&switchcmd=sethkrtsoll¶m=" + temperature, webIface, GET, 1); - itemName = ain; + super(WEBSERVICE_PATH, WEBSERVICE_COMMAND + "&ain=" + ain + "¶m=" + temperature, webIface, GET, 1); + this.ain = ain; } @Override public void execute(int status, String response) { super.execute(status, response); if (isValidRequest()) { - logger.debug("Received State response {} for item {}", response, itemName); + logger.debug("Received response '{}' for item '{}'", response, ain); } } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetSwitchCallback.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetSwitchCallback.java index d5c3e04883ec5..8843b29870d45 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetSwitchCallback.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaSetSwitchCallback.java @@ -14,6 +14,7 @@ import static org.eclipse.jetty.http.HttpMethod.GET; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,31 +24,31 @@ * * @author Robert Bausdorf - Initial contribution */ +@NonNullByDefault public class FritzAhaSetSwitchCallback extends FritzAhaReauthCallback { - private final Logger logger = LoggerFactory.getLogger(getClass()); - /** - * Item to update - */ - private String itemName; + + private final Logger logger = LoggerFactory.getLogger(FritzAhaSetSwitchCallback.class); + + private final String ain; /** * Constructor * * @param webIface Interface to FRITZ!Box - * @param ain AIN of the device that should be switched + * @param ain AIN of the device that should be switched * @param switchOn true - switch on, false - switch off */ public FritzAhaSetSwitchCallback(FritzAhaWebInterface webIface, String ain, boolean switchOn) { - super(WEBSERVICE_PATH, "ain=" + ain + "&switchcmd=" + (switchOn ? "setswitchon" : "setswitchoff"), webIface, + super(WEBSERVICE_PATH, "switchcmd=" + (switchOn ? "setswitchon" : "setswitchoff") + "&ain=" + ain, webIface, GET, 1); - itemName = ain; + this.ain = ain; } @Override public void execute(int status, String response) { super.execute(status, response); if (isValidRequest()) { - logger.debug("Received State response {} for item {}", response, itemName); + logger.debug("Received response '{}' for item '{}'", response, ain); } } } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateCallback.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateCallback.java index a98c3d6686f0d..e07702f507b6f 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateCallback.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateCallback.java @@ -19,9 +19,10 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.openhab.binding.avmfritz.internal.ahamodel.DeviceListModel; +import org.openhab.binding.avmfritz.internal.dto.DeviceListModel; import org.openhab.binding.avmfritz.internal.handler.AVMFritzBaseBridgeHandler; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; import org.openhab.binding.avmfritz.internal.util.JAXBUtils; @@ -35,14 +36,14 @@ * @author Robert Bausdorf - Initial contribution * @author Christoph Weitkamp - Added support for groups */ +@NonNullByDefault public class FritzAhaUpdateCallback extends FritzAhaReauthCallback { private final Logger logger = LoggerFactory.getLogger(FritzAhaUpdateCallback.class); - /** - * Handler to update - */ - private AVMFritzBaseBridgeHandler handler; + private static final String WEBSERVICE_COMMAND = "switchcmd=getdevicelistinfos"; + + private final AVMFritzBaseBridgeHandler handler; /** * Constructor @@ -51,7 +52,7 @@ public class FritzAhaUpdateCallback extends FritzAhaReauthCallback { * @param handler Bridge handler that will update things. */ public FritzAhaUpdateCallback(FritzAhaWebInterface webIface, AVMFritzBaseBridgeHandler handler) { - super(WEBSERVICE_PATH, "switchcmd=getdevicelistinfos", webIface, GET, 1); + super(WEBSERVICE_PATH, WEBSERVICE_COMMAND, webIface, GET, 1); this.handler = handler; } @@ -61,10 +62,10 @@ public void execute(int status, String response) { logger.trace("Received State response {}", response); if (isValidRequest()) { try { - Unmarshaller u = JAXBUtils.JAXBCONTEXT_DEVICES.createUnmarshaller(); - DeviceListModel model = (DeviceListModel) u.unmarshal(new StringReader(response)); + Unmarshaller unmarshaller = JAXBUtils.JAXBCONTEXT_DEVICES.createUnmarshaller(); + DeviceListModel model = (DeviceListModel) unmarshaller.unmarshal(new StringReader(response)); if (model != null) { - handler.addDeviceList(model.getDevicelist()); + handler.onDeviceListAdded(model.getDevicelist()); } else { logger.debug("no model in response"); } diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateTemplatesCallback.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateTemplatesCallback.java index 31955c59bd804..cb950a2a8e1e6 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateTemplatesCallback.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/hardware/callbacks/FritzAhaUpdateTemplatesCallback.java @@ -19,7 +19,8 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; -import org.openhab.binding.avmfritz.internal.ahamodel.templates.TemplateListModel; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.avmfritz.internal.dto.templates.TemplateListModel; import org.openhab.binding.avmfritz.internal.handler.AVMFritzBaseBridgeHandler; import org.openhab.binding.avmfritz.internal.hardware.FritzAhaWebInterface; import org.openhab.binding.avmfritz.internal.util.JAXBUtils; @@ -31,6 +32,7 @@ * * @author Christoph Weitkamp - Initial contribution */ +@NonNullByDefault public class FritzAhaUpdateTemplatesCallback extends FritzAhaReauthCallback { private final Logger logger = LoggerFactory.getLogger(FritzAhaUpdateTemplatesCallback.class); diff --git a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/util/JAXBUtils.java b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/util/JAXBUtils.java index 734333eef771e..e1316cf8d0c35 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/util/JAXBUtils.java +++ b/bundles/org.openhab.binding.avmfritz/src/main/java/org/openhab/binding/avmfritz/internal/util/JAXBUtils.java @@ -17,8 +17,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.avmfritz.internal.ahamodel.DeviceListModel; -import org.openhab.binding.avmfritz.internal.ahamodel.templates.TemplateListModel; +import org.openhab.binding.avmfritz.internal.dto.DeviceListModel; +import org.openhab.binding.avmfritz.internal.dto.templates.TemplateListModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/config/config.xml index 6934c281ffcf3..e9fd9f655d4f9 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/config/config.xml @@ -23,11 +23,11 @@ The local IP address or hostname of the FRITZ!Box. fritz.box
- + Port of the FRITZ!Box. - + Protocol to connect to the FRITZ!Box (http or https). http @@ -36,7 +36,7 @@ - + User name which has HomeAuto permissions on the given FRITZ!Box. @@ -45,20 +45,17 @@ Password to access the FRITZ!Box. - + Interval polling the FRITZ!Box (in seconds). 15 - + Timeout for asynchronous connections (in milliseconds). 10000 - + Timeout for synchronous connections (in milliseconds). 2000 @@ -89,11 +86,11 @@ The localIP address or hostname of the FRITZ!Powerline. fritz.powerline - + Port of the FRITZ!Powerline. - + Protocol to connect to the FRITZ!Powerline (http or https). http @@ -107,20 +104,17 @@ Password to access the FRITZ!Powerline. - + Interval polling the FRITZ!Powerline (in seconds). 15 - + Timeout for asynchronous connections (in milliseconds). 10000 - + Timeout for synchronous connections (in milliseconds). 2000 @@ -142,7 +136,7 @@
- + Current temperature offset (in °C). 0 diff --git a/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/bridge-types.xml b/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/bridge-types.xml index 3baf1d84574f5..e99d649931f72 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/bridge-types.xml +++ b/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/bridge-types.xml @@ -10,10 +10,10 @@ This bridge represents a FRITZ!Box. - + - + @@ -21,15 +21,15 @@ FRITZ!Powerline 546E with switchable outlet in stand-alone mode. - - - - - - - + + + + + + + - +
diff --git a/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/channel-types.xml index 05bb38c688e88..505758b019ff4 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/channel-types.xml @@ -9,7 +9,7 @@ String Apply template for device(s). - + @@ -31,7 +31,7 @@ Device is locked for switching over external sources. Contact - + @@ -39,7 +39,7 @@ Device is locked for switching by pressing the button on the device. Contact - + @@ -48,9 +48,9 @@ Current measured temperature. Temperature - + - + @@ -58,7 +58,7 @@ Accumulated energy consumption. Energy - + @@ -66,7 +66,7 @@ Current power consumption. Energy - + @@ -74,7 +74,7 @@ Current voltage. Energy - + @@ -89,7 +89,7 @@ Current measured temperature. Temperature - + @@ -97,7 +97,7 @@ Thermostat Setpoint temperature. Temperature - + @@ -105,7 +105,7 @@ Thermostat Eco temperature. Temperature - + @@ -113,7 +113,7 @@ Thermostat Comfort temperature. Temperature - + @@ -137,7 +137,7 @@ Next change of Setpoint Temperature. Time - + @@ -145,7 +145,7 @@ Next Setpoint Temperature. Temperature - + @@ -153,7 +153,7 @@ Contact state information (OPEN/CLOSED). Contact - + @@ -161,6 +161,6 @@ States the last time the button was pressed. Time - +
diff --git a/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/thing-types.xml index b251b0fda53c8..03a46a87bd0a5 100644 --- a/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.avmfritz/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,143 +7,143 @@ - - + + Comet DECT heating thermostat. - - - - - - - - - - - - + + + + + + + + + + + + ain - + - - + + FRITZ!DECT 301 heating thermostat. - - - - - - - - - - - - + + + + + + + + + + + + ain - + - - + + FRITZ!DECT 300 heating thermostat. - - - - - - - - - - - - + + + + + + + + + + + + ain - + - - + + FRITZ!DECT210 switchable outlet. - - - - - - - + + + + + + + ain - + - - + + FRITZ!DECT200 switchable outlet. - - - - - - - + + + + + + + ain - + - - + + @@ -151,59 +151,59 @@ - - - - - - + + + + + + ain - + - - + + FRITZ!DECT Repeater 100 DECT repeater. - + ain - + - - + + HAN-FUN contact (e.g. SmartHome Tür-/Fensterkontakt or SmartHome Bewegungsmelder). - + ain - + - - + + @@ -214,63 +214,63 @@ Triggered when a button was pressed. - + ain - + - - + + Group for heating thermostats. - - - - - - - - - - - + + + + + + + + + + + ain - + - - + + Group for switchable outlets and power meters. - - - - - - + + + + + + ain - +
diff --git a/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzDeviceListModelTest.java b/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzDeviceListModelTest.java similarity index 99% rename from bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzDeviceListModelTest.java rename to bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzDeviceListModelTest.java index 0a743776fc6d5..e6ea03fe02ba2 100644 --- a/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzDeviceListModelTest.java +++ b/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzDeviceListModelTest.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import static org.junit.Assert.*; import static org.openhab.binding.avmfritz.internal.BindingConstants.*; @@ -22,6 +22,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.Before; import org.junit.Test; import org.openhab.binding.avmfritz.internal.util.JAXBUtils; @@ -33,11 +34,12 @@ * * @author Christoph Weitkamp - Initial contribution */ +@NonNullByDefault public class AVMFritzDeviceListModelTest { private final Logger logger = LoggerFactory.getLogger(AVMFritzDeviceListModelTest.class); - private DeviceListModel devices; + private @NonNullByDefault({}) DeviceListModel devices; @Before public void setUp() { diff --git a/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzTemplateListModelTest.java b/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzTemplateListModelTest.java similarity index 91% rename from bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzTemplateListModelTest.java rename to bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzTemplateListModelTest.java index b00707aaad810..6f333090e915f 100644 --- a/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/AVMFritzTemplateListModelTest.java +++ b/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/AVMFritzTemplateListModelTest.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import static org.junit.Assert.*; @@ -20,10 +20,11 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.Before; import org.junit.Test; -import org.openhab.binding.avmfritz.internal.ahamodel.templates.TemplateListModel; -import org.openhab.binding.avmfritz.internal.ahamodel.templates.TemplateModel; +import org.openhab.binding.avmfritz.internal.dto.templates.TemplateListModel; +import org.openhab.binding.avmfritz.internal.dto.templates.TemplateModel; import org.openhab.binding.avmfritz.internal.util.JAXBUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,11 +34,12 @@ * * @author Christoph Weitkamp - Initial contribution */ +@NonNullByDefault public class AVMFritzTemplateListModelTest { private final Logger logger = LoggerFactory.getLogger(AVMFritzTemplateListModelTest.class); - private TemplateListModel templates; + private @NonNullByDefault({}) TemplateListModel templates; @Before public void setUp() { diff --git a/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/HeatingModelTest.java b/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/HeatingModelTest.java similarity index 95% rename from bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/HeatingModelTest.java rename to bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/HeatingModelTest.java index 8292fe288cd3b..af7bf9ea4a35d 100644 --- a/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/ahamodel/HeatingModelTest.java +++ b/bundles/org.openhab.binding.avmfritz/src/test/java/org/openhab/binding/avmfritz/internal/dto/HeatingModelTest.java @@ -10,12 +10,13 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.avmfritz.internal.ahamodel; +package org.openhab.binding.avmfritz.internal.dto; import static org.junit.Assert.assertEquals; import java.math.BigDecimal; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.Test; /** @@ -23,6 +24,7 @@ * * @author Christoph Weitkamp - Initial contribution */ +@NonNullByDefault public class HeatingModelTest { private static final BigDecimal BIGDECIMAL_FOURTEEN = new BigDecimal("14.0"); diff --git a/bundles/org.openhab.binding.bigassfan/pom.xml b/bundles/org.openhab.binding.bigassfan/pom.xml index a7db44b67711b..3eaab2c4e4c5b 100644 --- a/bundles/org.openhab.binding.bigassfan/pom.xml +++ b/bundles/org.openhab.binding.bigassfan/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bigassfan diff --git a/bundles/org.openhab.binding.bigassfan/src/main/feature/feature.xml b/bundles/org.openhab.binding.bigassfan/src/main/feature/feature.xml index a1fe880d1f1d2..581e6047e683b 100644 --- a/bundles/org.openhab.binding.bigassfan/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bigassfan/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.bigassfan/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.bigassfan/${project.version} + diff --git a/bundles/org.openhab.binding.bigassfan/src/main/java/org/openhab/binding/bigassfan/internal/BigAssFanHandlerFactory.java b/bundles/org.openhab.binding.bigassfan/src/main/java/org/openhab/binding/bigassfan/internal/BigAssFanHandlerFactory.java index 6ccd5f6fc4b1c..8ef5ccbba6d07 100644 --- a/bundles/org.openhab.binding.bigassfan/src/main/java/org/openhab/binding/bigassfan/internal/BigAssFanHandlerFactory.java +++ b/bundles/org.openhab.binding.bigassfan/src/main/java/org/openhab/binding/bigassfan/internal/BigAssFanHandlerFactory.java @@ -14,6 +14,8 @@ import static org.openhab.binding.bigassfan.internal.BigAssFanBindingConstants.SUPPORTED_THING_TYPES_UIDS; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.net.NetworkAddressService; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; @@ -21,6 +23,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.openhab.binding.bigassfan.internal.handler.BigAssFanHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -30,10 +33,16 @@ * * @author Mark Hilbush - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.bigassfan") public class BigAssFanHandlerFactory extends BaseThingHandlerFactory { - private NetworkAddressService networkAddressService; + private final NetworkAddressService networkAddressService; + + @Activate + public BigAssFanHandlerFactory(@Reference NetworkAddressService networkAddressService) { + this.networkAddressService = networkAddressService; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -41,21 +50,11 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { return new BigAssFanHandler(thing, networkAddressService.getPrimaryIpv4HostAddress()); } return null; } - - @Reference - protected void setNetworkAddressService(NetworkAddressService networkAddressService) { - this.networkAddressService = networkAddressService; - } - - protected void unsetNetworkAddressService(NetworkAddressService networkAddressService) { - this.networkAddressService = null; - } - } diff --git a/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/binding/binding.xml index 6ae5c5744cadf..664ec1389cc1a 100644 --- a/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - BigAssFan Binding diff --git a/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/config/config.xml index 794fe12edd6ae..5413ad64981d5 100644 --- a/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/thing/thing-types.xml index c5f02ec0f18da..cf256e18a326c 100644 --- a/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.bigassfan/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -10,36 +11,36 @@ - - + + - - - - - - - - - + + + + + + + + + - - - - - - - + + + + + + + - + - + - + @@ -49,20 +50,20 @@ - - - - - + + + + + - + - + - + @@ -71,11 +72,11 @@ Wall controller for Big Ass Fan - - + + - + diff --git a/bundles/org.openhab.binding.bluetooth.airthings/pom.xml b/bundles/org.openhab.binding.bluetooth.airthings/pom.xml index 643394a1a4886..07931a7a5a4d0 100644 --- a/bundles/org.openhab.binding.bluetooth.airthings/pom.xml +++ b/bundles/org.openhab.binding.bluetooth.airthings/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bluetooth.airthings diff --git a/bundles/org.openhab.binding.bluetooth.airthings/src/main/feature/feature.xml b/bundles/org.openhab.binding.bluetooth.airthings/src/main/feature/feature.xml index e173dbc0692fd..61515fa537b95 100644 --- a/bundles/org.openhab.binding.bluetooth.airthings/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bluetooth.airthings/src/main/feature/feature.xml @@ -1,12 +1,12 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.airthings/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.airthings/${project.version} + diff --git a/bundles/org.openhab.binding.bluetooth.airthings/src/main/java/org/openhab/binding/bluetooth/airthings/internal/AirthingsDiscoveryParticipant.java b/bundles/org.openhab.binding.bluetooth.airthings/src/main/java/org/openhab/binding/bluetooth/airthings/internal/AirthingsDiscoveryParticipant.java index a0fbb98fd77a2..b243c55194125 100644 --- a/bundles/org.openhab.binding.bluetooth.airthings/src/main/java/org/openhab/binding/bluetooth/airthings/internal/AirthingsDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.bluetooth.airthings/src/main/java/org/openhab/binding/bluetooth/airthings/internal/AirthingsDiscoveryParticipant.java @@ -25,7 +25,7 @@ import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.openhab.binding.bluetooth.BluetoothBindingConstants; -import org.openhab.binding.bluetooth.BluetoothDevice; +import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryDevice; import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryParticipant; import org.osgi.service.component.annotations.Component; @@ -49,8 +49,7 @@ public Set getSupportedThingTypeUIDs() { } @Override - @Nullable - public ThingUID getThingUID(BluetoothDevice device) { + public @Nullable ThingUID getThingUID(BluetoothDiscoveryDevice device) { if (isAirthingsDevice(device)) { if (WAVE_PLUS_MODEL.equals(device.getModel())) { return new ThingUID(AirthingsBindingConstants.THING_TYPE_AIRTHINGS_WAVE_PLUS, @@ -61,8 +60,7 @@ public ThingUID getThingUID(BluetoothDevice device) { } @Override - @Nullable - public DiscoveryResult createResult(BluetoothDevice device) { + public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device) { if (!isAirthingsDevice(device)) { return null; } @@ -77,11 +75,11 @@ public DiscoveryResult createResult(BluetoothDevice device) { } @Override - public boolean requiresConnection(BluetoothDevice device) { + public boolean requiresConnection(BluetoothDiscoveryDevice device) { return isAirthingsDevice(device); } - private boolean isAirthingsDevice(BluetoothDevice device) { + private boolean isAirthingsDevice(BluetoothDiscoveryDevice device) { Integer manufacturerId = device.getManufacturerId(); if (manufacturerId != null && manufacturerId == AIRTHINGS_COMPANY_ID) { return true; @@ -89,7 +87,7 @@ private boolean isAirthingsDevice(BluetoothDevice device) { return false; } - private DiscoveryResult createWavePlus(BluetoothDevice device, ThingUID thingUID) { + private DiscoveryResult createWavePlus(BluetoothDiscoveryDevice device, ThingUID thingUID) { Map properties = new HashMap<>(); properties.put(BluetoothBindingConstants.CONFIGURATION_ADDRESS, device.getAddress().toString()); properties.put(Thing.PROPERTY_VENDOR, "Airthings AS"); diff --git a/bundles/org.openhab.binding.bluetooth.airthings/src/main/resources/ESH-INF/thing/airthings.xml b/bundles/org.openhab.binding.bluetooth.airthings/src/main/resources/ESH-INF/thing/airthings.xml index 8abff7c1d8d2d..076566cbd54ae 100644 --- a/bundles/org.openhab.binding.bluetooth.airthings/src/main/resources/ESH-INF/thing/airthings.xml +++ b/bundles/org.openhab.binding.bluetooth.airthings/src/main/resources/ESH-INF/thing/airthings.xml @@ -6,23 +6,23 @@ - - + + Indoor air quality monitor with radon detection - + - - - - - - - + + + + + + + @@ -42,42 +42,42 @@ Number:Dimensionless Humidity level - + Number:Temperature Temperature - + Number:Pressure Pressure - + Number:Dimensionless Carbon dioxide level - + Number:Dimensionless Total volatile organic compounds - + Number:Density Radon gas level - + Number:Density Radon gas level - + diff --git a/bundles/org.openhab.binding.bluetooth.am43/pom.xml b/bundles/org.openhab.binding.bluetooth.am43/pom.xml index 4caedd32166df..dc8c8c207bbbd 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/pom.xml +++ b/bundles/org.openhab.binding.bluetooth.am43/pom.xml @@ -1,18 +1,20 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bluetooth.am43 openHAB Add-ons :: Bundles :: AM43 Bluetooth Adapter - + org.openhab.addons.bundles org.openhab.binding.bluetooth diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/feature/feature.xml b/bundles/org.openhab.binding.bluetooth.am43/src/main/feature/feature.xml index b610ed0d9a3fe..f514c54332a48 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.am43/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.am43/${project.version} + diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43BindingConstants.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43BindingConstants.java index 8768767fbddbf..9324adbb152b5 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43BindingConstants.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43BindingConstants.java @@ -59,5 +59,4 @@ public static List getAllChannels() { CHANNEL_ID_HAS_LIGHT_SENSOR, CHANNEL_ID_OPERATION_MODE, CHANNEL_ID_SPEED, CHANNEL_ID_ELECTRIC, CHANNEL_ID_POSITION, CHANNEL_ID_LENGTH, CHANNEL_ID_DIAMETER, CHANNEL_ID_TYPE, CHANNEL_ID_LIGHT_LEVEL); } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43Configuration.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43Configuration.java index b327d56bf596d..9ee5132563019 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43Configuration.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43Configuration.java @@ -29,5 +29,4 @@ public String toString() { return "AM43Configuration [address=" + address + ", refreshInterval=" + refreshInterval + ", invertPosition=" + invertPosition + ", commandTimeout=" + commandTimeout + "]"; } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43DiscoveryParticipant.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43DiscoveryParticipant.java index 6dc3cb2f7d91f..463dc558686dd 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43DiscoveryParticipant.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43DiscoveryParticipant.java @@ -25,8 +25,8 @@ import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.openhab.binding.bluetooth.BluetoothBindingConstants; -import org.openhab.binding.bluetooth.BluetoothDevice; import org.openhab.binding.bluetooth.BluetoothDevice.ConnectionState; +import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryDevice; import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryParticipant; import org.osgi.service.component.annotations.Component; @@ -46,7 +46,7 @@ public Set getSupportedThingTypeUIDs() { } @Override - public @Nullable DiscoveryResult createResult(BluetoothDevice device) { + public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device) { ThingUID thingUID = getThingUID(device); if (thingUID == null) { return null; @@ -68,7 +68,7 @@ public Set getSupportedThingTypeUIDs() { } @Override - public @Nullable ThingUID getThingUID(BluetoothDevice device) { + public @Nullable ThingUID getThingUID(BluetoothDiscoveryDevice device) { if (device.getConnectionState() == ConnectionState.CONNECTED && device.supportsService(AM43BindingConstants.SERVICE_UUID)) { return new ThingUID(AM43BindingConstants.THING_TYPE_AM43, device.getAdapter().getUID(), @@ -78,7 +78,7 @@ public Set getSupportedThingTypeUIDs() { } @Override - public boolean requiresConnection(BluetoothDevice device) { + public boolean requiresConnection(BluetoothDiscoveryDevice device) { return device.getManufacturerId() == null && device.getName() != null; } } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43Handler.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43Handler.java index da53d21b9df3d..95a97d875ce28 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43Handler.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/AM43Handler.java @@ -464,5 +464,4 @@ private void updateStateIfLinked(String channelUID, State state) { updateState(channelUID, state); } } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/AM43Command.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/AM43Command.java index 0bda2bb59149b..0abffe2e941ac 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/AM43Command.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/AM43Command.java @@ -167,5 +167,4 @@ public byte[] getResponse() { public String toString() { return getClass().getSimpleName(); } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ControlCommand.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ControlCommand.java index a989b3bf895a1..80e638ad66683 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ControlCommand.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ControlCommand.java @@ -28,5 +28,4 @@ public class ControlCommand extends AM43Command { public ControlCommand(ControlAction action) { super(COMMAND, action.getCode()); } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ResetLimitsCommand.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ResetLimitsCommand.java index 8a9bfd36992c9..ee5ee89358a3b 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ResetLimitsCommand.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ResetLimitsCommand.java @@ -27,5 +27,4 @@ public class ResetLimitsCommand extends AM43Command { public ResetLimitsCommand() { super(COMMAND, (byte) 0, (byte) 0, (byte) 1); } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ResponseListener.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ResponseListener.java index eea54008da042..9d6f3834f6ec4 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ResponseListener.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/ResponseListener.java @@ -31,5 +31,4 @@ public interface ResponseListener { public void receivedResponse(GetPositionCommand command); public void receivedResponse(GetSpeedCommand command); - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetPositionCommand.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetPositionCommand.java index 414929528a78c..69e4ae55f8394 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetPositionCommand.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetPositionCommand.java @@ -27,5 +27,4 @@ public class SetPositionCommand extends AM43Command { public SetPositionCommand(int position) { super(COMMAND, (byte) position); } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetSettingsCommand.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetSettingsCommand.java index 35953d4f8f063..6a22fc9361437 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetSettingsCommand.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetSettingsCommand.java @@ -45,5 +45,4 @@ private static byte[] createContent(MotorSettings motorSettings) { return new byte[] { (byte) dataHead, (byte) deviceSpeed, 0, (byte) ((deviceLength & 0xFF00) >> 8), (byte) (deviceLength & 0xFF), (byte) deviceDiameter }; } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetTimeCommand.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetTimeCommand.java index c22cd378add93..59d3185a9f939 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetTimeCommand.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/command/SetTimeCommand.java @@ -41,5 +41,4 @@ private static byte[] createContent() { int dayOfWeek = instance.get(Calendar.DAY_OF_WEEK) - 1; return new byte[] { (byte) dayOfWeek, (byte) hour, (byte) minute, (byte) second }; } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/Direction.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/Direction.java index aa8deb78b7acd..3e8e4dbeb2fac 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/Direction.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/Direction.java @@ -34,5 +34,4 @@ public byte toByte() { public static Direction valueOf(boolean bitValue) { return bitValue ? Forward : Reverse; } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/MotorSettings.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/MotorSettings.java index 7814e226168dc..4eedf401ec009 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/MotorSettings.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/MotorSettings.java @@ -107,5 +107,4 @@ public int getDiameter() { public void setDiameter(int diameter) { this.diameter = diameter; } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/OperationMode.java b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/OperationMode.java index 76636e1850551..075ece063119f 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/OperationMode.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/java/org/openhab/binding/bluetooth/am43/internal/data/OperationMode.java @@ -34,5 +34,4 @@ public byte toByte() { public static OperationMode valueOf(boolean bitValue) { return bitValue ? Inching : Continuous; } - } diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/main/resources/ESH-INF/thing/am43.xml b/bundles/org.openhab.binding.bluetooth.am43/src/main/resources/ESH-INF/thing/am43.xml index 04522273d5f57..bfd0234f0be08 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/main/resources/ESH-INF/thing/am43.xml +++ b/bundles/org.openhab.binding.bluetooth.am43/src/main/resources/ESH-INF/thing/am43.xml @@ -1,13 +1,13 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - - + + @@ -15,19 +15,19 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ Blinds - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -66,26 +66,26 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ - + Switch - + Switch - + Switch Whether or not a light sensor is attached to the motor - + String @@ -96,19 +96,19 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ - + Number:Dimensionless The speed value in RPMs set for this motor - + Rollershutter The percent value of the blind position - + @@ -117,26 +117,26 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ The distance the blinds travel from full open and close (not really important) - + Number:Length The diameter of the pulley of this motor (not really important) - + Number:Dimensionless The type of blinds this motor is operating. (not really important) - + Number:Dimensionless Light level detected by the solar sensor. Will range from 0-10 - + diff --git a/bundles/org.openhab.binding.bluetooth.am43/src/test/java/org/openhab/binding/bluetooth/am43/CommandTest.java b/bundles/org.openhab.binding.bluetooth.am43/src/test/java/org/openhab/binding/bluetooth/am43/CommandTest.java index d39046dda9b69..3cc87a162d28f 100644 --- a/bundles/org.openhab.binding.bluetooth.am43/src/test/java/org/openhab/binding/bluetooth/am43/CommandTest.java +++ b/bundles/org.openhab.binding.bluetooth.am43/src/test/java/org/openhab/binding/bluetooth/am43/CommandTest.java @@ -49,5 +49,4 @@ public void controlOpenCommandTest() { Assert.assertArrayEquals(expected, actual); } - } diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/pom.xml b/bundles/org.openhab.binding.bluetooth.bluegiga/pom.xml index 76dde9bfceae0..67dda55db3b48 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/pom.xml +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bluetooth.bluegiga diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/feature/feature.xml b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/feature/feature.xml index 20d5b6946e564..00dbbf4cd6a27 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/feature/feature.xml @@ -1,12 +1,12 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.bluegiga/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.bluegiga/${project.version} + diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java index 76d8951a12a3a..4fc2dbae0bc31 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/BlueGigaBluetoothDevice.java @@ -20,9 +20,11 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.common.ThreadPoolManager; +import org.openhab.binding.bluetooth.BaseBluetoothDevice; import org.openhab.binding.bluetooth.BluetoothAddress; import org.openhab.binding.bluetooth.BluetoothCharacteristic; import org.openhab.binding.bluetooth.BluetoothCompletionStatus; +import org.openhab.binding.bluetooth.BluetoothDescriptor; import org.openhab.binding.bluetooth.BluetoothDevice; import org.openhab.binding.bluetooth.BluetoothService; import org.openhab.binding.bluetooth.bluegiga.handler.BlueGigaBridgeHandler; @@ -52,7 +54,7 @@ * @author Chris Jackson - Initial contribution */ @NonNullByDefault -public class BlueGigaBluetoothDevice extends BluetoothDevice implements BlueGigaEventListener { +public class BlueGigaBluetoothDevice extends BaseBluetoothDevice implements BlueGigaEventListener { private final long TIMEOUT_SEC = 60; private final Logger logger = LoggerFactory.getLogger(BlueGigaBluetoothDevice.class); @@ -169,6 +171,30 @@ public boolean discoverServices() { return true; } + @Override + public boolean enableNotifications(BluetoothCharacteristic characteristic) { + // TODO will be implemented in a followup PR + return false; + } + + @Override + public boolean disableNotifications(BluetoothCharacteristic characteristic) { + // TODO will be implemented in a followup PR + return false; + } + + @Override + public boolean enableNotifications(BluetoothDescriptor descriptor) { + // TODO will be implemented in a followup PR + return false; + } + + @Override + public boolean disableNotifications(BluetoothDescriptor descriptor) { + // TODO will be implemented in a followup PR + return false; + } + @Override public boolean readCharacteristic(@Nullable BluetoothCharacteristic characteristic) { if (characteristic == null || characteristic.getHandle() == 0) { @@ -278,7 +304,7 @@ private void handleScanEvent(BlueGigaScanResponseEvent event) { Map eirRecord = (Map) obj; Map.Entry eirEntry = eirRecord.entrySet().iterator().next(); - manufacturer = (int) eirEntry.getKey(); + manufacturer = eirEntry.getKey().intValue(); int[] manufacturerInt = eirEntry.getValue(); manufacturerData = new byte[manufacturerInt.length + 2]; diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaDeviceCommand.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaDeviceCommand.java index 3bb6f131028b1..13a45b1502024 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaDeviceCommand.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaDeviceCommand.java @@ -49,5 +49,4 @@ public final void setConnection(int connection) { public final int getConnection() { return connection; } - } diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaException.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaException.java index 75556563699fb..1182723a52323 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaException.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaException.java @@ -36,5 +36,4 @@ public BlueGigaException(String message) { public BlueGigaException(String message, Throwable cause) { super(message, cause); } - } diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaHandlerListener.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaHandlerListener.java index cda1ff5e6644e..2ef5c6f403ac8 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaHandlerListener.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaHandlerListener.java @@ -28,5 +28,4 @@ public interface BlueGigaHandlerListener { * @param reason a reason caused to be closed */ void bluegigaClosed(Exception reason); - } diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaTransactionManager.java b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaTransactionManager.java index 14f05f42f5a87..b99fc693798f4 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaTransactionManager.java +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/java/org/openhab/binding/bluetooth/bluegiga/internal/BlueGigaTransactionManager.java @@ -231,7 +231,6 @@ public T call() throws TimeoutException { } else { throw new TimeoutException("No response from BlueGiga controller"); } - } @Override diff --git a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/resources/ESH-INF/thing/bluegiga.xml b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/resources/ESH-INF/thing/bluegiga.xml index ddef05a56a1f3..d08fddbff342b 100644 --- a/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/resources/ESH-INF/thing/bluegiga.xml +++ b/bundles/org.openhab.binding.bluetooth.bluegiga/src/main/resources/ESH-INF/thing/bluegiga.xml @@ -12,6 +12,7 @@ serial-port + false Serial Port @@ -40,25 +41,29 @@ - Passive scan interval defines the interval when scanning is re-started in units of 625us. Default is 4000ms. + Passive scan interval defines the interval when scanning is re-started in units of 625us. Default is + 4000ms. true 6400 - Passive scan Window defines how long time the scanner will listen on a certain frequency and try to pick up advertisement packets. Default is 4000ms. + Passive scan Window defines how long time the scanner will listen on a certain frequency and try to + pick up advertisement packets. Default is 4000ms. true 6400 - Active scan interval defines the interval when scanning is re-started in units of 625us. Default is 4000ms. + Active scan interval defines the interval when scanning is re-started in units of 625us. Default is + 4000ms. true 6400 - Active scan Window defines how long time the scanner will listen on a certain frequency and try to pick up advertisement packets. Default is 4000ms. + Active scan Window defines how long time the scanner will listen on a certain frequency and try to pick + up advertisement packets. Default is 4000ms. true 6400 @@ -82,7 +87,8 @@ - Connection supervision timeout in units of 10ms defines how long the devices can be out of range before the connection is closed. Default is 10000ms. + Connection supervision timeout in units of 10ms defines how long the devices can be out of range before + the connection is closed. Default is 10000ms. true 1000 diff --git a/bundles/org.openhab.binding.bluetooth.bluez/pom.xml b/bundles/org.openhab.binding.bluetooth.bluez/pom.xml index e5a3fd60a10d2..8b16b643b7064 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/pom.xml +++ b/bundles/org.openhab.binding.bluetooth.bluez/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bluetooth.bluez @@ -26,5 +28,5 @@ compile - + diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/feature/feature.xml b/bundles/org.openhab.binding.bluetooth.bluez/src/main/feature/feature.xml index 9885924e6ef87..1119f1727a4b1 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/feature/feature.xml @@ -1,12 +1,12 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.bluez/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.bluez/${project.version} + diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/BlueZAdapterConstants.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/BlueZAdapterConstants.java index 9bacff6ea89b9..b982eaa694666 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/BlueZAdapterConstants.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/BlueZAdapterConstants.java @@ -30,5 +30,4 @@ public class BlueZAdapterConstants { // Properties public static final String PROPERTY_ADDRESS = "address"; - } diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/BlueZBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/BlueZBluetoothDevice.java index dd63b4cd21d04..5968b19d561ac 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/BlueZBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/BlueZBluetoothDevice.java @@ -20,11 +20,11 @@ import org.eclipse.smarthome.core.common.ThreadPoolManager; import org.eclipse.smarthome.core.util.HexUtils; +import org.openhab.binding.bluetooth.BaseBluetoothDevice; import org.openhab.binding.bluetooth.BluetoothAddress; import org.openhab.binding.bluetooth.BluetoothCharacteristic; import org.openhab.binding.bluetooth.BluetoothCompletionStatus; import org.openhab.binding.bluetooth.BluetoothDescriptor; -import org.openhab.binding.bluetooth.BluetoothDevice; import org.openhab.binding.bluetooth.BluetoothService; import org.openhab.binding.bluetooth.bluez.handler.BlueZBridgeHandler; import org.openhab.binding.bluetooth.notification.BluetoothConnectionStatusNotification; @@ -43,7 +43,7 @@ * @author Kai Kreuzer - Initial contribution and API * */ -public class BlueZBluetoothDevice extends BluetoothDevice { +public class BlueZBluetoothDevice extends BaseBluetoothDevice { private tinyb.BluetoothDevice device; @@ -113,12 +113,14 @@ public synchronized void updateTinybDevice(tinyb.BluetoothDevice tinybDevice) { private void enableNotifications() { logger.debug("Enabling notifications for device '{}'", device.getAddress()); device.enableRSSINotifications(n -> { + updateLastSeenTime(); rssi = (int) n; BluetoothScanNotification notification = new BluetoothScanNotification(); notification.setRssi(n); notifyListeners(BluetoothEventType.SCAN_RECORD, notification); }); device.enableManufacturerDataNotifications(n -> { + updateLastSeenTime(); for (Map.Entry entry : n.entrySet()) { BluetoothScanNotification notification = new BluetoothScanNotification(); byte[] data = new byte[entry.getValue().length + 2]; @@ -133,12 +135,14 @@ private void enableNotifications() { } }); device.enableConnectedNotifications(connected -> { + updateLastSeenTime(); connectionState = connected ? ConnectionState.CONNECTED : ConnectionState.DISCONNECTED; logger.debug("Connection state of '{}' changed to {}", address, connectionState); notifyListeners(BluetoothEventType.CONNECTION_STATE, new BluetoothConnectionStatusNotification(connectionState)); }); device.enableServicesResolvedNotifications(resolved -> { + updateLastSeenTime(); logger.debug("Received services resolved event for '{}': {}", address, resolved); if (resolved) { refreshServices(); @@ -146,6 +150,7 @@ private void enableNotifications() { } }); device.enableServiceDataNotifications(data -> { + updateLastSeenTime(); if (logger.isDebugEnabled()) { logger.debug("Received service data for '{}':", address); for (Map.Entry entry : data.entrySet()) { @@ -221,6 +226,11 @@ public boolean disconnect() { return false; } + @Override + public boolean discoverServices() { + return false; + } + private void ensureConnected() { if (device == null || !device.getConnected()) { throw new IllegalStateException("TinyB device is not set or not connected"); diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/handler/BlueZAdapterConfiguration.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/handler/BlueZAdapterConfiguration.java index b85ce17496e9e..0999624eeeb09 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/handler/BlueZAdapterConfiguration.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/handler/BlueZAdapterConfiguration.java @@ -22,5 +22,4 @@ public class BlueZAdapterConfiguration extends BaseBluetoothBridgeHandlerConfiguration { public String address; - } diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/handler/BlueZBridgeHandler.java b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/handler/BlueZBridgeHandler.java index ef0b12d886324..cabaabb1d3698 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/handler/BlueZBridgeHandler.java +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/java/org/openhab/binding/bluetooth/bluez/handler/BlueZBridgeHandler.java @@ -166,5 +166,4 @@ public void dispose() { } super.dispose(); } - } diff --git a/bundles/org.openhab.binding.bluetooth.bluez/src/main/resources/ESH-INF/thing/bluez.xml b/bundles/org.openhab.binding.bluetooth.bluez/src/main/resources/ESH-INF/thing/bluez.xml index ec8fdc6a9e502..32cb28cd3907e 100644 --- a/bundles/org.openhab.binding.bluetooth.bluez/src/main/resources/ESH-INF/thing/bluez.xml +++ b/bundles/org.openhab.binding.bluetooth.bluez/src/main/resources/ESH-INF/thing/bluez.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.bluetooth.blukii/pom.xml b/bundles/org.openhab.binding.bluetooth.blukii/pom.xml index 34b6eb18d5a84..db48714ecddfe 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/pom.xml +++ b/bundles/org.openhab.binding.bluetooth.blukii/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bluetooth.blukii diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/feature/feature.xml b/bundles/org.openhab.binding.bluetooth.blukii/src/main/feature/feature.xml index 9de45bf093a61..5b9fba476a60d 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/feature/feature.xml @@ -1,12 +1,12 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.blukii/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.blukii/${project.version} + diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/handler/BlukiiHandler.java b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/handler/BlukiiHandler.java index 7046c29fd59fd..a8b28c8a90912 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/handler/BlukiiHandler.java +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/handler/BlukiiHandler.java @@ -76,5 +76,4 @@ public void onScanRecordReceived(BluetoothScanNotification scanNotification) { } super.onScanRecordReceived(scanNotification); } - } diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/BlukiiDiscoveryParticipant.java b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/BlukiiDiscoveryParticipant.java index 83ec28e117328..91a2d161ade38 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/BlukiiDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/BlukiiDiscoveryParticipant.java @@ -17,7 +17,7 @@ import java.util.Map; import java.util.Set; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; @@ -25,8 +25,8 @@ import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.openhab.binding.bluetooth.BluetoothBindingConstants; -import org.openhab.binding.bluetooth.BluetoothDevice; import org.openhab.binding.bluetooth.blukii.BlukiiBindingConstants; +import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryDevice; import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryParticipant; import org.osgi.service.component.annotations.Component; @@ -36,16 +36,17 @@ * @author Kai Kreuzer - Initial contribution and API * */ +@NonNullByDefault @Component(immediate = true) public class BlukiiDiscoveryParticipant implements BluetoothDiscoveryParticipant { @Override - public @NonNull Set<@NonNull ThingTypeUID> getSupportedThingTypeUIDs() { + public Set getSupportedThingTypeUIDs() { return Collections.singleton(BlukiiBindingConstants.THING_TYPE_BEACON); } @Override - public @Nullable ThingUID getThingUID(@NonNull BluetoothDevice device) { + public @Nullable ThingUID getThingUID(BluetoothDiscoveryDevice device) { String name = device.getName(); if (name != null && name.startsWith(BlukiiBindingConstants.BLUKII_PREFIX)) { if (name.charAt(BlukiiBindingConstants.BLUKII_PREFIX.length()) == 'B') { @@ -57,7 +58,7 @@ public class BlukiiDiscoveryParticipant implements BluetoothDiscoveryParticipant } @Override - public DiscoveryResult createResult(@NonNull BluetoothDevice device) { + public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device) { ThingUID thingUID = getThingUID(device); if (thingUID != null) { @@ -79,5 +80,4 @@ public DiscoveryResult createResult(@NonNull BluetoothDevice device) { return null; } } - } diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Accelerometer.java b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Accelerometer.java index 33eb5e88b01c9..2727154e4c053 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Accelerometer.java +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Accelerometer.java @@ -35,5 +35,4 @@ public Accelerometer(final double tiltX, final double tiltY, final double tiltZ) public String toString() { return "Accelerometer [tiltX=" + tiltX + ", tiltY=" + tiltY + ", tiltZ=" + tiltZ + "]"; } - } diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/BlukiiData.java b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/BlukiiData.java index 71dab74be4caf..a69f870bc16d2 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/BlukiiData.java +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/BlukiiData.java @@ -42,5 +42,4 @@ public String toString() { return "BlukiiData [battery=" + battery + ", magnetometer=" + magnetometer + ", environment=" + environment + ", accelerometer=" + accelerometer + "]"; } - } diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/BlukiiDataDecoder.java b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/BlukiiDataDecoder.java index 4afa8504faf5c..21f44460b67eb 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/BlukiiDataDecoder.java +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/BlukiiDataDecoder.java @@ -106,5 +106,4 @@ private static int doubleByteToInt(byte b1, byte b2) { int i2 = b2 & 0xFF; return (i1 * 0x100) + i2; } - } diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Environment.java b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Environment.java index c8b8a8d20a6ee..43179434f6e34 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Environment.java +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Environment.java @@ -38,5 +38,4 @@ public String toString() { return "Environment [pressure=" + pressure + ", luminance=" + luminance + ", humidity=" + humidity + ", temperature=" + temperature + "]"; } - } diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Magnetometer.java b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Magnetometer.java index 7ae9597d62dcf..02347bf68e75e 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Magnetometer.java +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/java/org/openhab/binding/bluetooth/blukii/internal/data/Magnetometer.java @@ -35,5 +35,4 @@ public Magnetometer(final int x, final int y, final int z) { public String toString() { return "Magnetometer [x=" + x + ", y=" + y + ", z=" + z + "]"; } - } diff --git a/bundles/org.openhab.binding.bluetooth.blukii/src/main/resources/ESH-INF/thing/blukii.xml b/bundles/org.openhab.binding.bluetooth.blukii/src/main/resources/ESH-INF/thing/blukii.xml index 81ae24a0affe2..ae55d8b90f0ee 100644 --- a/bundles/org.openhab.binding.bluetooth.blukii/src/main/resources/ESH-INF/thing/blukii.xml +++ b/bundles/org.openhab.binding.bluetooth.blukii/src/main/resources/ESH-INF/thing/blukii.xml @@ -1,29 +1,30 @@ - - - + + A Blukii SmartBeacon - - + + - - - - + + + + - - - + + + @@ -38,43 +39,43 @@ Number:Temperature - + Number:Dimensionless - + Number:Pressure - + Number:Illuminance - + Number:Angle - + Number:Angle - + Number:Angle - + diff --git a/bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml b/bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml index 3f1e1641f9135..dbf861f996c3a 100644 --- a/bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml +++ b/bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bluetooth.ruuvitag diff --git a/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/feature/feature.xml b/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/feature/feature.xml index 0e9d99154bb29..00d77179b89c6 100644 --- a/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/feature/feature.xml @@ -1,12 +1,12 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.ruuvitag/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.ruuvitag/${project.version} + diff --git a/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/java/org/openhab/binding/bluetooth/ruuvitag/internal/RuuviTagBindingConstants.java b/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/java/org/openhab/binding/bluetooth/ruuvitag/internal/RuuviTagBindingConstants.java index 316a13777f933..2cf83a8537b2b 100644 --- a/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/java/org/openhab/binding/bluetooth/ruuvitag/internal/RuuviTagBindingConstants.java +++ b/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/java/org/openhab/binding/bluetooth/ruuvitag/internal/RuuviTagBindingConstants.java @@ -40,5 +40,4 @@ public class RuuviTagBindingConstants { public static final String CHANNEL_ID_ACCELERATIONZ = "accelerationz"; public static final String CHANNEL_ID_MEASUREMENT_SEQUENCE_NUMBER = "measurementSequenceNumber"; public static final String CHANNEL_ID_MOVEMENT_COUNTER = "movementCounter"; - } diff --git a/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/java/org/openhab/binding/bluetooth/ruuvitag/internal/RuuviTagDiscoveryParticipant.java b/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/java/org/openhab/binding/bluetooth/ruuvitag/internal/RuuviTagDiscoveryParticipant.java index 17f885b148e8c..064bc90b80ce7 100644 --- a/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/java/org/openhab/binding/bluetooth/ruuvitag/internal/RuuviTagDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/java/org/openhab/binding/bluetooth/ruuvitag/internal/RuuviTagDiscoveryParticipant.java @@ -25,7 +25,7 @@ import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.openhab.binding.bluetooth.BluetoothBindingConstants; -import org.openhab.binding.bluetooth.BluetoothDevice; +import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryDevice; import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryParticipant; import org.osgi.service.component.annotations.Component; @@ -47,8 +47,7 @@ public Set getSupportedThingTypeUIDs() { } @Override - @Nullable - public ThingUID getThingUID(BluetoothDevice device) { + public @Nullable ThingUID getThingUID(BluetoothDiscoveryDevice device) { Integer manufacturerId = device.getManufacturerId(); if (manufacturerId != null && manufacturerId == RUUVITAG_COMPANY_ID) { return new ThingUID(RuuviTagBindingConstants.THING_TYPE_BEACON, device.getAdapter().getUID(), @@ -58,8 +57,7 @@ public ThingUID getThingUID(BluetoothDevice device) { } @Override - @Nullable - public DiscoveryResult createResult(BluetoothDevice device) { + public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device) { ThingUID thingUID = getThingUID(device); if (thingUID == null) { return null; @@ -78,5 +76,4 @@ public DiscoveryResult createResult(BluetoothDevice device) { .withRepresentationProperty(BluetoothBindingConstants.CONFIGURATION_ADDRESS) .withBridge(device.getAdapter().getUID()).withLabel(label).build(); } - } diff --git a/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/resources/ESH-INF/thing/ruuvitag.xml b/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/resources/ESH-INF/thing/ruuvitag.xml index ab6ff81e4f7ea..4ab48881c9121 100644 --- a/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/resources/ESH-INF/thing/ruuvitag.xml +++ b/bundles/org.openhab.binding.bluetooth.ruuvitag/src/main/resources/ESH-INF/thing/ruuvitag.xml @@ -6,27 +6,27 @@ - - + + A RuuviTag SmartBeacon - + - - - - - - - - - - - + + + + + + + + + + + @@ -41,56 +41,56 @@ Number:Acceleration - + Number:Acceleration - + Number:Acceleration - + Number:ElectricPotential - + Number - + Number:Dimensionless - + Number:Dimensionless - + Number:Dimensionless - + Number:Pressure - + Number:Temperature - + Number:Power - + diff --git a/bundles/org.openhab.binding.bluetooth/pom.xml b/bundles/org.openhab.binding.bluetooth/pom.xml index 717d5ebf6cf4e..3fa78a6992b9b 100644 --- a/bundles/org.openhab.binding.bluetooth/pom.xml +++ b/bundles/org.openhab.binding.bluetooth/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bluetooth diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/AbstractBluetoothBridgeHandler.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/AbstractBluetoothBridgeHandler.java index 91680f8da66b9..dec999ada3abe 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/AbstractBluetoothBridgeHandler.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/AbstractBluetoothBridgeHandler.java @@ -219,5 +219,4 @@ private boolean deviceReachable(BluetoothDevice device) { Integer rssi = device.getRssi(); return rssi != null && rssi != 0; } - } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BaseBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BaseBluetoothDevice.java new file mode 100644 index 0000000000000..f405b686348a1 --- /dev/null +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BaseBluetoothDevice.java @@ -0,0 +1,349 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bluetooth; + +import java.time.ZonedDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.bluetooth.notification.BluetoothConnectionStatusNotification; +import org.openhab.binding.bluetooth.notification.BluetoothScanNotification; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link BaseBluetoothDevice} implements parts of the BluetoothDevice functionality that is + * shared to all concrete BluetoothDevice implementations. + * + * @author Connor Petty - Initial Contribution + */ +@NonNullByDefault +public abstract class BaseBluetoothDevice extends BluetoothDevice { + + private final Logger logger = LoggerFactory.getLogger(BaseBluetoothDevice.class); + + /** + * Current connection state + */ + protected ConnectionState connectionState = ConnectionState.DISCOVERING; + + /** + * Manufacturer id + */ + protected @Nullable Integer manufacturer = null; + + /** + * Device name. + *

+ * Uses the devices long name if known, otherwise the short name if known + */ + protected @Nullable String name; + + /** + * List of supported services + */ + protected final Map supportedServices = new ConcurrentHashMap<>(); + + /** + * Last known RSSI + */ + protected @Nullable Integer rssi = null; + + /** + * Last reported transmitter power + */ + protected @Nullable Integer txPower = null; + + /** + * Last time when activity occurred on this device. + */ + protected ZonedDateTime lastSeenTime; + + /** + * The event listeners will be notified of device updates + */ + private final List eventListeners = new CopyOnWriteArrayList<>(); + + /** + * Construct a Bluetooth device taking the Bluetooth address + * + * @param adapter + * @param sender + */ + public BaseBluetoothDevice(BluetoothAdapter adapter, BluetoothAddress address) { + super(adapter, address); + this.lastSeenTime = ZonedDateTime.now(); + } + + /** + * Returns the last time this device was active + * + * @return The last time this device was active + */ + @Override + public ZonedDateTime getLastSeenTime() { + return lastSeenTime; + } + + /** + * Updates the last activity timestamp for this device. + * Should be called whenever activity occurs on this device. + * + */ + @Override + public void updateLastSeenTime() { + lastSeenTime = ZonedDateTime.now(); + } + + /** + * Returns the name of the Bluetooth device. + * + * @return The devices name + */ + @Override + public @Nullable String getName() { + return name; + } + + /** + * Sets the manufacturer id for the device + * + * @param manufacturer the manufacturer id + */ + public void setManufacturerId(int manufacturer) { + this.manufacturer = manufacturer; + } + + /** + * Returns the manufacturer ID of the device + * + * @return an integer with manufacturer ID of the device, or null if not known + */ + @Override + public @Nullable Integer getManufacturerId() { + return manufacturer; + } + + /** + * Returns a {@link BluetoothService} if the requested service is supported + * + * @return the {@link BluetoothService} or null if the service is not supported. + */ + @Override + public @Nullable BluetoothService getServices(UUID uuid) { + return supportedServices.get(uuid); + } + + /** + * Returns a list of supported service UUIDs + * + * @return list of supported {@link BluetoothService}s. + */ + @Override + public Collection getServices() { + return supportedServices.values(); + } + + /** + * Sets the device transmit power + * + * @param power the current transmitter power in dBm + */ + public void setTxPower(int txPower) { + this.txPower = txPower; + } + + /** + * Returns the last Transmit Power value or null if no transmit power has been received + * + * @return the last reported transmitter power value in dBm + */ + @Override + public @Nullable Integer getTxPower() { + return txPower; + } + + /** + * Sets the current Receive Signal Strength Indicator (RSSI) value + * + * @param rssi the current RSSI value in dBm + * @return true if the RSSI has changed, false if it was the same as previous + */ + public boolean setRssi(int rssi) { + boolean changed = (this.rssi == null || this.rssi != rssi); + this.rssi = rssi; + + return changed; + } + + /** + * Returns the last Receive Signal Strength Indicator (RSSI) value or null if no RSSI has been received + * + * @return the last RSSI value in dBm + */ + @Override + public @Nullable Integer getRssi() { + return rssi; + } + + /** + * Set the name of the device + * + * @param name a {@link String} defining the device name + */ + public void setName(String name) { + this.name = name; + } + + /** + * Check if the device supports the specified service + * + * @param uuid the service {@link UUID} + * @return true if the service is supported + */ + @Override + public boolean supportsService(UUID uuid) { + return supportedServices.containsKey(uuid); + } + + /** + * Get the current connection state for this device + * + * @return the current {@link ConnectionState} + */ + @Override + public ConnectionState getConnectionState() { + return connectionState; + } + + /** + * Adds a service to the device. + * + * @param service the new {@link BluetoothService} to add + * @return true if the service was added or false if the service was already supported + */ + @Override + protected boolean addService(BluetoothService service) { + BluetoothService oldValue = supportedServices.putIfAbsent(service.getUuid(), service); + if (oldValue == null) { + logger.trace("Adding new service to device {}: {}", address, service); + return true; + } + return false; + } + + /** + * Adds a device listener + * + * @param listener the {@link BluetoothDeviceListener} to add + */ + @Override + public void addListener(BluetoothDeviceListener listener) { + eventListeners.add(listener); + } + + /** + * Removes a device listener + * + * @param listener the {@link BluetoothDeviceListener} to remove + */ + @Override + public void removeListener(BluetoothDeviceListener listener) { + eventListeners.remove(listener); + } + + /** + * Checks if this device has any listeners + * + * @return true if this device has listeners + */ + @Override + public boolean hasListeners() { + return !eventListeners.isEmpty(); + } + + /** + * Releases resources that this device is using. + * + */ + @Override + protected void dispose() { + } + + /** + * Notify the listeners of an event + * + * @param event the {@link BluetoothEventType} of this event + * @param args an array of arguments to pass to the callback + */ + @Override + protected void notifyListeners(BluetoothEventType event, Object... args) { + for (BluetoothDeviceListener listener : eventListeners) { + try { + switch (event) { + case SCAN_RECORD: + listener.onScanRecordReceived((BluetoothScanNotification) args[0]); + break; + case CONNECTION_STATE: + listener.onConnectionStateChange((BluetoothConnectionStatusNotification) args[0]); + break; + case SERVICES_DISCOVERED: + listener.onServicesDiscovered(); + break; + case CHARACTERISTIC_READ_COMPLETE: + listener.onCharacteristicReadComplete((BluetoothCharacteristic) args[0], + (BluetoothCompletionStatus) args[1]); + break; + case CHARACTERISTIC_WRITE_COMPLETE: + listener.onCharacteristicWriteComplete((BluetoothCharacteristic) args[0], + (BluetoothCompletionStatus) args[1]); + break; + case CHARACTERISTIC_UPDATED: + listener.onCharacteristicUpdate((BluetoothCharacteristic) args[0]); + break; + case DESCRIPTOR_UPDATED: + listener.onDescriptorUpdate((BluetoothDescriptor) args[0]); + break; + } + } catch (Exception e) { + logger.error("Failed to inform listener '{}': {}", listener, e.getMessage(), e); + } + } + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("BluetoothDevice [address="); + builder.append(address); + builder.append(", manufacturer="); + builder.append(manufacturer); + if (BluetoothCompanyIdentifiers.get(manufacturer) != null) { + builder.append(" ("); + builder.append(BluetoothCompanyIdentifiers.get(manufacturer)); + builder.append(')'); + } + builder.append(", name="); + builder.append(name); + builder.append(", rssi="); + builder.append(rssi); + builder.append(']'); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BeaconBluetoothHandler.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BeaconBluetoothHandler.java index 3149716c0a52c..993ca12f80ae9 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BeaconBluetoothHandler.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BeaconBluetoothHandler.java @@ -15,6 +15,7 @@ import java.util.concurrent.locks.ReentrantLock; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -115,14 +116,17 @@ public void handleCommand(ChannelUID channelUID, Command command) { */ protected void updateRSSI() { if (device != null) { - Integer rssi = device.getRssi(); - if (rssi != null && rssi != 0) { - updateState(BluetoothBindingConstants.CHANNEL_TYPE_RSSI, new DecimalType(rssi)); - updateStatusBasedOnRssi(true); - } else { - updateState(BluetoothBindingConstants.CHANNEL_TYPE_RSSI, UnDefType.NULL); - updateStatusBasedOnRssi(false); - } + updateRSSI(device.getRssi()); + } + } + + private void updateRSSI(@Nullable Integer rssi) { + if (rssi != null && rssi != 0) { + updateState(BluetoothBindingConstants.CHANNEL_TYPE_RSSI, new DecimalType(rssi)); + updateStatusBasedOnRssi(true); + } else { + updateState(BluetoothBindingConstants.CHANNEL_TYPE_RSSI, UnDefType.NULL); + updateStatusBasedOnRssi(false); } } @@ -144,8 +148,7 @@ protected void updateStatusBasedOnRssi(boolean receivedSignal) { public void onScanRecordReceived(BluetoothScanNotification scanNotification) { int rssi = scanNotification.getRssi(); if (rssi != Integer.MIN_VALUE) { - device.setRssi(rssi); - updateRSSI(); + updateRSSI(rssi); } } @@ -173,5 +176,4 @@ public void onCharacteristicUpdate(BluetoothCharacteristic characteristic) { @Override public void onDescriptorUpdate(BluetoothDescriptor bluetoothDescriptor) { } - } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothAdapter.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothAdapter.java index da3ff8fe92b6f..eb85592d70d0c 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothAdapter.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothAdapter.java @@ -82,5 +82,4 @@ public interface BluetoothAdapter extends Identifiable { * @return true if this adapter has a {@link BluetoothDevice} with that address */ boolean hasHandlerForDevice(BluetoothAddress address); - } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothBindingConstants.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothBindingConstants.java index 6e9669cdef320..90c894c0dd3e5 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothBindingConstants.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothBindingConstants.java @@ -52,5 +52,4 @@ public class BluetoothBindingConstants { public static final UUID PROFILE_HEADSET = UUID.fromString("00001108-0000-1000-8000-00805f9b34fb"); public static final UUID PROFILE_HFP = UUID.fromString("0000111e-0000-1000-8000-00805f9b34fb"); public static final UUID PROFILE_HFP_AUDIOGATEWAY = UUID.fromString("0000111f-0000-1000-8000-00805f9b34fb"); - } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java index 2a83a27fd0bb2..e3bbf466351d6 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothCharacteristic.java @@ -654,5 +654,4 @@ public UUID getUUID() { return uuid; } } - } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDescriptor.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDescriptor.java index 73f323a3d8d13..8ac763c1d180a 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDescriptor.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDescriptor.java @@ -50,7 +50,6 @@ public BluetoothDescriptor(BluetoothCharacteristic characteristic, UUID uuid) { */ BluetoothCharacteristic getCharacteristic() { return characteristic; - } /** @@ -69,7 +68,6 @@ public int getPermissions() { */ public UUID getUuid() { return uuid; - } /** diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java index a972cd82ed820..b2734d0459897 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/BluetoothDevice.java @@ -14,18 +14,11 @@ import java.time.ZonedDateTime; import java.util.Collection; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.UUID; -import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.bluetooth.notification.BluetoothConnectionStatusNotification; -import org.openhab.binding.bluetooth.notification.BluetoothScanNotification; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The {@link BluetoothDevice} class provides a base implementation of a Bluetooth Low Energy device @@ -36,8 +29,6 @@ @NonNullByDefault public abstract class BluetoothDevice { - private final Logger logger = LoggerFactory.getLogger(BluetoothDevice.class); - /** * Enumeration of Bluetooth connection states * @@ -79,11 +70,6 @@ protected enum BluetoothEventType { SERVICES_DISCOVERED } - /** - * Current connection state - */ - protected ConnectionState connectionState = ConnectionState.DISCOVERING; - /** * The adapter the device is accessed through */ @@ -94,49 +80,6 @@ protected enum BluetoothEventType { */ protected final BluetoothAddress address; - /** - * Manufacturer id - */ - protected @Nullable Integer manufacturer = null; - - /** - * Device name. - *

- * Uses the devices long name if known, otherwise the short name if known - */ - protected @Nullable String name; - - protected @Nullable String model; - protected @Nullable String serialNumber; - protected @Nullable String hardwareRevision; - protected @Nullable String firmwareRevision; - protected @Nullable String softwareRevision; - - /** - * List of supported services - */ - protected final Map supportedServices = new HashMap<>(); - - /** - * Last known RSSI - */ - protected @Nullable Integer rssi = null; - - /** - * Last reported transmitter power - */ - protected @Nullable Integer txPower = null; - - /** - * Last time when activity occurred on this device. - */ - protected ZonedDateTime lastSeenTime; - - /** - * The event listeners will be notified of device updates - */ - private final List eventListeners = new CopyOnWriteArrayList<>(); - /** * Construct a Bluetooth device taking the Bluetooth address * @@ -146,7 +89,6 @@ protected enum BluetoothEventType { public BluetoothDevice(BluetoothAdapter adapter, BluetoothAddress address) { this.address = address; this.adapter = adapter; - this.lastSeenTime = ZonedDateTime.now(); } /** @@ -154,72 +96,42 @@ public BluetoothDevice(BluetoothAdapter adapter, BluetoothAddress address) { * * @return The last time this device was active */ - public ZonedDateTime getLastSeenTime() { - return lastSeenTime; - } + public abstract ZonedDateTime getLastSeenTime(); /** * Updates the last activity timestamp for this device. * Should be called whenever activity occurs on this device. * */ - public void updateLastSeenTime() { - lastSeenTime = ZonedDateTime.now(); - } + public abstract void updateLastSeenTime(); /** * Returns the name of the Bluetooth device. * * @return The devices name */ - public @Nullable String getName() { - return name; - } + public abstract @Nullable String getName(); /** - * Returns the model of the Bluetooth device. - * - * @return The devices model, null if not known - */ - public @Nullable String getModel() { - return model; - } - - /** - * Returns the serial number of the Bluetooth device. - * - * @return The serial model, null if not known - */ - public @Nullable String getSerialNumber() { - return serialNumber; - } - - /** - * Returns the hardware revision of the Bluetooth device. + * Returns the manufacturer ID of the device * - * @return The hardware revision, null if not known + * @return an integer with manufacturer ID of the device, or null if not known */ - public @Nullable String getHardwareRevision() { - return hardwareRevision; - } + public abstract @Nullable Integer getManufacturerId(); /** - * Returns the firmware revision of the Bluetooth device. + * Returns the last Transmit Power value or null if no transmit power has been received * - * @return The firmware revision, null if not known + * @return the last reported transmitter power value in dBm */ - public @Nullable String getFirmwareRevision() { - return firmwareRevision; - } + public abstract @Nullable Integer getTxPower(); /** - * Returns the software revision of the Bluetooth device. + * Returns the last Receive Signal Strength Indicator (RSSI) value or null if no RSSI has been received * - * @return The software revision, null if not known + * @return the last RSSI value in dBm */ - public @Nullable String getSoftwareRevision() { - return softwareRevision; - } + public abstract @Nullable Integer getRssi(); /** * Returns the physical address of the device. @@ -239,135 +151,19 @@ public BluetoothAdapter getAdapter() { return adapter; } - /** - * Sets the manufacturer id for the device - * - * @param manufacturer the manufacturer id - */ - public void setManufacturerId(int manufacturer) { - this.manufacturer = manufacturer; - } - - /** - * Returns the manufacturer ID of the device - * - * @return an integer with manufacturer ID of the device, or null if not known - */ - public @Nullable Integer getManufacturerId() { - return manufacturer; - } - /** * Returns a {@link BluetoothService} if the requested service is supported * * @return the {@link BluetoothService} or null if the service is not supported. */ - public @Nullable BluetoothService getServices(UUID uuid) { - return supportedServices.get(uuid); - } + public abstract @Nullable BluetoothService getServices(UUID uuid); /** * Returns a list of supported service UUIDs * * @return list of supported {@link BluetoothService}s. */ - public Collection getServices() { - return supportedServices.values(); - } - - /** - * Sets the device transmit power - * - * @param power the current transmitter power in dBm - */ - public void setTxPower(int txPower) { - this.txPower = txPower; - } - - /** - * Returns the last Transmit Power value or null if no transmit power has been received - * - * @return the last reported transmitter power value in dBm - */ - public @Nullable Integer getTxPower() { - return txPower; - } - - /** - * Sets the current Receive Signal Strength Indicator (RSSI) value - * - * @param rssi the current RSSI value in dBm - * @return true if the RSSI has changed, false if it was the same as previous - */ - public boolean setRssi(int rssi) { - boolean changed = (this.rssi == null || this.rssi != rssi); - this.rssi = rssi; - - return changed; - } - - /** - * Returns the last Receive Signal Strength Indicator (RSSI) value or null if no RSSI has been received - * - * @return the last RSSI value in dBm - */ - public @Nullable Integer getRssi() { - return rssi; - } - - /** - * Set the name of the device - * - * @param name a {@link String} defining the device name - */ - public void setName(String name) { - this.name = name; - } - - /** - * Set the model of the device - * - * @param model a {@link String} defining the device model - */ - public void setModel(String model) { - this.model = model; - } - - /** - * Set the serial number of the device - * - * @param model a {@link String} defining the serial number - */ - public void setSerialNumberl(String serialNumber) { - this.serialNumber = serialNumber; - } - - /** - * Set the hardware revision of the device - * - * @param model a {@link String} defining the hardware revision - */ - public void setHardwareRevision(String hardwareRevision) { - this.hardwareRevision = hardwareRevision; - } - - /** - * Set the firmware revision of the device - * - * @param model a {@link String} defining the firmware revision - */ - public void setFirmwareRevision(String firmwareRevision) { - this.firmwareRevision = firmwareRevision; - } - - /** - * Set the software revision of the device - * - * @param model a {@link String} defining the software revision - */ - public void setSoftwareRevision(String softwareRevision) { - this.softwareRevision = softwareRevision; - } + public abstract Collection getServices(); /** * Check if the device supports the specified service @@ -375,18 +171,14 @@ public void setSoftwareRevision(String softwareRevision) { * @param uuid the service {@link UUID} * @return true if the service is supported */ - public boolean supportsService(UUID uuid) { - return supportedServices.containsKey(uuid); - } + public abstract boolean supportsService(UUID uuid); /** * Get the current connection state for this device * * @return the current {@link ConnectionState} */ - public ConnectionState getConnectionState() { - return connectionState; - } + public abstract ConnectionState getConnectionState(); /** * Connects to a device. This is an asynchronous method. Once the connection state is updated, the @@ -396,9 +188,7 @@ public ConnectionState getConnectionState() { * * @return true if the connection process is started successfully */ - public boolean connect() { - return false; - } + public abstract boolean connect(); /** * Disconnects from a device. Once the connection state is updated, the @@ -409,9 +199,7 @@ public boolean connect() { * * @return true if the disconnection process is started successfully */ - public boolean disconnect() { - return false; - } + public abstract boolean disconnect(); /** * Starts a discovery on a device. This will iterate through all services and characteristics to build up a view of @@ -421,9 +209,7 @@ public boolean disconnect() { * * @return true if the discovery process is started successfully */ - public boolean discoverServices() { - return false; - } + public abstract boolean discoverServices(); /** * Gets a Bluetooth characteristic if it is known. @@ -436,7 +222,7 @@ public boolean discoverServices() { * @return the {@link BluetoothCharacteristic} or null if the characteristic is not found in the device */ public @Nullable BluetoothCharacteristic getCharacteristic(UUID uuid) { - for (BluetoothService service : supportedServices.values()) { + for (BluetoothService service : getServices()) { if (service.providesCharacteristic(uuid)) { return service.getCharacteristic(uuid); } @@ -457,9 +243,7 @@ public boolean discoverServices() { * @param characteristic the {@link BluetoothCharacteristic} to read. * @return true if the characteristic read is started successfully */ - public boolean readCharacteristic(BluetoothCharacteristic characteristic) { - return false; - } + public abstract boolean readCharacteristic(BluetoothCharacteristic characteristic); /** * Writes a characteristic. Only a single read or write operation can be requested at once. Attempting to perform an @@ -471,9 +255,7 @@ public boolean readCharacteristic(BluetoothCharacteristic characteristic) { * @param characteristic the {@link BluetoothCharacteristic} to read. * @return true if the characteristic write is started successfully */ - public boolean writeCharacteristic(BluetoothCharacteristic characteristic) { - return false; - } + public abstract boolean writeCharacteristic(BluetoothCharacteristic characteristic); /** * Enables notifications for a characteristic. Only a single read or write operation can be requested at once. @@ -485,9 +267,7 @@ public boolean writeCharacteristic(BluetoothCharacteristic characteristic) { * @param characteristic the {@link BluetoothCharacteristic} to receive notifications for. * @return true if the characteristic notification is started successfully */ - public boolean enableNotifications(BluetoothCharacteristic characteristic) { - return false; - } + public abstract boolean enableNotifications(BluetoothCharacteristic characteristic); /** * Disables notifications for a characteristic. Only a single read or write operation can be requested at once. @@ -497,9 +277,7 @@ public boolean enableNotifications(BluetoothCharacteristic characteristic) { * @param characteristic the {@link BluetoothCharacteristic} to disable notifications for. * @return true if the characteristic notification is stopped successfully */ - public boolean disableNotifications(BluetoothCharacteristic characteristic) { - return false; - } + public abstract boolean disableNotifications(BluetoothCharacteristic characteristic); /** * Enables notifications for a descriptor. Only a single read or write operation can be requested at once. @@ -511,9 +289,7 @@ public boolean disableNotifications(BluetoothCharacteristic characteristic) { * @param descriptor the {@link BluetoothDescriptor} to receive notifications for. * @return true if the descriptor notification is started successfully */ - public boolean enableNotifications(BluetoothDescriptor descriptor) { - return false; - } + public abstract boolean enableNotifications(BluetoothDescriptor descriptor); /** * Disables notifications for a descriptor. Only a single read or write operation can be requested at once. @@ -523,9 +299,7 @@ public boolean enableNotifications(BluetoothDescriptor descriptor) { * @param descriptor the {@link BluetoothDescriptor} to disable notifications for. * @return true if the descriptor notification is stopped successfully */ - public boolean disableNotifications(BluetoothDescriptor descriptor) { - return false; - } + public abstract boolean disableNotifications(BluetoothDescriptor descriptor); /** * Adds a service to the device. @@ -533,14 +307,7 @@ public boolean disableNotifications(BluetoothDescriptor descriptor) { * @param service the new {@link BluetoothService} to add * @return true if the service was added or false if the service was already supported */ - protected boolean addService(BluetoothService service) { - if (supportedServices.containsKey(service.getUuid())) { - return false; - } - logger.trace("Adding new service to device {}: {}", address, service); - supportedServices.put(service.getUuid(), service); - return true; - } + protected abstract boolean addService(BluetoothService service); /** * Adds a list of services to the device @@ -567,11 +334,9 @@ protected void addServices(List uuids) { * @return the {@link BluetoothService} or null if the service was not found */ protected @Nullable BluetoothService getServiceByHandle(int handle) { - synchronized (supportedServices) { - for (BluetoothService service : supportedServices.values()) { - if (service.getHandleStart() <= handle && service.getHandleEnd() >= handle) { - return service; - } + for (BluetoothService service : getServices()) { + if (service.getHandleStart() <= handle && service.getHandleEnd() >= handle) { + return service; } } return null; @@ -588,7 +353,6 @@ protected void addServices(List uuids) { if (service != null) { return service.getCharacteristicByHandle(handle); } - return null; } @@ -597,34 +361,27 @@ protected void addServices(List uuids) { * * @param listener the {@link BluetoothDeviceListener} to add */ - public void addListener(BluetoothDeviceListener listener) { - eventListeners.add(listener); - } + public abstract void addListener(BluetoothDeviceListener listener); /** * Removes a device listener * * @param listener the {@link BluetoothDeviceListener} to remove */ - public void removeListener(BluetoothDeviceListener listener) { - eventListeners.remove(listener); - } + public abstract void removeListener(BluetoothDeviceListener listener); /** * Checks if this device has any listeners * * @return true if this device has listeners */ - public boolean hasListeners() { - return !eventListeners.isEmpty(); - } + public abstract boolean hasListeners(); /** * Releases resources that this device is using. * */ - protected void dispose() { - } + protected abstract void dispose(); /** * Notify the listeners of an event @@ -632,67 +389,5 @@ protected void dispose() { * @param event the {@link BluetoothEventType} of this event * @param args an array of arguments to pass to the callback */ - protected void notifyListeners(BluetoothEventType event, Object... args) { - for (BluetoothDeviceListener listener : eventListeners) { - try { - switch (event) { - case SCAN_RECORD: - listener.onScanRecordReceived((BluetoothScanNotification) args[0]); - break; - case CONNECTION_STATE: - listener.onConnectionStateChange((BluetoothConnectionStatusNotification) args[0]); - break; - case SERVICES_DISCOVERED: - listener.onServicesDiscovered(); - break; - case CHARACTERISTIC_READ_COMPLETE: - listener.onCharacteristicReadComplete((BluetoothCharacteristic) args[0], - (BluetoothCompletionStatus) args[1]); - break; - case CHARACTERISTIC_WRITE_COMPLETE: - listener.onCharacteristicWriteComplete((BluetoothCharacteristic) args[0], - (BluetoothCompletionStatus) args[1]); - break; - case CHARACTERISTIC_UPDATED: - listener.onCharacteristicUpdate((BluetoothCharacteristic) args[0]); - break; - case DESCRIPTOR_UPDATED: - listener.onDescriptorUpdate((BluetoothDescriptor) args[0]); - break; - } - } catch (Exception e) { - logger.error("Failed to inform listener '{}': {}", listener, e.getMessage(), e); - } - } - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("BluetoothDevice [address="); - builder.append(address); - builder.append(", manufacturer="); - builder.append(manufacturer); - if (BluetoothCompanyIdentifiers.get(manufacturer) != null) { - builder.append(" ("); - builder.append(BluetoothCompanyIdentifiers.get(manufacturer)); - builder.append(')'); - } - builder.append(", name="); - builder.append(name); - builder.append(", model="); - builder.append(model); - builder.append(", serialNumber="); - builder.append(serialNumber); - builder.append(", hardwareRevision="); - builder.append(hardwareRevision); - builder.append(", firmwareRevision="); - builder.append(firmwareRevision); - builder.append(", softwareRevision="); - builder.append(softwareRevision); - builder.append(", rssi="); - builder.append(rssi); - builder.append(']'); - return builder.toString(); - } + protected abstract void notifyListeners(BluetoothEventType event, Object... args); } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/ConnectedBluetoothHandler.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/ConnectedBluetoothHandler.java index e7517b59a4e81..68bf24f3b9c37 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/ConnectedBluetoothHandler.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/ConnectedBluetoothHandler.java @@ -254,5 +254,4 @@ protected void activateChannel(@Nullable BluetoothCharacteristic characteristic, protected void activateChannel(@Nullable BluetoothCharacteristic characteristic, ChannelTypeUID channelTypeUID) { activateChannel(characteristic, channelTypeUID, null); } - } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/DelegateBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/DelegateBluetoothDevice.java new file mode 100644 index 0000000000000..11085f6e319fc --- /dev/null +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/DelegateBluetoothDevice.java @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bluetooth; + +import java.time.ZonedDateTime; +import java.util.Collection; +import java.util.UUID; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link DelegateBluetoothDevice} is an abstract parent class for BluetoothDevice implementations + * that delegate their functions to other BluetoothDevice instances. + * + * @author Connor Petty - Initial Contribution + */ +@NonNullByDefault +public abstract class DelegateBluetoothDevice extends BluetoothDevice { + + public DelegateBluetoothDevice(BluetoothAdapter adapter, BluetoothAddress address) { + super(adapter, address); + } + + protected abstract BluetoothDevice getDelegate(); + + @Override + public ZonedDateTime getLastSeenTime() { + return getDelegate().getLastSeenTime(); + } + + @Override + public void updateLastSeenTime() { + getDelegate().updateLastSeenTime(); + } + + @Override + public @Nullable String getName() { + return getDelegate().getName(); + } + + @Override + public @Nullable Integer getManufacturerId() { + return getDelegate().getManufacturerId(); + } + + @Override + public @Nullable Integer getRssi() { + return getDelegate().getRssi(); + } + + @Override + public @Nullable Integer getTxPower() { + return getDelegate().getTxPower(); + } + + @Override + public @Nullable BluetoothService getServices(UUID uuid) { + return getDelegate().getServices(uuid); + } + + @Override + public Collection getServices() { + return getDelegate().getServices(); + } + + @Override + public boolean supportsService(UUID uuid) { + return getDelegate().supportsService(uuid); + } + + @Override + public ConnectionState getConnectionState() { + return getDelegate().getConnectionState(); + } + + @Override + public boolean connect() { + return getDelegate().connect(); + } + + @Override + public boolean disconnect() { + return getDelegate().disconnect(); + } + + @Override + public boolean discoverServices() { + return getDelegate().discoverServices(); + } + + @Override + public boolean readCharacteristic(BluetoothCharacteristic characteristic) { + return getDelegate().readCharacteristic(characteristic); + } + + @Override + public boolean writeCharacteristic(BluetoothCharacteristic characteristic) { + return getDelegate().writeCharacteristic(characteristic); + } + + @Override + public boolean enableNotifications(BluetoothCharacteristic characteristic) { + return getDelegate().enableNotifications(characteristic); + } + + @Override + public boolean disableNotifications(BluetoothCharacteristic characteristic) { + return getDelegate().disableNotifications(characteristic); + } + + @Override + public boolean enableNotifications(BluetoothDescriptor descriptor) { + return getDelegate().enableNotifications(descriptor); + } + + @Override + public boolean disableNotifications(BluetoothDescriptor descriptor) { + return getDelegate().disableNotifications(descriptor); + } + + @Override + protected boolean addService(BluetoothService service) { + return getDelegate().addService(service); + } + + @Override + public void addListener(BluetoothDeviceListener listener) { + getDelegate().addListener(listener); + } + + @Override + public void removeListener(BluetoothDeviceListener listener) { + getDelegate().removeListener(listener); + } + + @Override + public boolean hasListeners() { + return getDelegate().hasListeners(); + } + + @Override + protected void notifyListeners(BluetoothEventType event, Object... args) { + getDelegate().notifyListeners(event, args); + } + + @Override + public @Nullable BluetoothCharacteristic getCharacteristic(UUID uuid) { + return getDelegate().getCharacteristic(uuid); + } + + @Override + protected void dispose() { + getDelegate().dispose(); + } +} diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/BluetoothDiscoveryDevice.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/BluetoothDiscoveryDevice.java new file mode 100644 index 0000000000000..bd0ef1aade4bb --- /dev/null +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/BluetoothDiscoveryDevice.java @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bluetooth.discovery; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.bluetooth.BluetoothCompanyIdentifiers; +import org.openhab.binding.bluetooth.BluetoothDevice; +import org.openhab.binding.bluetooth.DelegateBluetoothDevice; + +/** + * The {@link BluetoothDiscoveryDevice} is the BluetoothDevice subclass passed to + * BluetoothDiscoveryParticipants as part of discovery. It includes extra fields + * provided for the convenience of participant implementations. + * + * @author Connor Petty - Initial Contribution + */ +@NonNullByDefault +public class BluetoothDiscoveryDevice extends DelegateBluetoothDevice { + + private BluetoothDevice delegate; + + protected @Nullable String model; + protected @Nullable String serialNumber; + protected @Nullable String hardwareRevision; + protected @Nullable String firmwareRevision; + protected @Nullable String softwareRevision; + + public BluetoothDiscoveryDevice(BluetoothDevice device) { + super(device.getAdapter(), device.getAddress()); + this.delegate = device; + } + + @Override + protected BluetoothDevice getDelegate() { + return delegate; + } + + /** + * Returns the model of the Bluetooth device. + * + * @return The devices model, null if not known + */ + public @Nullable String getModel() { + return model; + } + + /** + * Returns the serial number of the Bluetooth device. + * + * @return The serial model, null if not known + */ + public @Nullable String getSerialNumber() { + return serialNumber; + } + + /** + * Returns the hardware revision of the Bluetooth device. + * + * @return The hardware revision, null if not known + */ + public @Nullable String getHardwareRevision() { + return hardwareRevision; + } + + /** + * Returns the firmware revision of the Bluetooth device. + * + * @return The firmware revision, null if not known + */ + public @Nullable String getFirmwareRevision() { + return firmwareRevision; + } + + /** + * Returns the software revision of the Bluetooth device. + * + * @return The software revision, null if not known + */ + public @Nullable String getSoftwareRevision() { + return softwareRevision; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("BluetoothDevice [address="); + builder.append(address); + builder.append(", manufacturer="); + + Integer manufacturer = getManufacturerId(); + builder.append(manufacturer); + if (BluetoothCompanyIdentifiers.get(manufacturer) != null) { + builder.append(" ("); + builder.append(BluetoothCompanyIdentifiers.get(manufacturer)); + builder.append(')'); + } + builder.append(", name="); + builder.append(getName()); + builder.append(", model="); + builder.append(model); + builder.append(", serialNumber="); + builder.append(serialNumber); + builder.append(", hardwareRevision="); + builder.append(hardwareRevision); + builder.append(", firmwareRevision="); + builder.append(firmwareRevision); + builder.append(", softwareRevision="); + builder.append(softwareRevision); + builder.append(", rssi="); + builder.append(getRssi()); + builder.append(']'); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/BluetoothDiscoveryParticipant.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/BluetoothDiscoveryParticipant.java index 48a71d29b1ffc..794bfed7e5a0c 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/BluetoothDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/BluetoothDiscoveryParticipant.java @@ -19,7 +19,6 @@ import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; -import org.openhab.binding.bluetooth.BluetoothDevice; /** * A {@link BluetoothDiscoveryParticipant} that is registered as a service is picked up by the BluetoothDiscoveryService @@ -45,7 +44,7 @@ public interface BluetoothDiscoveryParticipant { * @return the according discovery result or null, if device is not * supported by this participant */ - public @Nullable DiscoveryResult createResult(BluetoothDevice device); + public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device); /** * Returns the thing UID for a Bluetooth device @@ -53,7 +52,7 @@ public interface BluetoothDiscoveryParticipant { * @param device the Bluetooth device * @return a thing UID or null, if the device is not supported by this participant */ - public @Nullable ThingUID getThingUID(BluetoothDevice device); + public @Nullable ThingUID getThingUID(BluetoothDiscoveryDevice device); /** * Returns true if this participant requires the device to be connected before it can produce a @@ -69,7 +68,7 @@ public interface BluetoothDiscoveryParticipant { * @param device the Bluetooth device * @return true if a connection is required before calling {@link createResult(BluetoothDevice)} */ - public default boolean requiresConnection(BluetoothDevice device) { + public default boolean requiresConnection(BluetoothDiscoveryDevice device) { return false; } } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDeviceSnapshot.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDeviceSnapshot.java index 37b8aa764d5cc..648e4896fb885 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDeviceSnapshot.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDeviceSnapshot.java @@ -12,18 +12,13 @@ */ package org.openhab.binding.bluetooth.discovery.internal; -import java.util.Collection; import java.util.Objects; -import java.util.UUID; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.bluetooth.BluetoothAddress; -import org.openhab.binding.bluetooth.BluetoothCharacteristic; -import org.openhab.binding.bluetooth.BluetoothDescriptor; import org.openhab.binding.bluetooth.BluetoothDevice; -import org.openhab.binding.bluetooth.BluetoothDeviceListener; -import org.openhab.binding.bluetooth.BluetoothService; +import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryDevice; /** * The {@link BluetoothDeviceSnapshot} acts as a dummy {@link BluetoothDevice} implementation that simply acts as a @@ -32,106 +27,114 @@ * @author Connor Petty - Initial Contribution */ @NonNullByDefault -public class BluetoothDeviceSnapshot extends BluetoothDevice { +public class BluetoothDeviceSnapshot extends BluetoothDiscoveryDevice { - private BluetoothDevice delegate; + private @Nullable String name; + private @Nullable Integer manufacturer; + private @Nullable Integer txPower; public BluetoothDeviceSnapshot(BluetoothDevice device) { - super(device.getAdapter(), device.getAddress()); - this.delegate = device; + super(device); this.txPower = device.getTxPower(); this.manufacturer = device.getManufacturerId(); this.name = device.getName(); - this.model = device.getModel(); - this.serialNumber = device.getSerialNumber(); - this.hardwareRevision = device.getHardwareRevision(); - this.firmwareRevision = device.getFirmwareRevision(); - this.softwareRevision = device.getSoftwareRevision(); } @Override - public boolean connect() { - return delegate.connect(); + public @Nullable String getName() { + return name; } - @Override - public boolean disconnect() { - return delegate.disconnect(); - } - - @Override - public boolean enableNotifications(BluetoothCharacteristic characteristic) { - return delegate.enableNotifications(characteristic); - } - - @Override - public boolean enableNotifications(BluetoothDescriptor descriptor) { - return delegate.enableNotifications(descriptor); - } - - @Override - public boolean disableNotifications(BluetoothCharacteristic characteristic) { - return delegate.disableNotifications(characteristic); - } - - @Override - public boolean disableNotifications(BluetoothDescriptor descriptor) { - return delegate.disableNotifications(descriptor); - } - - @Override - public boolean discoverServices() { - return delegate.discoverServices(); - } - - @Override - public void addListener(BluetoothDeviceListener listener) { - delegate.addListener(listener); + /** + * Set the name of the device + * + * @param name a {@link String} defining the device name + */ + public void setName(String name) { + this.name = name; } - @Override - public void removeListener(BluetoothDeviceListener listener) { - delegate.removeListener(listener); + /** + * Sets the manufacturer id for the device + * + * @param manufacturer the manufacturer id + */ + public void setManufacturerId(int manufacturer) { + this.manufacturer = manufacturer; } + /** + * Returns the manufacturer ID of the device + * + * @return an integer with manufacturer ID of the device, or null if not known + */ @Override - public ConnectionState getConnectionState() { - return delegate.getConnectionState(); + public @Nullable Integer getManufacturerId() { + return manufacturer; } - @Override - public Collection getServices() { - return delegate.getServices(); + /** + * Sets the device transmit power + * + * @param power the current transmitter power in dBm + */ + public void setTxPower(int txPower) { + this.txPower = txPower; } + /** + * Returns the last Transmit Power value or null if no transmit power has been received + * + * @return the last reported transmitter power value in dBm + */ @Override - public @Nullable BluetoothService getServices(UUID uuid) { - return delegate.getServices(uuid); + public @Nullable Integer getTxPower() { + return txPower; } - @Override - public @Nullable BluetoothCharacteristic getCharacteristic(UUID uuid) { - return delegate.getCharacteristic(uuid); + /** + * Set the model of the device + * + * @param model a {@link String} defining the device model + */ + public void setModel(String model) { + this.model = model; } - @Override - public boolean hasListeners() { - return delegate.hasListeners(); + /** + * Set the serial number of the device + * + * @param model a {@link String} defining the serial number + */ + public void setSerialNumberl(String serialNumber) { + this.serialNumber = serialNumber; } - @Override - public boolean supportsService(UUID uuid) { - return delegate.supportsService(uuid); + /** + * Set the hardware revision of the device + * + * @param model a {@link String} defining the hardware revision + */ + public void setHardwareRevision(String hardwareRevision) { + this.hardwareRevision = hardwareRevision; } - @Override - public boolean readCharacteristic(BluetoothCharacteristic characteristic) { - return delegate.readCharacteristic(characteristic); + /** + * Set the firmware revision of the device + * + * @param model a {@link String} defining the firmware revision + */ + public void setFirmwareRevision(String firmwareRevision) { + this.firmwareRevision = firmwareRevision; } - @Override - public boolean writeCharacteristic(BluetoothCharacteristic characteristic) { - return delegate.writeCharacteristic(characteristic); + /** + * Set the software revision of the device + * + * @param model a {@link String} defining the software revision + */ + public void setSoftwareRevision(String softwareRevision) { + this.softwareRevision = softwareRevision; } @Override @@ -209,7 +212,7 @@ public boolean equals(@Nullable Object obj) { * * @return true if this snapshot changed as a result of this operation */ - public void merge(BluetoothDevice device) { + public void merge(BluetoothDeviceSnapshot device) { Integer txPower = device.getTxPower(); Integer manufacturer = device.getManufacturerId(); String name = device.getName(); @@ -245,5 +248,4 @@ public void merge(BluetoothDevice device) { this.softwareRevision = softwareRevision; } } - } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryProcess.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryProcess.java index 99d53c327e9c8..8c2044aea3b41 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryProcess.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryProcess.java @@ -66,7 +66,7 @@ public class BluetoothDiscoveryProcess implements Supplier, Blu private final Condition serviceDiscoveryCondition = serviceDiscoveryLock.newCondition(); private final Condition infoDiscoveryCondition = serviceDiscoveryLock.newCondition(); - private final BluetoothDevice device; + private final BluetoothDeviceSnapshot device; private final Collection participants; private final Set adapters; @@ -77,8 +77,8 @@ public class BluetoothDiscoveryProcess implements Supplier, Blu */ private volatile @Nullable GattCharacteristic ongoingGattCharacteristic; - public BluetoothDiscoveryProcess(BluetoothDevice device, Collection participants, - Set adapters) { + public BluetoothDiscoveryProcess(BluetoothDeviceSnapshot device, + Collection participants, Set adapters) { this.participants = participants; this.device = device; this.adapters = adapters; @@ -371,5 +371,4 @@ public void onCharacteristicUpdate(BluetoothCharacteristic characteristic) { @Override public void onDescriptorUpdate(BluetoothDescriptor bluetoothDescriptor) { } - } diff --git a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryService.java b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryService.java index 4df93ec2c7625..41e898a0b6ab6 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryService.java +++ b/bundles/org.openhab.binding.bluetooth/src/main/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryService.java @@ -269,11 +269,10 @@ private synchronized void createDiscoveryFuture(BluetoothDevice device) { discoveryFutures.put(adapter, new SnapshotFuture(snapshot, future)); } - private CompletableFuture startDiscoveryProcess(BluetoothDevice device) { + private CompletableFuture startDiscoveryProcess(BluetoothDeviceSnapshot device) { return CompletableFuture.supplyAsync(new BluetoothDiscoveryProcess(device, participants, adapters), scheduler); } - } private static class SnapshotFuture { @@ -284,7 +283,5 @@ public SnapshotFuture(BluetoothDeviceSnapshot snapshot, CompletableFutureRSSI Received signal strength indicator QualityOfService - + diff --git a/bundles/org.openhab.binding.bluetooth/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.bluetooth/src/main/resources/ESH-INF/thing/thing-types.xml index 24a0a105356d2..20fc62175bd6c 100644 --- a/bundles/org.openhab.binding.bluetooth/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.bluetooth/src/main/resources/ESH-INF/thing/thing-types.xml @@ -6,14 +6,14 @@ - - + + A generic Bluetooth device in beacon-mode - + @@ -26,14 +26,14 @@ - - + + A generic Bluetooth device in connected-mode - + diff --git a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothAdapter.java b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothAdapter.java index d5ace31518b34..25211f3af3bcb 100644 --- a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothAdapter.java +++ b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothAdapter.java @@ -66,5 +66,4 @@ public MockBluetoothDevice getDevice(BluetoothAddress address) { public boolean hasHandlerForDevice(BluetoothAddress address) { return false; } - } diff --git a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothDevice.java b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothDevice.java index 35f3fbfb40c4d..e4061f2d57df4 100644 --- a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothDevice.java +++ b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/MockBluetoothDevice.java @@ -15,6 +15,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; +import org.eclipse.jdt.annotation.NonNull; import org.openhab.binding.bluetooth.BluetoothCharacteristic.GattCharacteristic; import org.openhab.binding.bluetooth.notification.BluetoothConnectionStatusNotification; @@ -23,7 +24,7 @@ * * @author Connor Petty - Initial contribution */ -public class MockBluetoothDevice extends BluetoothDevice { +public class MockBluetoothDevice extends BaseBluetoothDevice { private AtomicBoolean servicesDiscovered = new AtomicBoolean(false); @@ -89,4 +90,28 @@ protected void notifyListeners(BluetoothEventType event, Object... args) { CompletableFuture.runAsync(() -> super.notifyListeners(event, args)); } + @Override + public boolean writeCharacteristic(@NonNull BluetoothCharacteristic characteristic) { + return false; + } + + @Override + public boolean enableNotifications(@NonNull BluetoothCharacteristic characteristic) { + return false; + } + + @Override + public boolean disableNotifications(@NonNull BluetoothCharacteristic characteristic) { + return false; + } + + @Override + public boolean enableNotifications(@NonNull BluetoothDescriptor descriptor) { + return false; + } + + @Override + public boolean disableNotifications(@NonNull BluetoothDescriptor descriptor) { + return false; + } } diff --git a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryServiceTest.java b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryServiceTest.java index 62b392dbebb2f..a82118d152e47 100644 --- a/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryServiceTest.java +++ b/bundles/org.openhab.binding.bluetooth/src/test/java/org/openhab/binding/bluetooth/discovery/internal/BluetoothDiscoveryServiceTest.java @@ -47,6 +47,7 @@ import org.openhab.binding.bluetooth.MockBluetoothAdapter; import org.openhab.binding.bluetooth.MockBluetoothDevice; import org.openhab.binding.bluetooth.TestUtils; +import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryDevice; import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryParticipant; import org.openhab.binding.bluetooth.notification.BluetoothConnectionStatusNotification; import org.slf4j.Logger; @@ -112,8 +113,8 @@ public void ignoreOtherDuplicateTest() { @Test public void ignoreRssiDuplicateTest() { - BluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); - BluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); + MockBluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); + MockBluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); discoveryService.deviceDiscovered(device); // changing the rssi should not result in a new discovery device.setRssi(100); @@ -126,8 +127,8 @@ public void ignoreRssiDuplicateTest() { @Test public void nonDuplicateNameTest() throws InterruptedException { - BluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); - BluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); + MockBluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); + MockBluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); discoveryService.deviceDiscovered(device); // this second call should produce another result device.setName("sdfad"); @@ -140,8 +141,8 @@ public void nonDuplicateNameTest() throws InterruptedException { @Test public void nonDuplicateTxPowerTest() { - BluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); - BluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); + MockBluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); + MockBluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); discoveryService.deviceDiscovered(device); // this second call should produce another result device.setTxPower(10); @@ -154,8 +155,8 @@ public void nonDuplicateTxPowerTest() { @Test public void nonDuplicateManufacturerIdTest() { - BluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); - BluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); + MockBluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); + MockBluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); discoveryService.deviceDiscovered(device); // this second call should produce another result device.setManufacturerId(100); @@ -316,8 +317,8 @@ public void removeDefaultDeviceTest() { @Test public void removeUpdatedDefaultDeviceTest() { Mockito.doReturn(null).when(participant1).createResult(ArgumentMatchers.any()); - BluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); - BluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); + MockBluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); + MockBluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); discoveryService.deviceDiscovered(device); device.setName("somename"); discoveryService.deviceDiscovered(device); @@ -354,12 +355,12 @@ public void bluezConnectionTimeoutTest() { public void replaceOlderDiscoveryTest() { Mockito.doReturn(null).when(participant1).createResult(ArgumentMatchers.any()); - BluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); - BluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); + MockBluetoothAdapter mockAdapter1 = new MockBluetoothAdapter(); + MockBluetoothDevice device = mockAdapter1.getDevice(TestUtils.randomAddress()); MockDiscoveryParticipant participant2 = new MockDiscoveryParticipant() { @Override - public @Nullable DiscoveryResult createResult(BluetoothDevice device) { + public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device) { Integer manufacturer = device.getManufacturerId(); if (manufacturer != null && manufacturer.equals(10)) { // without a device name it should produce a random ThingUID @@ -424,13 +425,13 @@ public void recursiveFutureTest() throws InterruptedException { MockDiscoveryParticipant participant2 = new MockDiscoveryParticipant() { @Override - public @Nullable DiscoveryResult createResult(BluetoothDevice device) { + public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device) { try { pauseLatch.await(); } catch (InterruptedException e) { // do nothing } - device.setName(deviceName); + ((BluetoothDeviceSnapshot) device).setName(deviceName); callCount.incrementAndGet(); return super.createResult(device); } @@ -465,18 +466,17 @@ public Set getSupportedThingTypeUIDs() { } @Override - public @Nullable DiscoveryResult createResult(BluetoothDevice device) { + public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device) { return DiscoveryResultBuilder.create(getThingUID(device)).withLabel(RandomStringUtils.randomAlphabetic(6)) .withRepresentationProperty(RandomStringUtils.randomAlphabetic(6)) .withBridge(device.getAdapter().getUID()).build(); } @Override - public @NonNull ThingUID getThingUID(BluetoothDevice device) { + public @NonNull ThingUID getThingUID(BluetoothDiscoveryDevice device) { String id = device.getName() != null ? device.getName() : RandomStringUtils.randomAlphabetic(6); return new ThingUID(typeUID, device.getAdapter().getUID(), id); } - } private class BadConnectionDevice extends MockBluetoothDevice { @@ -502,5 +502,4 @@ public boolean connect() { return false; } } - } diff --git a/bundles/org.openhab.binding.boschindego/pom.xml b/bundles/org.openhab.binding.boschindego/pom.xml index aae6e7e34c4bc..6a1ab1702fcf7 100644 --- a/bundles/org.openhab.binding.boschindego/pom.xml +++ b/bundles/org.openhab.binding.boschindego/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.boschindego diff --git a/bundles/org.openhab.binding.boschindego/src/main/feature/feature.xml b/bundles/org.openhab.binding.boschindego/src/main/feature/feature.xml index 22bafe1398949..5dfb526148149 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.boschindego/src/main/feature/feature.xml @@ -1,13 +1,13 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab.tp-jackson - mvn:org.apache.httpcomponents/httpcore-osgi/4.4.9 - mvn:org.apache.httpcomponents/httpclient-osgi/4.5.5 - mvn:commons-codec/commons-codec/1.10 - mvn:org.openhab.addons.bundles/org.openhab.binding.boschindego/${project.version} - + + openhab-runtime-base + openhab.tp-jackson + mvn:org.apache.httpcomponents/httpcore-osgi/4.4.9 + mvn:org.apache.httpcomponents/httpclient-osgi/4.5.5 + mvn:commons-codec/commons-codec/1.10 + mvn:org.openhab.addons.bundles/org.openhab.binding.boschindego/${project.version} + diff --git a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/BoschIndegoBindingConstants.java b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/BoschIndegoBindingConstants.java index 7a1fb6e9da62a..46c4b53fec129 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/BoschIndegoBindingConstants.java +++ b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/BoschIndegoBindingConstants.java @@ -36,5 +36,4 @@ public class BoschIndegoBindingConstants { public static final String ERRORCODE = "errorcode"; public static final String STATECODE = "statecode"; public static final String READY = "ready"; - } diff --git a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/IndegoStateConstants.java b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/IndegoStateConstants.java index 5c325339aa8ee..cec3c5ff81c8b 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/IndegoStateConstants.java +++ b/bundles/org.openhab.binding.boschindego/src/main/java/org/openhab/binding/boschindego/internal/IndegoStateConstants.java @@ -26,5 +26,4 @@ public class IndegoStateConstants { public static final int STATE_DOCKED_3 = 261; public static final int STATE_PAUSED = 517; public static final int STATE_IDLE_IN_LAWN = 519; - } diff --git a/bundles/org.openhab.binding.boschindego/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.boschindego/src/main/resources/ESH-INF/binding/binding.xml index 74cb41eb51d7c..3c9baea8775ed 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.boschindego/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + BoschIndego Binding This is the binding for Bosch Indego Connect lawn mowers. diff --git a/bundles/org.openhab.binding.boschindego/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.boschindego/src/main/resources/ESH-INF/thing/thing-types.xml index cc6798ff0179c..431de7e9ecaa7 100644 --- a/bundles/org.openhab.binding.boschindego/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.boschindego/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -16,21 +16,21 @@ - - - Username for the Bosch Indego account. - - - password - - Password for the Bosch Indego account. - - - - Specifies the refresh interval in seconds. - 180 - - + + + Username for the Bosch Indego account. + + + password + + Password for the Bosch Indego account. + + + + Specifies the refresh interval in seconds. + 180 + + @@ -55,38 +55,38 @@ API-code of the Indego state - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + String - + Dimmer diff --git a/bundles/org.openhab.binding.bosesoundtouch/pom.xml b/bundles/org.openhab.binding.bosesoundtouch/pom.xml index 5d7bb1fdcd380..c4620532fab0f 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/pom.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bosesoundtouch diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/feature/feature.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/feature/feature.xml index fc7d06348db1a..6ec7719042c08 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - openhab-transport-mdns - mvn:org.openhab.addons.bundles/org.openhab.binding.bosesoundtouch/${project.version} - + + openhab-runtime-base + openhab-transport-http + openhab-transport-mdns + mvn:org.openhab.addons.bundles/org.openhab.binding.bosesoundtouch/${project.version} + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchBindingConstants.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchBindingConstants.java index 0bd8c8bec0123..ef86e02e30a9b 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchBindingConstants.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchBindingConstants.java @@ -1,97 +1,96 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bosesoundtouch.internal; - -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.eclipse.smarthome.core.thing.ThingTypeUID; - -/** - * The {@link BoseSoundTouchBindinConstantsg} class defines common constants, which are - * used across the whole binding. - * - * @author Christian Niessner - Initial contribution - * @author Thomas Traunbauer - Initial contribution - */ -public class BoseSoundTouchBindingConstants { - - public static final String BINDING_ID = "bosesoundtouch"; - - // List of all Thing Type UIDs - public static final ThingTypeUID BST_UNKNOWN_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "device"); - - public static final ThingTypeUID BST_10_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "10"); - public static final ThingTypeUID BST_20_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "20"); - public static final ThingTypeUID BST_30_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "30"); - public static final ThingTypeUID BST_300_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "300"); - public static final ThingTypeUID BST_WLA_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "wirelessLinkAdapter"); - public static final ThingTypeUID BST_WSMS_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, - "waveSoundTouchMusicSystemIV"); - public static final ThingTypeUID BST_SA5A_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "sa5Amplifier"); - - public static final Set SUPPORTED_KNOWN_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream - .of(BST_UNKNOWN_THING_TYPE_UID, BST_10_THING_TYPE_UID, BST_20_THING_TYPE_UID, BST_30_THING_TYPE_UID, - BST_300_THING_TYPE_UID, BST_WLA_THING_TYPE_UID, BST_WSMS_THING_TYPE_UID, BST_SA5A_THING_TYPE_UID) - .collect(Collectors.toSet())); - - public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>(SUPPORTED_KNOWN_THING_TYPES_UIDS); - - // Partial list of Channel Type IDs - public static final String CHANNEL_TYPE_OPERATION_MODE_DEFAULT = "operationMode_default"; - public static final String CHANNEL_TYPE_OPERATION_MODE_BST_10_20_30 = "operationMode_BST_10_20_30"; - public static final String CHANNEL_TYPE_OPERATION_MODE_BST_300 = "operationMode_BST_300"; - public static final String CHANNEL_TYPE_OPERATION_MODE_BST_SA5A = "operationMode_BST_SA5_Amplifier"; - public static final String CHANNEL_TYPE_OPERATION_MODE_BST_WLA = "operationMode_BST_WLA"; - - // List of all Channel IDs - public static final String CHANNEL_POWER = "power"; - public static final String CHANNEL_VOLUME = "volume"; - public static final String CHANNEL_MUTE = "mute"; - public static final String CHANNEL_OPERATIONMODE = "operationMode"; - public static final String CHANNEL_PLAYER_CONTROL = "playerControl"; - public static final String CHANNEL_PRESET = "preset"; - public static final String CHANNEL_BASS = "bass"; - public static final String CHANNEL_RATEENABLED = "rateEnabled"; - public static final String CHANNEL_SKIPENABLED = "skipEnabled"; - public static final String CHANNEL_SKIPPREVIOUSENABLED = "skipPreviousEnabled"; - public static final String CHANNEL_SAVE_AS_PRESET = "saveAsPreset"; - public static final String CHANNEL_KEY_CODE = "keyCode"; - public static final String CHANNEL_NOWPLAYING_ALBUM = "nowPlayingAlbum"; - public static final String CHANNEL_NOWPLAYING_ARTWORK = "nowPlayingArtwork"; - public static final String CHANNEL_NOWPLAYING_ARTIST = "nowPlayingArtist"; - public static final String CHANNEL_NOWPLAYING_DESCRIPTION = "nowPlayingDescription"; - public static final String CHANNEL_NOWPLAYING_GENRE = "nowPlayingGenre"; - public static final String CHANNEL_NOWPLAYING_ITEMNAME = "nowPlayingItemName"; - public static final String CHANNEL_NOWPLAYING_STATIONLOCATION = "nowPlayingStationLocation"; - public static final String CHANNEL_NOWPLAYING_STATIONNAME = "nowPlayingStationName"; - public static final String CHANNEL_NOWPLAYING_TRACK = "nowPlayingTrack"; - public static final String CHANNEL_NOTIFICATION_SOUND = "notificationsound"; - - public static final List CHANNEL_IDS = Collections.unmodifiableList( - Stream.of(CHANNEL_POWER, CHANNEL_VOLUME, CHANNEL_MUTE, CHANNEL_OPERATIONMODE, CHANNEL_PLAYER_CONTROL, - CHANNEL_PRESET, CHANNEL_BASS, CHANNEL_RATEENABLED, CHANNEL_SKIPENABLED, CHANNEL_SKIPPREVIOUSENABLED, - CHANNEL_SAVE_AS_PRESET, CHANNEL_KEY_CODE, CHANNEL_NOWPLAYING_ALBUM, CHANNEL_NOWPLAYING_ARTWORK, - CHANNEL_NOWPLAYING_ARTIST, CHANNEL_NOWPLAYING_DESCRIPTION, CHANNEL_NOWPLAYING_GENRE, - CHANNEL_NOWPLAYING_ITEMNAME, CHANNEL_NOWPLAYING_STATIONLOCATION, CHANNEL_NOWPLAYING_STATIONNAME, - CHANNEL_NOWPLAYING_TRACK, CHANNEL_NOTIFICATION_SOUND).collect(Collectors.toList())); - - // Device information parameters; - public static final String DEVICE_INFO_NAME = "INFO_NAME"; - public static final String DEVICE_INFO_TYPE = "INFO_TYPE"; - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bosesoundtouch.internal; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link BoseSoundTouchBindinConstantsg} class defines common constants, which are + * used across the whole binding. + * + * @author Christian Niessner - Initial contribution + * @author Thomas Traunbauer - Initial contribution + */ +public class BoseSoundTouchBindingConstants { + + public static final String BINDING_ID = "bosesoundtouch"; + + // List of all Thing Type UIDs + public static final ThingTypeUID BST_UNKNOWN_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "device"); + + public static final ThingTypeUID BST_10_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "10"); + public static final ThingTypeUID BST_20_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "20"); + public static final ThingTypeUID BST_30_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "30"); + public static final ThingTypeUID BST_300_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "300"); + public static final ThingTypeUID BST_WLA_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "wirelessLinkAdapter"); + public static final ThingTypeUID BST_WSMS_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, + "waveSoundTouchMusicSystemIV"); + public static final ThingTypeUID BST_SA5A_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "sa5Amplifier"); + + public static final Set SUPPORTED_KNOWN_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream + .of(BST_UNKNOWN_THING_TYPE_UID, BST_10_THING_TYPE_UID, BST_20_THING_TYPE_UID, BST_30_THING_TYPE_UID, + BST_300_THING_TYPE_UID, BST_WLA_THING_TYPE_UID, BST_WSMS_THING_TYPE_UID, BST_SA5A_THING_TYPE_UID) + .collect(Collectors.toSet())); + + public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>(SUPPORTED_KNOWN_THING_TYPES_UIDS); + + // Partial list of Channel Type IDs + public static final String CHANNEL_TYPE_OPERATION_MODE_DEFAULT = "operationMode_default"; + public static final String CHANNEL_TYPE_OPERATION_MODE_BST_10_20_30 = "operationMode_BST_10_20_30"; + public static final String CHANNEL_TYPE_OPERATION_MODE_BST_300 = "operationMode_BST_300"; + public static final String CHANNEL_TYPE_OPERATION_MODE_BST_SA5A = "operationMode_BST_SA5_Amplifier"; + public static final String CHANNEL_TYPE_OPERATION_MODE_BST_WLA = "operationMode_BST_WLA"; + + // List of all Channel IDs + public static final String CHANNEL_POWER = "power"; + public static final String CHANNEL_VOLUME = "volume"; + public static final String CHANNEL_MUTE = "mute"; + public static final String CHANNEL_OPERATIONMODE = "operationMode"; + public static final String CHANNEL_PLAYER_CONTROL = "playerControl"; + public static final String CHANNEL_PRESET = "preset"; + public static final String CHANNEL_BASS = "bass"; + public static final String CHANNEL_RATEENABLED = "rateEnabled"; + public static final String CHANNEL_SKIPENABLED = "skipEnabled"; + public static final String CHANNEL_SKIPPREVIOUSENABLED = "skipPreviousEnabled"; + public static final String CHANNEL_SAVE_AS_PRESET = "saveAsPreset"; + public static final String CHANNEL_KEY_CODE = "keyCode"; + public static final String CHANNEL_NOWPLAYING_ALBUM = "nowPlayingAlbum"; + public static final String CHANNEL_NOWPLAYING_ARTWORK = "nowPlayingArtwork"; + public static final String CHANNEL_NOWPLAYING_ARTIST = "nowPlayingArtist"; + public static final String CHANNEL_NOWPLAYING_DESCRIPTION = "nowPlayingDescription"; + public static final String CHANNEL_NOWPLAYING_GENRE = "nowPlayingGenre"; + public static final String CHANNEL_NOWPLAYING_ITEMNAME = "nowPlayingItemName"; + public static final String CHANNEL_NOWPLAYING_STATIONLOCATION = "nowPlayingStationLocation"; + public static final String CHANNEL_NOWPLAYING_STATIONNAME = "nowPlayingStationName"; + public static final String CHANNEL_NOWPLAYING_TRACK = "nowPlayingTrack"; + public static final String CHANNEL_NOTIFICATION_SOUND = "notificationsound"; + + public static final List CHANNEL_IDS = Collections.unmodifiableList( + Stream.of(CHANNEL_POWER, CHANNEL_VOLUME, CHANNEL_MUTE, CHANNEL_OPERATIONMODE, CHANNEL_PLAYER_CONTROL, + CHANNEL_PRESET, CHANNEL_BASS, CHANNEL_RATEENABLED, CHANNEL_SKIPENABLED, CHANNEL_SKIPPREVIOUSENABLED, + CHANNEL_SAVE_AS_PRESET, CHANNEL_KEY_CODE, CHANNEL_NOWPLAYING_ALBUM, CHANNEL_NOWPLAYING_ARTWORK, + CHANNEL_NOWPLAYING_ARTIST, CHANNEL_NOWPLAYING_DESCRIPTION, CHANNEL_NOWPLAYING_GENRE, + CHANNEL_NOWPLAYING_ITEMNAME, CHANNEL_NOWPLAYING_STATIONLOCATION, CHANNEL_NOWPLAYING_STATIONNAME, + CHANNEL_NOWPLAYING_TRACK, CHANNEL_NOTIFICATION_SOUND).collect(Collectors.toList())); + + // Device information parameters; + public static final String DEVICE_INFO_NAME = "INFO_NAME"; + public static final String DEVICE_INFO_TYPE = "INFO_TYPE"; +} diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchConfiguration.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchConfiguration.java index dede672884757..ceb82dfef5db1 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchConfiguration.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchConfiguration.java @@ -1,35 +1,35 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bosesoundtouch.internal; - -import org.eclipse.smarthome.core.thing.Thing; - -/** - * Configuration class for soundtouch - * - * @author Ivaylo Ivanov - Initial contribution - */ -public class BoseSoundTouchConfiguration { - - // Device configuration parameters; - public static final String HOST = "host"; - public static final String MAC_ADDRESS = Thing.PROPERTY_MAC_ADDRESS; - public static final String APP_KEY = "appKey"; - - public String host; - public String macAddress; - public String appKey; - - // Not an actual configuration field, but it will contain the name of the group (in case of Stereo Pair) - public String groupName; -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bosesoundtouch.internal; + +import org.eclipse.smarthome.core.thing.Thing; + +/** + * Configuration class for soundtouch + * + * @author Ivaylo Ivanov - Initial contribution + */ +public class BoseSoundTouchConfiguration { + + // Device configuration parameters; + public static final String HOST = "host"; + public static final String MAC_ADDRESS = Thing.PROPERTY_MAC_ADDRESS; + public static final String APP_KEY = "appKey"; + + public String host; + public String macAddress; + public String appKey; + + // Not an actual configuration field, but it will contain the name of the group (in case of Stereo Pair) + public String groupName; +} diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchNotificationChannelConfiguration.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchNotificationChannelConfiguration.java index a40e8b302b321..81fbc61ff5c02 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchNotificationChannelConfiguration.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/BoseSoundTouchNotificationChannelConfiguration.java @@ -1,42 +1,42 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bosesoundtouch.internal; - -/** - * Configuration class for soundtouch notification channel - * - * @author Ivaylo Ivanov - Initial contribution - */ -public class BoseSoundTouchNotificationChannelConfiguration { - - public static final String MIN_FIRMWARE = "14"; - public static final String MODEL_TYPE = "sm2"; - - public static final String NOTIFICATION_VOLUME = "notificationVolume"; - public static final String NOTIFICATION_SERVICE = "notificationService"; - public static final String NOTIFICATION_REASON = "notificationReason"; - public static final String NOTIFICATION_MESSAGE = "notificationMessage"; - - public Integer notificationVolume; - public String notificationService; - public String notificationReason; - public String notificationMessage; - - public static boolean isSupportedFirmware(String firmware) { - return firmware != null && firmware.compareTo(MIN_FIRMWARE) > 0; - } - - public static boolean isSupportedHardware(String hardware) { - return MODEL_TYPE.equals(hardware); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bosesoundtouch.internal; + +/** + * Configuration class for soundtouch notification channel + * + * @author Ivaylo Ivanov - Initial contribution + */ +public class BoseSoundTouchNotificationChannelConfiguration { + + public static final String MIN_FIRMWARE = "14"; + public static final String MODEL_TYPE = "sm2"; + + public static final String NOTIFICATION_VOLUME = "notificationVolume"; + public static final String NOTIFICATION_SERVICE = "notificationService"; + public static final String NOTIFICATION_REASON = "notificationReason"; + public static final String NOTIFICATION_MESSAGE = "notificationMessage"; + + public Integer notificationVolume; + public String notificationService; + public String notificationReason; + public String notificationMessage; + + public static boolean isSupportedFirmware(String firmware) { + return firmware != null && firmware.compareTo(MIN_FIRMWARE) > 0; + } + + public static boolean isSupportedHardware(String hardware) { + return MODEL_TYPE.equals(hardware); + } +} diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/CommandExecutor.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/CommandExecutor.java index 0a0e651e66fea..b7f578c961e08 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/CommandExecutor.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/CommandExecutor.java @@ -82,9 +82,9 @@ public void updatePresetContainerFromPlayer(Map playerPres /** * Adds a ContentItem to the PresetContainer * - * @param id the id the ContentItem should be reached + * @param id the id the ContentItem should be reached * @param contentItem the contentItem that should be saved as PRESET. Note that a eventually set presetID of the - * ContentItem will be overwritten with id + * ContentItem will be overwritten with id */ public void addContentItemToPresetContainer(int id, ContentItem contentItem) { contentItem.setPresetID(id); @@ -100,7 +100,7 @@ public void addContentItemToPresetContainer(int id, ContentItem contentItem) { * Adds the current selected ContentItem to the PresetContainer * * @param command the command is a DecimalType, thats intValue will be used as id. The id the ContentItem should be - * reached + * reached */ public void addCurrentContentItemToPresetContainer(DecimalType command) { if (command.intValue() > 6) { diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/ContentItem.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/ContentItem.java index b8b79d18b539d..63382403476ce 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/ContentItem.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/ContentItem.java @@ -192,7 +192,7 @@ public boolean isPresetable() { public int getPresetID() { return presetID; } - + public String getContainerArt() { return containerArt; } @@ -249,7 +249,7 @@ public String generateXML() { } return xml; } - + public StateOption toStateOption() { String stateOptionLabel = String.valueOf(presetID) + ": " + itemName; return new StateOption(String.valueOf(presetID), stateOptionLabel); diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/ContentItemMaker.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/ContentItemMaker.java index 6b150abc801ec..f599ae5a82c64 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/ContentItemMaker.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/ContentItemMaker.java @@ -233,5 +233,4 @@ private ContentItem getTV() throws OperationModeNotAvailableException { throw new OperationModeNotAvailableException(); } } - } diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/RemoteKeyType.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/RemoteKeyType.java index f2e4321d65d6d..c9fa043efdf24 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/RemoteKeyType.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/RemoteKeyType.java @@ -57,5 +57,4 @@ private RemoteKeyType() { public String toString() { return name; } - } diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/XMLResponseHandler.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/XMLResponseHandler.java index 3033de1ccd132..6e6168d43bb5d 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/XMLResponseHandler.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/XMLResponseHandler.java @@ -1,691 +1,690 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bosesoundtouch.internal; - -import static org.eclipse.smarthome.core.thing.Thing.PROPERTY_FIRMWARE_VERSION; -import static org.eclipse.smarthome.core.thing.Thing.PROPERTY_HARDWARE_VERSION; -import static org.eclipse.smarthome.core.thing.Thing.PROPERTY_MODEL_ID; -import static org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchBindingConstants.*; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Stack; - -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.library.types.PlayPauseType; -import org.eclipse.smarthome.core.library.types.RawType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.UnDefType; -import org.eclipse.smarthome.io.net.http.HttpUtil; -import org.openhab.binding.bosesoundtouch.internal.handler.BoseSoundTouchHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -/** - * The {@link XMLResponseHandler} class handles the XML communication with the Soundtouch - * - * @author Christian Niessner - Initial contribution - * @author Thomas Traunbauer - Initial contribution - * @author Kai Kreuzer - code clean up - */ -public class XMLResponseHandler extends DefaultHandler { - - private final Logger logger = LoggerFactory.getLogger(XMLResponseHandler.class); - - private BoseSoundTouchHandler handler; - private CommandExecutor commandExecutor; - - private Map> stateSwitchingMap; - - private Stack states; - private XMLHandlerState state; - private boolean msgHeaderWasValid; - - private ContentItem contentItem; - private boolean volumeMuteEnabled; - private OnOffType rateEnabled; - private OnOffType skipEnabled; - private OnOffType skipPreviousEnabled; - - private State nowPlayingSource; - - private BoseSoundTouchConfiguration masterDeviceId; - String deviceId; - - private Map playerPresets; - - /** - * Creates a new instance of this class - * - * @param handler - * @param stateSwitchingMap the stateSwitchingMap is the XMLState Map, that says which Flags are computed - */ - public XMLResponseHandler(BoseSoundTouchHandler handler, - Map> stateSwitchingMap) { - this.handler = handler; - this.commandExecutor = handler.getCommandExecutor(); - this.stateSwitchingMap = stateSwitchingMap; - init(); - } - - @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - super.startElement(uri, localName, qName, attributes); - logger.trace("{}: startElement('{}'; state: {})", handler.getDeviceName(), localName, state); - states.push(state); - XMLHandlerState curState = state; // save for switch statement - Map stateMap = stateSwitchingMap.get(state); - state = XMLHandlerState.Unprocessed; // set default value; we avoid default in select to have the compiler - // showing a - // warning for unhandled states - switch (curState) { - case INIT: - if ("updates".equals(localName)) { - // it just seems to be a ping - havn't seen any data on it.. - if (checkDeviceId(localName, attributes, false)) { - state = XMLHandlerState.Updates; - } else { - state = XMLHandlerState.Unprocessed; - } - } else { - state = stateMap.get(localName); - if (state == null) { - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}", handler.getDeviceName(), curState, - localName); - } - state = XMLHandlerState.Unprocessed; - } - } - break; - case Msg: - if ("header".equals(localName)) { - // message - if (checkDeviceId(localName, attributes, false)) { - state = XMLHandlerState.MsgHeader; - msgHeaderWasValid = true; - } else { - state = XMLHandlerState.Unprocessed; - } - } else if ("body".equals(localName)) { - if (msgHeaderWasValid) { - state = XMLHandlerState.MsgBody; - } else { - state = XMLHandlerState.Unprocessed; - } - } else { - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, - localName); - } - state = XMLHandlerState.Unprocessed; - } - break; - case MsgHeader: - if ("request".equals(localName)) { - state = XMLHandlerState.Unprocessed; // TODO implement request id / response tracking... - } else { - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, - localName); - } - state = XMLHandlerState.Unprocessed; - } - break; - case MsgBody: - if ("nowPlaying".equals(localName)) { - /* - * if (!checkDeviceId(localName, attributes, true)) { - * state = XMLHandlerState.Unprocessed; - * break; - * } - */ - rateEnabled = OnOffType.OFF; - skipEnabled = OnOffType.OFF; - skipPreviousEnabled = OnOffType.OFF; - state = XMLHandlerState.NowPlaying; - String source = attributes.getValue("source"); - if (nowPlayingSource == null || !nowPlayingSource.toString().equals(source)) { - // source changed - nowPlayingSource = new StringType(source); - // reset enabled states - updateRateEnabled(OnOffType.OFF); - updateSkipEnabled(OnOffType.OFF); - updateSkipPreviousEnabled(OnOffType.OFF); - - // clear all "nowPlaying" details on source change... - updateNowPlayingAlbum(UnDefType.NULL); - updateNowPlayingArtwork(UnDefType.NULL); - updateNowPlayingArtist(UnDefType.NULL); - updateNowPlayingDescription(UnDefType.NULL); - updateNowPlayingGenre(UnDefType.NULL); - updateNowPlayingItemName(UnDefType.NULL); - updateNowPlayingStationLocation(UnDefType.NULL); - updateNowPlayingStationName(UnDefType.NULL); - updateNowPlayingTrack(UnDefType.NULL); - } - } else if ("zone".equals(localName)) { - state = XMLHandlerState.Zone; - } else if ("presets".equals(localName)) { - // reset the current playerPrests - playerPresets = new HashMap<>(); - for (int i = 1; i <= 6; i++) { - playerPresets.put(i, null); - } - state = XMLHandlerState.Presets; - } else if ("group".equals(localName)) { - this.masterDeviceId = new BoseSoundTouchConfiguration(); - state = stateMap.get(localName); - } else { - state = stateMap.get(localName); - if (state == null) { - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}", handler.getDeviceName(), curState, - localName); - } - state = XMLHandlerState.Unprocessed; - } else if (state != XMLHandlerState.Volume && state != XMLHandlerState.Presets - && state != XMLHandlerState.Group - && state != XMLHandlerState.Unprocessed) { - if (!checkDeviceId(localName, attributes, false)) { - state = XMLHandlerState.Unprocessed; - break; - } - } - } - break; - case Presets: - if ("preset".equals(localName)) { - state = XMLHandlerState.Preset; - String id = attributes.getValue("id"); - if (contentItem == null) { - contentItem = new ContentItem(); - } - contentItem.setPresetID(Integer.parseInt(id)); - } else { - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, - localName); - } - state = XMLHandlerState.Unprocessed; - } - break; - case Sources: - if ("sourceItem".equals(localName)) { - state = XMLHandlerState.Unprocessed; - String source = attributes.getValue("source"); - String sourceAccount = attributes.getValue("sourceAccount"); - String status = attributes.getValue("status"); - if (status.equals("READY")) { - if (source.equals("AUX")) { - if (sourceAccount.equals("AUX")) { - commandExecutor.setAUXAvailable(true); - } - if (sourceAccount.equals("AUX1")) { - commandExecutor.setAUX1Available(true); - } - if (sourceAccount.equals("AUX2")) { - commandExecutor.setAUX2Available(true); - } - if (sourceAccount.equals("AUX3")) { - commandExecutor.setAUX3Available(true); - } - } - if (source.equals("STORED_MUSIC")) { - commandExecutor.setStoredMusicAvailable(true); - } - if (source.equals("INTERNET_RADIO")) { - commandExecutor.setInternetRadioAvailable(true); - } - if (source.equals("BLUETOOTH")) { - commandExecutor.setBluetoothAvailable(true); - } - if (source.equals("PRODUCT")) { - if (sourceAccount.equals("TV")) { - commandExecutor.setTVAvailable(true); - } - if (sourceAccount.equals("HDMI_1")) { - commandExecutor.setHDMI1Available(true); - } - } - } - } else { - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, - localName); - } - state = XMLHandlerState.Unprocessed; - } - break; - // auto go trough the state map - case Group: - case Zone: - case Bass: - case ContentItem: - case MasterDeviceId: - case GroupName: - case DeviceId: - case DeviceIp: - case Info: - case NowPlaying: - case Preset: - case Updates: - case Volume: - case Components: - case Component: - state = nextState(stateMap, curState, localName); - break; - case BassCapabilities: - state = nextState(stateMap, curState, localName); - break; - // all entities without any children expected.. - case BassTarget: - case BassActual: - case BassUpdated: - case BassMin: - case BassMax: - case BassDefault: - case ContentItemItemName: - case ContentItemContainerArt: - case InfoName: - case InfoType: - case InfoFirmwareVersion: - case InfoModuleType: - case NowPlayingAlbum: - case NowPlayingArt: - case NowPlayingArtist: - case NowPlayingGenre: - case NowPlayingDescription: - case NowPlayingPlayStatus: - case NowPlayingRateEnabled: - case NowPlayingSkipEnabled: - case NowPlayingSkipPreviousEnabled: - case NowPlayingStationLocation: - case NowPlayingStationName: - case NowPlayingTrack: - case VolumeTarget: - case VolumeActual: - case VolumeUpdated: - case VolumeMuteEnabled: - case ZoneMember: - case ZoneUpdated: // currently this dosn't provide any zone details.. - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, - localName); - } - state = XMLHandlerState.Unprocessed; - break; - case BassAvailable: - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, - localName); - } - state = XMLHandlerState.Unprocessed; - break; - case Unprocessed: - // all further things are also unprocessed - state = XMLHandlerState.Unprocessed; - break; - case UnprocessedNoTextExpected: - state = XMLHandlerState.UnprocessedNoTextExpected; - break; - } - if (state == XMLHandlerState.ContentItem) { - if (contentItem == null) { - contentItem = new ContentItem(); - } - contentItem.setSource(attributes.getValue("source")); - contentItem.setSourceAccount(attributes.getValue("sourceAccount")); - contentItem.setLocation(attributes.getValue("location")); - contentItem.setPresetable(Boolean.parseBoolean(attributes.getValue("isPresetable"))); - for (int attrId = 0; attrId < attributes.getLength(); attrId++) { - String attrName = attributes.getLocalName(attrId); - if ("source".equalsIgnoreCase(attrName)) { - continue; - } - if ("location".equalsIgnoreCase(attrName)) { - continue; - } - if ("sourceAccount".equalsIgnoreCase(attrName)) { - continue; - } - if ("isPresetable".equalsIgnoreCase(attrName)) { - continue; - } - contentItem.setAdditionalAttribute(attrName, attributes.getValue(attrId)); - } - } - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - super.endElement(uri, localName, qName); - logger.trace("{}: endElement('{}')", handler.getDeviceName(), localName); - final XMLHandlerState prevState = state; - state = states.pop(); - switch (prevState) { - case Info: - commandExecutor.getInformations(APIRequest.VOLUME); - commandExecutor.getInformations(APIRequest.PRESETS); - commandExecutor.getInformations(APIRequest.NOW_PLAYING); - commandExecutor.getInformations(APIRequest.GET_ZONE); - commandExecutor.getInformations(APIRequest.BASS); - commandExecutor.getInformations(APIRequest.SOURCES); - commandExecutor.getInformations(APIRequest.BASSCAPABILITIES); - commandExecutor.getInformations(APIRequest.GET_GROUP); - break; - case ContentItem: - if (state == XMLHandlerState.NowPlaying) { - // update now playing name... - updateNowPlayingItemName(new StringType(contentItem.getItemName())); - commandExecutor.setCurrentContentItem(contentItem); - } - break; - case Preset: - if (state == XMLHandlerState.Presets) { - playerPresets.put(contentItem.getPresetID(), contentItem); - contentItem = null; - } - break; - case NowPlaying: - if (state == XMLHandlerState.MsgBody) { - updateRateEnabled(rateEnabled); - updateSkipEnabled(skipEnabled); - updateSkipPreviousEnabled(skipPreviousEnabled); - } - break; - // handle special tags.. - case BassUpdated: - // request current bass level - commandExecutor.getInformations(APIRequest.BASS); - break; - case VolumeUpdated: - commandExecutor.getInformations(APIRequest.VOLUME); - break; - case NowPlayingRateEnabled: - rateEnabled = OnOffType.ON; - break; - case NowPlayingSkipEnabled: - skipEnabled = OnOffType.ON; - break; - case NowPlayingSkipPreviousEnabled: - skipPreviousEnabled = OnOffType.ON; - break; - case Volume: - OnOffType muted = volumeMuteEnabled ? OnOffType.ON : OnOffType.OFF; - commandExecutor.setCurrentMuted(volumeMuteEnabled); - commandExecutor.postVolumeMuted(muted); - break; - case ZoneUpdated: - commandExecutor.getInformations(APIRequest.GET_ZONE); - break; - case Presets: - commandExecutor.updatePresetContainerFromPlayer(playerPresets); - playerPresets = null; - break; - case Group: - handler.handleGroupUpdated(masterDeviceId); - break; - default: - // no actions... - break; - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - logger.trace("{}: Text data during {}: '{}'", handler.getDeviceName(), state, new String(ch, start, length)); - super.characters(ch, start, length); - switch (state) { - case INIT: - case Msg: - case MsgHeader: - case MsgBody: - case Bass: - case BassUpdated: - case Updates: - case Volume: - case VolumeUpdated: - case Info: - case Preset: - case Presets: - case NowPlaying: - case NowPlayingRateEnabled: - case NowPlayingSkipEnabled: - case NowPlayingSkipPreviousEnabled: - case ContentItem: - case UnprocessedNoTextExpected: - case Zone: - case ZoneUpdated: - case Sources: - logger.debug("{}: Unexpected text data during {}: '{}'", handler.getDeviceName(), state, - new String(ch, start, length)); - break; - case BassMin: // @TODO - find out how to dynamically change "channel-type" bass configuration - case BassMax: // based on these values... - case BassDefault: - case BassTarget: - case VolumeTarget: - // this are currently unprocessed values. - break; - case BassCapabilities: - logger.debug("{}: Unexpected text data during {}: '{}'", handler.getDeviceName(), state, - new String(ch, start, length)); - break; - case Unprocessed: - // drop quietly.. - break; - case BassActual: - commandExecutor.updateBassLevelGUIState(new DecimalType(new String(ch, start, length))); - break; - case InfoName: - setConfigOption(DEVICE_INFO_NAME, new String(ch, start, length)); - break; - case InfoType: - setConfigOption(DEVICE_INFO_TYPE, new String(ch, start, length)); - setConfigOption(PROPERTY_MODEL_ID, new String(ch, start, length)); - break; - case InfoModuleType: - setConfigOption(PROPERTY_HARDWARE_VERSION, new String(ch, start, length)); - break; - case InfoFirmwareVersion: - String[] fwVersion = new String(ch, start, length).split(" "); - setConfigOption(PROPERTY_FIRMWARE_VERSION, fwVersion[0]); - break; - case BassAvailable: - boolean bassAvailable = Boolean.parseBoolean(new String(ch, start, length)); - commandExecutor.setBassAvailable(bassAvailable); - break; - case NowPlayingAlbum: - updateNowPlayingAlbum(new StringType(new String(ch, start, length))); - break; - case NowPlayingArt: - String url = new String(ch, start, length); - if (url.startsWith("http")) { - // We download the cover art in a different thread to not delay the other operations - handler.getScheduler().submit(() -> { - RawType image = HttpUtil.downloadImage(url, true, 500000); - if (image != null) { - updateNowPlayingArtwork(image); - } else { - updateNowPlayingArtwork(UnDefType.UNDEF); - } - }); - } else { - updateNowPlayingArtwork(UnDefType.UNDEF); - } - break; - case NowPlayingArtist: - updateNowPlayingArtist(new StringType(new String(ch, start, length))); - break; - case ContentItemItemName: - contentItem.setItemName(new String(ch, start, length)); - break; - case ContentItemContainerArt: - contentItem.setContainerArt(new String(ch, start, length)); - break; - case NowPlayingDescription: - updateNowPlayingDescription(new StringType(new String(ch, start, length))); - break; - case NowPlayingGenre: - updateNowPlayingGenre(new StringType(new String(ch, start, length))); - break; - case NowPlayingPlayStatus: - String playPauseState = new String(ch, start, length); - if ("PLAY_STATE".equals(playPauseState) || "BUFFERING_STATE".equals(playPauseState)) { - commandExecutor.updatePlayerControlGUIState(PlayPauseType.PLAY); - } else if ("STOP_STATE".equals(playPauseState) || "PAUSE_STATE".equals(playPauseState)) { - commandExecutor.updatePlayerControlGUIState(PlayPauseType.PAUSE); - } - break; - case NowPlayingStationLocation: - updateNowPlayingStationLocation(new StringType(new String(ch, start, length))); - break; - case NowPlayingStationName: - updateNowPlayingStationName(new StringType(new String(ch, start, length))); - break; - case NowPlayingTrack: - updateNowPlayingTrack(new StringType(new String(ch, start, length))); - break; - case VolumeActual: - commandExecutor.updateVolumeGUIState(new PercentType(Integer.parseInt(new String(ch, start, length)))); - break; - case VolumeMuteEnabled: - volumeMuteEnabled = Boolean.parseBoolean(new String(ch, start, length)); - commandExecutor.setCurrentMuted(volumeMuteEnabled); - break; - case MasterDeviceId: - if (masterDeviceId != null) { - masterDeviceId.macAddress = new String(ch, start, length); - } - break; - case GroupName: - if (masterDeviceId != null) { - masterDeviceId.groupName = new String(ch, start, length); - } - break; - case DeviceId: - deviceId = new String(ch, start, length); - break; - case DeviceIp: - if (masterDeviceId != null && Objects.equals(masterDeviceId.macAddress, deviceId)) { - masterDeviceId.host = new String(ch, start, length); - } - break; - default: - // do nothing - break; - } - } - - @Override - public void skippedEntity(String name) throws SAXException { - super.skippedEntity(name); - } - - private boolean checkDeviceId(String localName, Attributes attributes, boolean allowFromMaster) { - String deviceID = attributes.getValue("deviceID"); - if (deviceID == null) { - logger.warn("{}: No device-ID in entity {}", handler.getDeviceName(), localName); - return false; - } - if (deviceID.equals(handler.getMacAddress())) { - return true; - } - logger.warn("{}: Wrong device-ID in entity '{}': Got: '{}', expected: '{}'", handler.getDeviceName(), localName, - deviceID, handler.getMacAddress()); - return false; - } - - private void init() { - states = new Stack<>(); - state = XMLHandlerState.INIT; - nowPlayingSource = null; - } - - private XMLHandlerState nextState(Map stateMap, XMLHandlerState curState, - String localName) { - XMLHandlerState state = stateMap.get(localName); - if (state == null) { - if (logger.isDebugEnabled()) { - logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, localName); - } - state = XMLHandlerState.Unprocessed; - } - return state; - } - - private void setConfigOption(String option, String value) { - Map prop = handler.getThing().getProperties(); - String cur = prop.get(option); - if (cur == null || !cur.equals(value)) { - logger.debug("{}: Option '{}' updated: From '{}' to '{}'", handler.getDeviceName(), option, cur, value); - handler.getThing().setProperty(option, value); - } - } - - private void updateNowPlayingAlbum(State state) { - handler.updateState(CHANNEL_NOWPLAYING_ALBUM, state); - } - - private void updateNowPlayingArtwork(State state) { - handler.updateState(CHANNEL_NOWPLAYING_ARTWORK, state); - } - - private void updateNowPlayingArtist(State state) { - handler.updateState(CHANNEL_NOWPLAYING_ARTIST, state); - } - - private void updateNowPlayingDescription(State state) { - handler.updateState(CHANNEL_NOWPLAYING_DESCRIPTION, state); - } - - private void updateNowPlayingGenre(State state) { - handler.updateState(CHANNEL_NOWPLAYING_GENRE, state); - } - - private void updateNowPlayingItemName(State state) { - handler.updateState(CHANNEL_NOWPLAYING_ITEMNAME, state); - } - - private void updateNowPlayingStationLocation(State state) { - handler.updateState(CHANNEL_NOWPLAYING_STATIONLOCATION, state); - } - - private void updateNowPlayingStationName(State state) { - handler.updateState(CHANNEL_NOWPLAYING_STATIONNAME, state); - } - - private void updateNowPlayingTrack(State state) { - handler.updateState(CHANNEL_NOWPLAYING_TRACK, state); - } - - private void updateRateEnabled(OnOffType state) { - handler.updateState(CHANNEL_RATEENABLED, state); - } - - private void updateSkipEnabled(OnOffType state) { - handler.updateState(CHANNEL_SKIPENABLED, state); - } - - private void updateSkipPreviousEnabled(OnOffType state) { - handler.updateState(CHANNEL_SKIPPREVIOUSENABLED, state); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bosesoundtouch.internal; + +import static org.eclipse.smarthome.core.thing.Thing.PROPERTY_FIRMWARE_VERSION; +import static org.eclipse.smarthome.core.thing.Thing.PROPERTY_HARDWARE_VERSION; +import static org.eclipse.smarthome.core.thing.Thing.PROPERTY_MODEL_ID; +import static org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchBindingConstants.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Stack; + +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.library.types.PlayPauseType; +import org.eclipse.smarthome.core.library.types.RawType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.eclipse.smarthome.io.net.http.HttpUtil; +import org.openhab.binding.bosesoundtouch.internal.handler.BoseSoundTouchHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * The {@link XMLResponseHandler} class handles the XML communication with the Soundtouch + * + * @author Christian Niessner - Initial contribution + * @author Thomas Traunbauer - Initial contribution + * @author Kai Kreuzer - code clean up + */ +public class XMLResponseHandler extends DefaultHandler { + + private final Logger logger = LoggerFactory.getLogger(XMLResponseHandler.class); + + private BoseSoundTouchHandler handler; + private CommandExecutor commandExecutor; + + private Map> stateSwitchingMap; + + private Stack states; + private XMLHandlerState state; + private boolean msgHeaderWasValid; + + private ContentItem contentItem; + private boolean volumeMuteEnabled; + private OnOffType rateEnabled; + private OnOffType skipEnabled; + private OnOffType skipPreviousEnabled; + + private State nowPlayingSource; + + private BoseSoundTouchConfiguration masterDeviceId; + String deviceId; + + private Map playerPresets; + + /** + * Creates a new instance of this class + * + * @param handler + * @param stateSwitchingMap the stateSwitchingMap is the XMLState Map, that says which Flags are computed + */ + public XMLResponseHandler(BoseSoundTouchHandler handler, + Map> stateSwitchingMap) { + this.handler = handler; + this.commandExecutor = handler.getCommandExecutor(); + this.stateSwitchingMap = stateSwitchingMap; + init(); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + super.startElement(uri, localName, qName, attributes); + logger.trace("{}: startElement('{}'; state: {})", handler.getDeviceName(), localName, state); + states.push(state); + XMLHandlerState curState = state; // save for switch statement + Map stateMap = stateSwitchingMap.get(state); + state = XMLHandlerState.Unprocessed; // set default value; we avoid default in select to have the compiler + // showing a + // warning for unhandled states + switch (curState) { + case INIT: + if ("updates".equals(localName)) { + // it just seems to be a ping - havn't seen any data on it.. + if (checkDeviceId(localName, attributes, false)) { + state = XMLHandlerState.Updates; + } else { + state = XMLHandlerState.Unprocessed; + } + } else { + state = stateMap.get(localName); + if (state == null) { + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}", handler.getDeviceName(), curState, + localName); + } + state = XMLHandlerState.Unprocessed; + } + } + break; + case Msg: + if ("header".equals(localName)) { + // message + if (checkDeviceId(localName, attributes, false)) { + state = XMLHandlerState.MsgHeader; + msgHeaderWasValid = true; + } else { + state = XMLHandlerState.Unprocessed; + } + } else if ("body".equals(localName)) { + if (msgHeaderWasValid) { + state = XMLHandlerState.MsgBody; + } else { + state = XMLHandlerState.Unprocessed; + } + } else { + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, + localName); + } + state = XMLHandlerState.Unprocessed; + } + break; + case MsgHeader: + if ("request".equals(localName)) { + state = XMLHandlerState.Unprocessed; // TODO implement request id / response tracking... + } else { + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, + localName); + } + state = XMLHandlerState.Unprocessed; + } + break; + case MsgBody: + if ("nowPlaying".equals(localName)) { + /* + * if (!checkDeviceId(localName, attributes, true)) { + * state = XMLHandlerState.Unprocessed; + * break; + * } + */ + rateEnabled = OnOffType.OFF; + skipEnabled = OnOffType.OFF; + skipPreviousEnabled = OnOffType.OFF; + state = XMLHandlerState.NowPlaying; + String source = attributes.getValue("source"); + if (nowPlayingSource == null || !nowPlayingSource.toString().equals(source)) { + // source changed + nowPlayingSource = new StringType(source); + // reset enabled states + updateRateEnabled(OnOffType.OFF); + updateSkipEnabled(OnOffType.OFF); + updateSkipPreviousEnabled(OnOffType.OFF); + + // clear all "nowPlaying" details on source change... + updateNowPlayingAlbum(UnDefType.NULL); + updateNowPlayingArtwork(UnDefType.NULL); + updateNowPlayingArtist(UnDefType.NULL); + updateNowPlayingDescription(UnDefType.NULL); + updateNowPlayingGenre(UnDefType.NULL); + updateNowPlayingItemName(UnDefType.NULL); + updateNowPlayingStationLocation(UnDefType.NULL); + updateNowPlayingStationName(UnDefType.NULL); + updateNowPlayingTrack(UnDefType.NULL); + } + } else if ("zone".equals(localName)) { + state = XMLHandlerState.Zone; + } else if ("presets".equals(localName)) { + // reset the current playerPrests + playerPresets = new HashMap<>(); + for (int i = 1; i <= 6; i++) { + playerPresets.put(i, null); + } + state = XMLHandlerState.Presets; + } else if ("group".equals(localName)) { + this.masterDeviceId = new BoseSoundTouchConfiguration(); + state = stateMap.get(localName); + } else { + state = stateMap.get(localName); + if (state == null) { + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}", handler.getDeviceName(), curState, + localName); + } + state = XMLHandlerState.Unprocessed; + } else if (state != XMLHandlerState.Volume && state != XMLHandlerState.Presets + && state != XMLHandlerState.Group && state != XMLHandlerState.Unprocessed) { + if (!checkDeviceId(localName, attributes, false)) { + state = XMLHandlerState.Unprocessed; + break; + } + } + } + break; + case Presets: + if ("preset".equals(localName)) { + state = XMLHandlerState.Preset; + String id = attributes.getValue("id"); + if (contentItem == null) { + contentItem = new ContentItem(); + } + contentItem.setPresetID(Integer.parseInt(id)); + } else { + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, + localName); + } + state = XMLHandlerState.Unprocessed; + } + break; + case Sources: + if ("sourceItem".equals(localName)) { + state = XMLHandlerState.Unprocessed; + String source = attributes.getValue("source"); + String sourceAccount = attributes.getValue("sourceAccount"); + String status = attributes.getValue("status"); + if (status.equals("READY")) { + if (source.equals("AUX")) { + if (sourceAccount.equals("AUX")) { + commandExecutor.setAUXAvailable(true); + } + if (sourceAccount.equals("AUX1")) { + commandExecutor.setAUX1Available(true); + } + if (sourceAccount.equals("AUX2")) { + commandExecutor.setAUX2Available(true); + } + if (sourceAccount.equals("AUX3")) { + commandExecutor.setAUX3Available(true); + } + } + if (source.equals("STORED_MUSIC")) { + commandExecutor.setStoredMusicAvailable(true); + } + if (source.equals("INTERNET_RADIO")) { + commandExecutor.setInternetRadioAvailable(true); + } + if (source.equals("BLUETOOTH")) { + commandExecutor.setBluetoothAvailable(true); + } + if (source.equals("PRODUCT")) { + if (sourceAccount.equals("TV")) { + commandExecutor.setTVAvailable(true); + } + if (sourceAccount.equals("HDMI_1")) { + commandExecutor.setHDMI1Available(true); + } + } + } + } else { + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, + localName); + } + state = XMLHandlerState.Unprocessed; + } + break; + // auto go trough the state map + case Group: + case Zone: + case Bass: + case ContentItem: + case MasterDeviceId: + case GroupName: + case DeviceId: + case DeviceIp: + case Info: + case NowPlaying: + case Preset: + case Updates: + case Volume: + case Components: + case Component: + state = nextState(stateMap, curState, localName); + break; + case BassCapabilities: + state = nextState(stateMap, curState, localName); + break; + // all entities without any children expected.. + case BassTarget: + case BassActual: + case BassUpdated: + case BassMin: + case BassMax: + case BassDefault: + case ContentItemItemName: + case ContentItemContainerArt: + case InfoName: + case InfoType: + case InfoFirmwareVersion: + case InfoModuleType: + case NowPlayingAlbum: + case NowPlayingArt: + case NowPlayingArtist: + case NowPlayingGenre: + case NowPlayingDescription: + case NowPlayingPlayStatus: + case NowPlayingRateEnabled: + case NowPlayingSkipEnabled: + case NowPlayingSkipPreviousEnabled: + case NowPlayingStationLocation: + case NowPlayingStationName: + case NowPlayingTrack: + case VolumeTarget: + case VolumeActual: + case VolumeUpdated: + case VolumeMuteEnabled: + case ZoneMember: + case ZoneUpdated: // currently this dosn't provide any zone details.. + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, + localName); + } + state = XMLHandlerState.Unprocessed; + break; + case BassAvailable: + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, + localName); + } + state = XMLHandlerState.Unprocessed; + break; + case Unprocessed: + // all further things are also unprocessed + state = XMLHandlerState.Unprocessed; + break; + case UnprocessedNoTextExpected: + state = XMLHandlerState.UnprocessedNoTextExpected; + break; + } + if (state == XMLHandlerState.ContentItem) { + if (contentItem == null) { + contentItem = new ContentItem(); + } + contentItem.setSource(attributes.getValue("source")); + contentItem.setSourceAccount(attributes.getValue("sourceAccount")); + contentItem.setLocation(attributes.getValue("location")); + contentItem.setPresetable(Boolean.parseBoolean(attributes.getValue("isPresetable"))); + for (int attrId = 0; attrId < attributes.getLength(); attrId++) { + String attrName = attributes.getLocalName(attrId); + if ("source".equalsIgnoreCase(attrName)) { + continue; + } + if ("location".equalsIgnoreCase(attrName)) { + continue; + } + if ("sourceAccount".equalsIgnoreCase(attrName)) { + continue; + } + if ("isPresetable".equalsIgnoreCase(attrName)) { + continue; + } + contentItem.setAdditionalAttribute(attrName, attributes.getValue(attrId)); + } + } + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + super.endElement(uri, localName, qName); + logger.trace("{}: endElement('{}')", handler.getDeviceName(), localName); + final XMLHandlerState prevState = state; + state = states.pop(); + switch (prevState) { + case Info: + commandExecutor.getInformations(APIRequest.VOLUME); + commandExecutor.getInformations(APIRequest.PRESETS); + commandExecutor.getInformations(APIRequest.NOW_PLAYING); + commandExecutor.getInformations(APIRequest.GET_ZONE); + commandExecutor.getInformations(APIRequest.BASS); + commandExecutor.getInformations(APIRequest.SOURCES); + commandExecutor.getInformations(APIRequest.BASSCAPABILITIES); + commandExecutor.getInformations(APIRequest.GET_GROUP); + break; + case ContentItem: + if (state == XMLHandlerState.NowPlaying) { + // update now playing name... + updateNowPlayingItemName(new StringType(contentItem.getItemName())); + commandExecutor.setCurrentContentItem(contentItem); + } + break; + case Preset: + if (state == XMLHandlerState.Presets) { + playerPresets.put(contentItem.getPresetID(), contentItem); + contentItem = null; + } + break; + case NowPlaying: + if (state == XMLHandlerState.MsgBody) { + updateRateEnabled(rateEnabled); + updateSkipEnabled(skipEnabled); + updateSkipPreviousEnabled(skipPreviousEnabled); + } + break; + // handle special tags.. + case BassUpdated: + // request current bass level + commandExecutor.getInformations(APIRequest.BASS); + break; + case VolumeUpdated: + commandExecutor.getInformations(APIRequest.VOLUME); + break; + case NowPlayingRateEnabled: + rateEnabled = OnOffType.ON; + break; + case NowPlayingSkipEnabled: + skipEnabled = OnOffType.ON; + break; + case NowPlayingSkipPreviousEnabled: + skipPreviousEnabled = OnOffType.ON; + break; + case Volume: + OnOffType muted = volumeMuteEnabled ? OnOffType.ON : OnOffType.OFF; + commandExecutor.setCurrentMuted(volumeMuteEnabled); + commandExecutor.postVolumeMuted(muted); + break; + case ZoneUpdated: + commandExecutor.getInformations(APIRequest.GET_ZONE); + break; + case Presets: + commandExecutor.updatePresetContainerFromPlayer(playerPresets); + playerPresets = null; + break; + case Group: + handler.handleGroupUpdated(masterDeviceId); + break; + default: + // no actions... + break; + } + } + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + logger.trace("{}: Text data during {}: '{}'", handler.getDeviceName(), state, new String(ch, start, length)); + super.characters(ch, start, length); + switch (state) { + case INIT: + case Msg: + case MsgHeader: + case MsgBody: + case Bass: + case BassUpdated: + case Updates: + case Volume: + case VolumeUpdated: + case Info: + case Preset: + case Presets: + case NowPlaying: + case NowPlayingRateEnabled: + case NowPlayingSkipEnabled: + case NowPlayingSkipPreviousEnabled: + case ContentItem: + case UnprocessedNoTextExpected: + case Zone: + case ZoneUpdated: + case Sources: + logger.debug("{}: Unexpected text data during {}: '{}'", handler.getDeviceName(), state, + new String(ch, start, length)); + break; + case BassMin: // @TODO - find out how to dynamically change "channel-type" bass configuration + case BassMax: // based on these values... + case BassDefault: + case BassTarget: + case VolumeTarget: + // this are currently unprocessed values. + break; + case BassCapabilities: + logger.debug("{}: Unexpected text data during {}: '{}'", handler.getDeviceName(), state, + new String(ch, start, length)); + break; + case Unprocessed: + // drop quietly.. + break; + case BassActual: + commandExecutor.updateBassLevelGUIState(new DecimalType(new String(ch, start, length))); + break; + case InfoName: + setConfigOption(DEVICE_INFO_NAME, new String(ch, start, length)); + break; + case InfoType: + setConfigOption(DEVICE_INFO_TYPE, new String(ch, start, length)); + setConfigOption(PROPERTY_MODEL_ID, new String(ch, start, length)); + break; + case InfoModuleType: + setConfigOption(PROPERTY_HARDWARE_VERSION, new String(ch, start, length)); + break; + case InfoFirmwareVersion: + String[] fwVersion = new String(ch, start, length).split(" "); + setConfigOption(PROPERTY_FIRMWARE_VERSION, fwVersion[0]); + break; + case BassAvailable: + boolean bassAvailable = Boolean.parseBoolean(new String(ch, start, length)); + commandExecutor.setBassAvailable(bassAvailable); + break; + case NowPlayingAlbum: + updateNowPlayingAlbum(new StringType(new String(ch, start, length))); + break; + case NowPlayingArt: + String url = new String(ch, start, length); + if (url.startsWith("http")) { + // We download the cover art in a different thread to not delay the other operations + handler.getScheduler().submit(() -> { + RawType image = HttpUtil.downloadImage(url, true, 500000); + if (image != null) { + updateNowPlayingArtwork(image); + } else { + updateNowPlayingArtwork(UnDefType.UNDEF); + } + }); + } else { + updateNowPlayingArtwork(UnDefType.UNDEF); + } + break; + case NowPlayingArtist: + updateNowPlayingArtist(new StringType(new String(ch, start, length))); + break; + case ContentItemItemName: + contentItem.setItemName(new String(ch, start, length)); + break; + case ContentItemContainerArt: + contentItem.setContainerArt(new String(ch, start, length)); + break; + case NowPlayingDescription: + updateNowPlayingDescription(new StringType(new String(ch, start, length))); + break; + case NowPlayingGenre: + updateNowPlayingGenre(new StringType(new String(ch, start, length))); + break; + case NowPlayingPlayStatus: + String playPauseState = new String(ch, start, length); + if ("PLAY_STATE".equals(playPauseState) || "BUFFERING_STATE".equals(playPauseState)) { + commandExecutor.updatePlayerControlGUIState(PlayPauseType.PLAY); + } else if ("STOP_STATE".equals(playPauseState) || "PAUSE_STATE".equals(playPauseState)) { + commandExecutor.updatePlayerControlGUIState(PlayPauseType.PAUSE); + } + break; + case NowPlayingStationLocation: + updateNowPlayingStationLocation(new StringType(new String(ch, start, length))); + break; + case NowPlayingStationName: + updateNowPlayingStationName(new StringType(new String(ch, start, length))); + break; + case NowPlayingTrack: + updateNowPlayingTrack(new StringType(new String(ch, start, length))); + break; + case VolumeActual: + commandExecutor.updateVolumeGUIState(new PercentType(Integer.parseInt(new String(ch, start, length)))); + break; + case VolumeMuteEnabled: + volumeMuteEnabled = Boolean.parseBoolean(new String(ch, start, length)); + commandExecutor.setCurrentMuted(volumeMuteEnabled); + break; + case MasterDeviceId: + if (masterDeviceId != null) { + masterDeviceId.macAddress = new String(ch, start, length); + } + break; + case GroupName: + if (masterDeviceId != null) { + masterDeviceId.groupName = new String(ch, start, length); + } + break; + case DeviceId: + deviceId = new String(ch, start, length); + break; + case DeviceIp: + if (masterDeviceId != null && Objects.equals(masterDeviceId.macAddress, deviceId)) { + masterDeviceId.host = new String(ch, start, length); + } + break; + default: + // do nothing + break; + } + } + + @Override + public void skippedEntity(String name) throws SAXException { + super.skippedEntity(name); + } + + private boolean checkDeviceId(String localName, Attributes attributes, boolean allowFromMaster) { + String deviceID = attributes.getValue("deviceID"); + if (deviceID == null) { + logger.warn("{}: No device-ID in entity {}", handler.getDeviceName(), localName); + return false; + } + if (deviceID.equals(handler.getMacAddress())) { + return true; + } + logger.warn("{}: Wrong device-ID in entity '{}': Got: '{}', expected: '{}'", handler.getDeviceName(), localName, + deviceID, handler.getMacAddress()); + return false; + } + + private void init() { + states = new Stack<>(); + state = XMLHandlerState.INIT; + nowPlayingSource = null; + } + + private XMLHandlerState nextState(Map stateMap, XMLHandlerState curState, + String localName) { + XMLHandlerState state = stateMap.get(localName); + if (state == null) { + if (logger.isDebugEnabled()) { + logger.warn("{}: Unhandled XML entity during {}: '{}'", handler.getDeviceName(), curState, localName); + } + state = XMLHandlerState.Unprocessed; + } + return state; + } + + private void setConfigOption(String option, String value) { + Map prop = handler.getThing().getProperties(); + String cur = prop.get(option); + if (cur == null || !cur.equals(value)) { + logger.debug("{}: Option '{}' updated: From '{}' to '{}'", handler.getDeviceName(), option, cur, value); + handler.getThing().setProperty(option, value); + } + } + + private void updateNowPlayingAlbum(State state) { + handler.updateState(CHANNEL_NOWPLAYING_ALBUM, state); + } + + private void updateNowPlayingArtwork(State state) { + handler.updateState(CHANNEL_NOWPLAYING_ARTWORK, state); + } + + private void updateNowPlayingArtist(State state) { + handler.updateState(CHANNEL_NOWPLAYING_ARTIST, state); + } + + private void updateNowPlayingDescription(State state) { + handler.updateState(CHANNEL_NOWPLAYING_DESCRIPTION, state); + } + + private void updateNowPlayingGenre(State state) { + handler.updateState(CHANNEL_NOWPLAYING_GENRE, state); + } + + private void updateNowPlayingItemName(State state) { + handler.updateState(CHANNEL_NOWPLAYING_ITEMNAME, state); + } + + private void updateNowPlayingStationLocation(State state) { + handler.updateState(CHANNEL_NOWPLAYING_STATIONLOCATION, state); + } + + private void updateNowPlayingStationName(State state) { + handler.updateState(CHANNEL_NOWPLAYING_STATIONNAME, state); + } + + private void updateNowPlayingTrack(State state) { + handler.updateState(CHANNEL_NOWPLAYING_TRACK, state); + } + + private void updateRateEnabled(OnOffType state) { + handler.updateState(CHANNEL_RATEENABLED, state); + } + + private void updateSkipEnabled(OnOffType state) { + handler.updateState(CHANNEL_SKIPENABLED, state); + } + + private void updateSkipPreviousEnabled(OnOffType state) { + handler.updateState(CHANNEL_SKIPPREVIOUSENABLED, state); + } +} diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/XMLResponseProcessor.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/XMLResponseProcessor.java index f4ee3762ec72d..6ab91903f6a9a 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/XMLResponseProcessor.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/XMLResponseProcessor.java @@ -1,173 +1,173 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bosesoundtouch.internal; - -import java.io.IOException; -import java.io.StringReader; -import java.util.HashMap; -import java.util.Map; - -import org.openhab.binding.bosesoundtouch.internal.handler.BoseSoundTouchHandler; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; -import org.xml.sax.helpers.XMLReaderFactory; - -/** - * The {@link XMLResponseProcessor} class handles the XML mapping - * - * @author Christian Niessner - Initial contribution - * @author Thomas Traunbauer - Initial contribution - */ -public class XMLResponseProcessor { - private BoseSoundTouchHandler handler; - - private Map> stateSwitchingMap; - - public XMLResponseProcessor(BoseSoundTouchHandler handler) { - this.handler = handler; - init(); - } - - public void handleMessage(String msg) throws SAXException, IOException { - XMLReader reader = XMLReaderFactory.createXMLReader(); - reader.setContentHandler(new XMLResponseHandler(handler, stateSwitchingMap)); - reader.parse(new InputSource(new StringReader(msg))); - } - - // initializes our XML parsing state machine - private void init() { - stateSwitchingMap = new HashMap<>(); - - Map msgInitMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.INIT, msgInitMap); - msgInitMap.put("msg", XMLHandlerState.Msg); - msgInitMap.put("SoundTouchSdkInfo", XMLHandlerState.Unprocessed); - msgInitMap.put("userActivityUpdate", XMLHandlerState.Unprocessed); // ignored.. - - Map msgBodyMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.MsgBody, msgBodyMap); - msgBodyMap.put("info", XMLHandlerState.Info); - msgBodyMap.put("volume", XMLHandlerState.Volume); - msgBodyMap.put("presets", XMLHandlerState.Presets); - msgBodyMap.put("key", XMLHandlerState.Unprocessed); // only confirmation of our key presses... - msgBodyMap.put("status", XMLHandlerState.Unprocessed); // only confirmation of commands sent to device... - msgBodyMap.put("zone", XMLHandlerState.Zone); // only confirmation of our key presses... - msgBodyMap.put("bass", XMLHandlerState.Bass); - msgBodyMap.put("sources", XMLHandlerState.Sources); - msgBodyMap.put("bassCapabilities", XMLHandlerState.BassCapabilities); - msgBodyMap.put("group", XMLHandlerState.Group); - - // info message states - Map infoMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.Info, infoMap); - infoMap.put("components", XMLHandlerState.Info); - infoMap.put("component", XMLHandlerState.Info); - infoMap.put("name", XMLHandlerState.InfoName); - infoMap.put("type", XMLHandlerState.InfoType); - infoMap.put("componentCategory", XMLHandlerState.Unprocessed); - infoMap.put("softwareVersion", XMLHandlerState.InfoFirmwareVersion); - infoMap.put("serialNumber", XMLHandlerState.Unprocessed); - infoMap.put("networkInfo", XMLHandlerState.Unprocessed); - infoMap.put("margeAccountUUID", XMLHandlerState.Unprocessed); - infoMap.put("margeURL", XMLHandlerState.Unprocessed); - infoMap.put("moduleType", XMLHandlerState.InfoModuleType); - infoMap.put("variant", XMLHandlerState.Unprocessed); - infoMap.put("variantMode", XMLHandlerState.Unprocessed); - infoMap.put("countryCode", XMLHandlerState.Unprocessed); - infoMap.put("regionCode", XMLHandlerState.Unprocessed); - - Map updatesMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.Updates, updatesMap); - updatesMap.put("clockDisplayUpdated", XMLHandlerState.Unprocessed); // can we get anything useful of that? - updatesMap.put("connectionStateUpdated", XMLHandlerState.UnprocessedNoTextExpected); - updatesMap.put("infoUpdated", XMLHandlerState.Unprocessed); - updatesMap.put("nowPlayingUpdated", XMLHandlerState.MsgBody); - updatesMap.put("nowSelectionUpdated", XMLHandlerState.Unprocessed); // TODO this seems to be quite a useful info - // what is currently played.. - updatesMap.put("recentsUpdated", XMLHandlerState.Unprocessed); - updatesMap.put("volumeUpdated", XMLHandlerState.MsgBody); - updatesMap.put("zoneUpdated", XMLHandlerState.ZoneUpdated); // just notifies but dosn't provide details - updatesMap.put("bassUpdated", XMLHandlerState.BassUpdated); - updatesMap.put("presetsUpdated", XMLHandlerState.MsgBody); - updatesMap.put("groupUpdated", XMLHandlerState.MsgBody); - - Map volume = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.Volume, volume); - volume.put("targetvolume", XMLHandlerState.VolumeTarget); - volume.put("actualvolume", XMLHandlerState.VolumeActual); - volume.put("muteenabled", XMLHandlerState.VolumeMuteEnabled); - - Map nowPlayingMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.NowPlaying, nowPlayingMap); - nowPlayingMap.put("album", XMLHandlerState.NowPlayingAlbum); - nowPlayingMap.put("art", XMLHandlerState.NowPlayingArt); - nowPlayingMap.put("artist", XMLHandlerState.NowPlayingArtist); - nowPlayingMap.put("ContentItem", XMLHandlerState.ContentItem); - nowPlayingMap.put("description", XMLHandlerState.NowPlayingDescription); - nowPlayingMap.put("playStatus", XMLHandlerState.NowPlayingPlayStatus); - nowPlayingMap.put("rateEnabled", XMLHandlerState.NowPlayingRateEnabled); - nowPlayingMap.put("skipEnabled", XMLHandlerState.NowPlayingSkipEnabled); - nowPlayingMap.put("skipPreviousEnabled", XMLHandlerState.NowPlayingSkipPreviousEnabled); - nowPlayingMap.put("stationLocation", XMLHandlerState.NowPlayingStationLocation); - nowPlayingMap.put("stationName", XMLHandlerState.NowPlayingStationName); - nowPlayingMap.put("track", XMLHandlerState.NowPlayingTrack); - nowPlayingMap.put("connectionStatusInfo", XMLHandlerState.Unprocessed); // TODO active when Source==Bluetooth - // TODO active when Source==Pandora and maybe also other sources - seems to be rating related - nowPlayingMap.put("time", XMLHandlerState.Unprocessed); - nowPlayingMap.put("rating", XMLHandlerState.Unprocessed); - nowPlayingMap.put("rateEnabled", XMLHandlerState.Unprocessed); - - // ContentItem specifies a resource (that also could be bookmarked in a preset) - Map contentItemMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.ContentItem, contentItemMap); - contentItemMap.put("itemName", XMLHandlerState.ContentItemItemName); - contentItemMap.put("containerArt", XMLHandlerState.ContentItemContainerArt); - - Map presetMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.Preset, presetMap); - presetMap.put("ContentItem", XMLHandlerState.ContentItem); - - Map zoneMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.Zone, zoneMap); - zoneMap.put("member", XMLHandlerState.ZoneMember); - - Map bassMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.Bass, bassMap); - bassMap.put("targetbass", XMLHandlerState.BassTarget); - bassMap.put("actualbass", XMLHandlerState.BassActual); - - Map sourceMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.Sources, sourceMap); - - Map bassCapabilitiesMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.BassCapabilities, bassCapabilitiesMap); - bassCapabilitiesMap.put("bassAvailable", XMLHandlerState.BassAvailable); - bassCapabilitiesMap.put("bassMin", XMLHandlerState.BassMin); - bassCapabilitiesMap.put("bassMax", XMLHandlerState.BassMax); - bassCapabilitiesMap.put("bassDefault", XMLHandlerState.BassDefault); - - Map groupsMap = new HashMap<>(); - stateSwitchingMap.put(XMLHandlerState.Group, groupsMap); - groupsMap.put("name", XMLHandlerState.GroupName); - groupsMap.put("masterDeviceId", XMLHandlerState.MasterDeviceId); - groupsMap.put("roles", XMLHandlerState.Unprocessed); - groupsMap.put("senderIPAddress", XMLHandlerState.Unprocessed); - groupsMap.put("status", XMLHandlerState.Unprocessed); - groupsMap.put("roles", XMLHandlerState.Unprocessed); - groupsMap.put("groupRole", XMLHandlerState.Unprocessed); - groupsMap.put("deviceId", XMLHandlerState.DeviceId); - groupsMap.put("role", XMLHandlerState.Unprocessed); - groupsMap.put("ipAddress", XMLHandlerState.DeviceIp); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bosesoundtouch.internal; + +import java.io.IOException; +import java.io.StringReader; +import java.util.HashMap; +import java.util.Map; + +import org.openhab.binding.bosesoundtouch.internal.handler.BoseSoundTouchHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * The {@link XMLResponseProcessor} class handles the XML mapping + * + * @author Christian Niessner - Initial contribution + * @author Thomas Traunbauer - Initial contribution + */ +public class XMLResponseProcessor { + private BoseSoundTouchHandler handler; + + private Map> stateSwitchingMap; + + public XMLResponseProcessor(BoseSoundTouchHandler handler) { + this.handler = handler; + init(); + } + + public void handleMessage(String msg) throws SAXException, IOException { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setContentHandler(new XMLResponseHandler(handler, stateSwitchingMap)); + reader.parse(new InputSource(new StringReader(msg))); + } + + // initializes our XML parsing state machine + private void init() { + stateSwitchingMap = new HashMap<>(); + + Map msgInitMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.INIT, msgInitMap); + msgInitMap.put("msg", XMLHandlerState.Msg); + msgInitMap.put("SoundTouchSdkInfo", XMLHandlerState.Unprocessed); + msgInitMap.put("userActivityUpdate", XMLHandlerState.Unprocessed); // ignored.. + + Map msgBodyMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.MsgBody, msgBodyMap); + msgBodyMap.put("info", XMLHandlerState.Info); + msgBodyMap.put("volume", XMLHandlerState.Volume); + msgBodyMap.put("presets", XMLHandlerState.Presets); + msgBodyMap.put("key", XMLHandlerState.Unprocessed); // only confirmation of our key presses... + msgBodyMap.put("status", XMLHandlerState.Unprocessed); // only confirmation of commands sent to device... + msgBodyMap.put("zone", XMLHandlerState.Zone); // only confirmation of our key presses... + msgBodyMap.put("bass", XMLHandlerState.Bass); + msgBodyMap.put("sources", XMLHandlerState.Sources); + msgBodyMap.put("bassCapabilities", XMLHandlerState.BassCapabilities); + msgBodyMap.put("group", XMLHandlerState.Group); + + // info message states + Map infoMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.Info, infoMap); + infoMap.put("components", XMLHandlerState.Info); + infoMap.put("component", XMLHandlerState.Info); + infoMap.put("name", XMLHandlerState.InfoName); + infoMap.put("type", XMLHandlerState.InfoType); + infoMap.put("componentCategory", XMLHandlerState.Unprocessed); + infoMap.put("softwareVersion", XMLHandlerState.InfoFirmwareVersion); + infoMap.put("serialNumber", XMLHandlerState.Unprocessed); + infoMap.put("networkInfo", XMLHandlerState.Unprocessed); + infoMap.put("margeAccountUUID", XMLHandlerState.Unprocessed); + infoMap.put("margeURL", XMLHandlerState.Unprocessed); + infoMap.put("moduleType", XMLHandlerState.InfoModuleType); + infoMap.put("variant", XMLHandlerState.Unprocessed); + infoMap.put("variantMode", XMLHandlerState.Unprocessed); + infoMap.put("countryCode", XMLHandlerState.Unprocessed); + infoMap.put("regionCode", XMLHandlerState.Unprocessed); + + Map updatesMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.Updates, updatesMap); + updatesMap.put("clockDisplayUpdated", XMLHandlerState.Unprocessed); // can we get anything useful of that? + updatesMap.put("connectionStateUpdated", XMLHandlerState.UnprocessedNoTextExpected); + updatesMap.put("infoUpdated", XMLHandlerState.Unprocessed); + updatesMap.put("nowPlayingUpdated", XMLHandlerState.MsgBody); + updatesMap.put("nowSelectionUpdated", XMLHandlerState.Unprocessed); // TODO this seems to be quite a useful info + // what is currently played.. + updatesMap.put("recentsUpdated", XMLHandlerState.Unprocessed); + updatesMap.put("volumeUpdated", XMLHandlerState.MsgBody); + updatesMap.put("zoneUpdated", XMLHandlerState.ZoneUpdated); // just notifies but dosn't provide details + updatesMap.put("bassUpdated", XMLHandlerState.BassUpdated); + updatesMap.put("presetsUpdated", XMLHandlerState.MsgBody); + updatesMap.put("groupUpdated", XMLHandlerState.MsgBody); + + Map volume = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.Volume, volume); + volume.put("targetvolume", XMLHandlerState.VolumeTarget); + volume.put("actualvolume", XMLHandlerState.VolumeActual); + volume.put("muteenabled", XMLHandlerState.VolumeMuteEnabled); + + Map nowPlayingMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.NowPlaying, nowPlayingMap); + nowPlayingMap.put("album", XMLHandlerState.NowPlayingAlbum); + nowPlayingMap.put("art", XMLHandlerState.NowPlayingArt); + nowPlayingMap.put("artist", XMLHandlerState.NowPlayingArtist); + nowPlayingMap.put("ContentItem", XMLHandlerState.ContentItem); + nowPlayingMap.put("description", XMLHandlerState.NowPlayingDescription); + nowPlayingMap.put("playStatus", XMLHandlerState.NowPlayingPlayStatus); + nowPlayingMap.put("rateEnabled", XMLHandlerState.NowPlayingRateEnabled); + nowPlayingMap.put("skipEnabled", XMLHandlerState.NowPlayingSkipEnabled); + nowPlayingMap.put("skipPreviousEnabled", XMLHandlerState.NowPlayingSkipPreviousEnabled); + nowPlayingMap.put("stationLocation", XMLHandlerState.NowPlayingStationLocation); + nowPlayingMap.put("stationName", XMLHandlerState.NowPlayingStationName); + nowPlayingMap.put("track", XMLHandlerState.NowPlayingTrack); + nowPlayingMap.put("connectionStatusInfo", XMLHandlerState.Unprocessed); // TODO active when Source==Bluetooth + // TODO active when Source==Pandora and maybe also other sources - seems to be rating related + nowPlayingMap.put("time", XMLHandlerState.Unprocessed); + nowPlayingMap.put("rating", XMLHandlerState.Unprocessed); + nowPlayingMap.put("rateEnabled", XMLHandlerState.Unprocessed); + + // ContentItem specifies a resource (that also could be bookmarked in a preset) + Map contentItemMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.ContentItem, contentItemMap); + contentItemMap.put("itemName", XMLHandlerState.ContentItemItemName); + contentItemMap.put("containerArt", XMLHandlerState.ContentItemContainerArt); + + Map presetMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.Preset, presetMap); + presetMap.put("ContentItem", XMLHandlerState.ContentItem); + + Map zoneMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.Zone, zoneMap); + zoneMap.put("member", XMLHandlerState.ZoneMember); + + Map bassMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.Bass, bassMap); + bassMap.put("targetbass", XMLHandlerState.BassTarget); + bassMap.put("actualbass", XMLHandlerState.BassActual); + + Map sourceMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.Sources, sourceMap); + + Map bassCapabilitiesMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.BassCapabilities, bassCapabilitiesMap); + bassCapabilitiesMap.put("bassAvailable", XMLHandlerState.BassAvailable); + bassCapabilitiesMap.put("bassMin", XMLHandlerState.BassMin); + bassCapabilitiesMap.put("bassMax", XMLHandlerState.BassMax); + bassCapabilitiesMap.put("bassDefault", XMLHandlerState.BassDefault); + + Map groupsMap = new HashMap<>(); + stateSwitchingMap.put(XMLHandlerState.Group, groupsMap); + groupsMap.put("name", XMLHandlerState.GroupName); + groupsMap.put("masterDeviceId", XMLHandlerState.MasterDeviceId); + groupsMap.put("roles", XMLHandlerState.Unprocessed); + groupsMap.put("senderIPAddress", XMLHandlerState.Unprocessed); + groupsMap.put("status", XMLHandlerState.Unprocessed); + groupsMap.put("roles", XMLHandlerState.Unprocessed); + groupsMap.put("groupRole", XMLHandlerState.Unprocessed); + groupsMap.put("deviceId", XMLHandlerState.DeviceId); + groupsMap.put("role", XMLHandlerState.Unprocessed); + groupsMap.put("ipAddress", XMLHandlerState.DeviceIp); + } +} diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/discovery/SoundTouchDiscoveryParticipant.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/discovery/SoundTouchDiscoveryParticipant.java index ce68b7d380435..8729dd85a3476 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/discovery/SoundTouchDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/discovery/SoundTouchDiscoveryParticipant.java @@ -1,213 +1,213 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bosesoundtouch.internal.discovery; - -import static org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchBindingConstants.*; - -import java.io.IOException; -import java.math.BigInteger; -import java.net.InetAddress; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import javax.jmdns.ServiceInfo; - -import org.eclipse.smarthome.config.discovery.DiscoveryResult; -import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; -import org.eclipse.smarthome.config.discovery.mdns.MDNSDiscoveryParticipant; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchConfiguration; -import org.osgi.service.component.annotations.Component; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link SoundTouchDiscoveryParticipant} is responsible processing the - * results of searches for mDNS services of type _soundtouch._tcp.local. - * - * @author Christian Niessner - Initial contribution - * @author Thomas Traunbauer - Initial contribution - */ -@Component(immediate = true, configurationPid = "discovery.bosesoundtouch") -public class SoundTouchDiscoveryParticipant implements MDNSDiscoveryParticipant { - - private final Logger logger = LoggerFactory.getLogger(SoundTouchDiscoveryParticipant.class); - - @Override - public Set getSupportedThingTypeUIDs() { - return SUPPORTED_THING_TYPES_UIDS; - } - - @Override - public DiscoveryResult createResult(ServiceInfo info) { - DiscoveryResult result = null; - ThingUID uid = getThingUID(info); - if (uid != null) { - // remove the domain from the name - InetAddress[] addrs = info.getInetAddresses(); - - Map properties = new HashMap<>(2); - - String label = null; - if (BST_10_THING_TYPE_UID.equals(getThingTypeUID(info))) { - try { - String group = DiscoveryUtil.executeUrl("http://" + addrs[0].getHostAddress() + ":8090/getGroup"); - label = DiscoveryUtil.getContentOfFirstElement(group, "name"); - } catch (IOException e) { - logger.debug("Can't obtain label for group. Will use the default one"); - } - } - - if (label == null || label.isEmpty()) { - label = info.getName(); - } - - if (label == null || label.isEmpty()) { - label = "Bose SoundTouch"; - } - - // we expect only one address per device.. - if (addrs.length > 1) { - logger.warn("Bose SoundTouch device {} ({}) reports multiple addresses - using the first one: {}", - info.getName(), label, Arrays.toString(addrs)); - } - - properties.put(BoseSoundTouchConfiguration.HOST, addrs[0].getHostAddress()); - if (getMacAddress(info) != null) { - properties.put(BoseSoundTouchConfiguration.MAC_ADDRESS, - new String(getMacAddress(info), StandardCharsets.UTF_8)); - } - - // Set manufacturer as thing property (if available) - byte[] manufacturer = info.getPropertyBytes("MANUFACTURER"); - if (manufacturer != null) { - properties.put(Thing.PROPERTY_VENDOR, new String(manufacturer, StandardCharsets.UTF_8)); - } - return DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(label).withTTL(600).build(); - } - return result; - } - - @Override - public ThingUID getThingUID(ServiceInfo info) { - logger.trace("ServiceInfo: {}", info); - ThingTypeUID typeUID = getThingTypeUID(info); - if (typeUID != null) { - if (info.getType() != null) { - if (info.getType().equals(getServiceType())) { - logger.trace("Discovered a Bose SoundTouch thing with name '{}'", info.getName()); - byte[] mac = getMacAddress(info); - if (mac != null) { - return new ThingUID(typeUID, new String(mac, StandardCharsets.UTF_8)); - } else { - return null; - } - } - } - } - return null; - } - - @Override - public String getServiceType() { - return "_soundtouch._tcp.local."; - } - - private ThingTypeUID getThingTypeUID(ServiceInfo info) { - InetAddress[] addrs = info.getInetAddresses(); - if (addrs.length > 0) { - String ip = addrs[0].getHostAddress(); - String deviceId = null; - byte[] mac = getMacAddress(info); - if (mac != null) { - deviceId = new String(mac, StandardCharsets.UTF_8); - } - String deviceType; - try { - String content = DiscoveryUtil.executeUrl("http://" + ip + ":8090/info"); - deviceType = DiscoveryUtil.getContentOfFirstElement(content, "type"); - } catch (IOException e) { - return null; - } - - if (deviceType.toLowerCase().contains("soundtouch 10")) { - // Check if it's a Stereo Pair - try { - String group = DiscoveryUtil.executeUrl("http://" + ip + ":8090/getGroup"); - String masterDevice = DiscoveryUtil.getContentOfFirstElement(group, "masterDeviceId"); - - if (Objects.equals(deviceId, masterDevice)) { - // Stereo Pair - Master Device - return BST_10_THING_TYPE_UID; - } else if (!masterDevice.isEmpty()) { - // Stereo Pair - Secondary Device - should not be paired - return null; - } else { - // Single player - return BST_10_THING_TYPE_UID; - } - } catch (IOException e) { - return null; - } - } - if (deviceType.toLowerCase().contains("soundtouch 20")) { - return BST_20_THING_TYPE_UID; - } - if (deviceType.toLowerCase().contains("soundtouch 300")) { - return BST_300_THING_TYPE_UID; - } - if (deviceType.toLowerCase().contains("soundtouch 30")) { - return BST_30_THING_TYPE_UID; - } - if (deviceType.toLowerCase().contains("soundtouch wireless link adapter")) { - return BST_WLA_THING_TYPE_UID; - } - if (deviceType.toLowerCase().contains("wave")) { - return BST_WSMS_THING_TYPE_UID; - } - if (deviceType.toLowerCase().contains("amplifier")) { - return BST_SA5A_THING_TYPE_UID; - } - return null; - } - return null; - } - - private byte[] getMacAddress(ServiceInfo info) { - if (info != null) { - // sometimes we see empty messages - ignore them - if (!info.hasData()) { - return null; - } - byte[] mac = info.getPropertyBytes("MAC"); - if (mac == null) { - logger.warn("SoundTouch Device {} delivered no MAC address!", info.getName()); - return null; - } - if (mac.length != 12) { - BigInteger bi = new BigInteger(1, mac); - logger.warn("SoundTouch Device {} delivered an invalid MAC address: 0x{}", info.getName(), - String.format("%0" + (mac.length << 1) + "X", bi)); - return null; - } - return mac; - } - return null; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bosesoundtouch.internal.discovery; + +import static org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchBindingConstants.*; + +import java.io.IOException; +import java.math.BigInteger; +import java.net.InetAddress; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import javax.jmdns.ServiceInfo; + +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.config.discovery.mdns.MDNSDiscoveryParticipant; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchConfiguration; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link SoundTouchDiscoveryParticipant} is responsible processing the + * results of searches for mDNS services of type _soundtouch._tcp.local. + * + * @author Christian Niessner - Initial contribution + * @author Thomas Traunbauer - Initial contribution + */ +@Component(immediate = true, configurationPid = "discovery.bosesoundtouch") +public class SoundTouchDiscoveryParticipant implements MDNSDiscoveryParticipant { + + private final Logger logger = LoggerFactory.getLogger(SoundTouchDiscoveryParticipant.class); + + @Override + public Set getSupportedThingTypeUIDs() { + return SUPPORTED_THING_TYPES_UIDS; + } + + @Override + public DiscoveryResult createResult(ServiceInfo info) { + DiscoveryResult result = null; + ThingUID uid = getThingUID(info); + if (uid != null) { + // remove the domain from the name + InetAddress[] addrs = info.getInetAddresses(); + + Map properties = new HashMap<>(2); + + String label = null; + if (BST_10_THING_TYPE_UID.equals(getThingTypeUID(info))) { + try { + String group = DiscoveryUtil.executeUrl("http://" + addrs[0].getHostAddress() + ":8090/getGroup"); + label = DiscoveryUtil.getContentOfFirstElement(group, "name"); + } catch (IOException e) { + logger.debug("Can't obtain label for group. Will use the default one"); + } + } + + if (label == null || label.isEmpty()) { + label = info.getName(); + } + + if (label == null || label.isEmpty()) { + label = "Bose SoundTouch"; + } + + // we expect only one address per device.. + if (addrs.length > 1) { + logger.warn("Bose SoundTouch device {} ({}) reports multiple addresses - using the first one: {}", + info.getName(), label, Arrays.toString(addrs)); + } + + properties.put(BoseSoundTouchConfiguration.HOST, addrs[0].getHostAddress()); + if (getMacAddress(info) != null) { + properties.put(BoseSoundTouchConfiguration.MAC_ADDRESS, + new String(getMacAddress(info), StandardCharsets.UTF_8)); + } + + // Set manufacturer as thing property (if available) + byte[] manufacturer = info.getPropertyBytes("MANUFACTURER"); + if (manufacturer != null) { + properties.put(Thing.PROPERTY_VENDOR, new String(manufacturer, StandardCharsets.UTF_8)); + } + return DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(label).withTTL(600).build(); + } + return result; + } + + @Override + public ThingUID getThingUID(ServiceInfo info) { + logger.trace("ServiceInfo: {}", info); + ThingTypeUID typeUID = getThingTypeUID(info); + if (typeUID != null) { + if (info.getType() != null) { + if (info.getType().equals(getServiceType())) { + logger.trace("Discovered a Bose SoundTouch thing with name '{}'", info.getName()); + byte[] mac = getMacAddress(info); + if (mac != null) { + return new ThingUID(typeUID, new String(mac, StandardCharsets.UTF_8)); + } else { + return null; + } + } + } + } + return null; + } + + @Override + public String getServiceType() { + return "_soundtouch._tcp.local."; + } + + private ThingTypeUID getThingTypeUID(ServiceInfo info) { + InetAddress[] addrs = info.getInetAddresses(); + if (addrs.length > 0) { + String ip = addrs[0].getHostAddress(); + String deviceId = null; + byte[] mac = getMacAddress(info); + if (mac != null) { + deviceId = new String(mac, StandardCharsets.UTF_8); + } + String deviceType; + try { + String content = DiscoveryUtil.executeUrl("http://" + ip + ":8090/info"); + deviceType = DiscoveryUtil.getContentOfFirstElement(content, "type"); + } catch (IOException e) { + return null; + } + + if (deviceType.toLowerCase().contains("soundtouch 10")) { + // Check if it's a Stereo Pair + try { + String group = DiscoveryUtil.executeUrl("http://" + ip + ":8090/getGroup"); + String masterDevice = DiscoveryUtil.getContentOfFirstElement(group, "masterDeviceId"); + + if (Objects.equals(deviceId, masterDevice)) { + // Stereo Pair - Master Device + return BST_10_THING_TYPE_UID; + } else if (!masterDevice.isEmpty()) { + // Stereo Pair - Secondary Device - should not be paired + return null; + } else { + // Single player + return BST_10_THING_TYPE_UID; + } + } catch (IOException e) { + return null; + } + } + if (deviceType.toLowerCase().contains("soundtouch 20")) { + return BST_20_THING_TYPE_UID; + } + if (deviceType.toLowerCase().contains("soundtouch 300")) { + return BST_300_THING_TYPE_UID; + } + if (deviceType.toLowerCase().contains("soundtouch 30")) { + return BST_30_THING_TYPE_UID; + } + if (deviceType.toLowerCase().contains("soundtouch wireless link adapter")) { + return BST_WLA_THING_TYPE_UID; + } + if (deviceType.toLowerCase().contains("wave")) { + return BST_WSMS_THING_TYPE_UID; + } + if (deviceType.toLowerCase().contains("amplifier")) { + return BST_SA5A_THING_TYPE_UID; + } + return null; + } + return null; + } + + private byte[] getMacAddress(ServiceInfo info) { + if (info != null) { + // sometimes we see empty messages - ignore them + if (!info.hasData()) { + return null; + } + byte[] mac = info.getPropertyBytes("MAC"); + if (mac == null) { + logger.warn("SoundTouch Device {} delivered no MAC address!", info.getName()); + return null; + } + if (mac.length != 12) { + BigInteger bi = new BigInteger(1, mac); + logger.warn("SoundTouch Device {} delivered an invalid MAC address: 0x{}", info.getName(), + String.format("%0" + (mac.length << 1) + "X", bi)); + return null; + } + return mac; + } + return null; + } +} diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/handler/BoseSoundTouchHandler.java b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/handler/BoseSoundTouchHandler.java index 819dc224198ba..49fc0a5029043 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/handler/BoseSoundTouchHandler.java +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/java/org/openhab/binding/bosesoundtouch/internal/handler/BoseSoundTouchHandler.java @@ -1,564 +1,563 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bosesoundtouch.internal.handler; - -import static org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchBindingConstants.*; - -import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.StatusCode; -import org.eclipse.jetty.websocket.api.WebSocketFrameListener; -import org.eclipse.jetty.websocket.api.WebSocketListener; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.api.extensions.Frame.Type; -import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; -import org.eclipse.jetty.websocket.client.WebSocketClient; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.NextPreviousType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.library.types.PlayPauseType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.Channel; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandlerCallback; -import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.StateOption; -import org.openhab.binding.bosesoundtouch.internal.APIRequest; -import org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchConfiguration; -import org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchNotificationChannelConfiguration; -import org.openhab.binding.bosesoundtouch.internal.BoseStateDescriptionOptionProvider; -import org.openhab.binding.bosesoundtouch.internal.CommandExecutor; -import org.openhab.binding.bosesoundtouch.internal.OperationModeType; -import org.openhab.binding.bosesoundtouch.internal.PresetContainer; -import org.openhab.binding.bosesoundtouch.internal.RemoteKeyType; -import org.openhab.binding.bosesoundtouch.internal.XMLResponseProcessor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link BoseSoundTouchHandler} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Christian Niessner - Initial contribution - * @author Thomas Traunbauer - Initial contribution - * @author Kai Kreuzer - code clean up - * @author Alexander Kostadinov - Handling of websocket ping-pong mechanism for thing status check - */ -public class BoseSoundTouchHandler extends BaseThingHandler implements WebSocketListener, WebSocketFrameListener { - - private static final int MAX_MISSED_PONGS_COUNT = 2; - - private static final int RETRY_INTERVAL_IN_SECS = 30; - - private final Logger logger = LoggerFactory.getLogger(BoseSoundTouchHandler.class); - - private ScheduledFuture connectionChecker; - private WebSocketClient client; - private volatile Session session; - private volatile CommandExecutor commandExecutor; - private volatile int missedPongsCount = 0; - - private XMLResponseProcessor xmlResponseProcessor; - - private PresetContainer presetContainer; - private BoseStateDescriptionOptionProvider stateOptionProvider; - - /** - * Creates a new instance of this class for the {@link Thing}. - * - * @param thing the thing that should be handled, not null - * @param presetContainer the preset container instance to use for managing presets - * - * @throws IllegalArgumentException if thing or factory argument is null - */ - public BoseSoundTouchHandler(Thing thing, PresetContainer presetContainer, - BoseStateDescriptionOptionProvider stateOptionProvider) { - super(thing); - this.presetContainer = presetContainer; - this.stateOptionProvider = stateOptionProvider; - xmlResponseProcessor = new XMLResponseProcessor(this); - } - - @Override - public void initialize() { - connectionChecker = scheduler.scheduleWithFixedDelay(() -> checkConnection(), 0, RETRY_INTERVAL_IN_SECS, - TimeUnit.SECONDS); - } - - @Override - public void dispose() { - if (connectionChecker != null && !connectionChecker.isCancelled()) { - connectionChecker.cancel(true); - connectionChecker = null; - } - closeConnection(); - super.dispose(); - } - - @Override - public void handleRemoval() { - presetContainer.clear(); - super.handleRemoval(); - } - - @Override - public void updateState(String channelID, State state) { - // don't update channel if it's not linked (in case of Stereo Pair slave device) - if (isLinked(channelID)) { - super.updateState(channelID, state); - } else { - logger.debug("{}: Skipping state update because of not linked channel '{}'", getDeviceName(), channelID); - } - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - if (commandExecutor == null) { - logger.debug("{}: Can't handle command '{}' for channel '{}' because of not initialized connection.", - getDeviceName(), command, channelUID); - return; - } else { - logger.debug("{}: handleCommand({}, {});", getDeviceName(), channelUID, command); - } - - if (command.equals(RefreshType.REFRESH)) { - switch (channelUID.getIdWithoutGroup()) { - case CHANNEL_BASS: - commandExecutor.getInformations(APIRequest.BASS); - break; - case CHANNEL_KEY_CODE: - // refresh makes no sense... ? - break; - case CHANNEL_NOWPLAYING_ALBUM: - case CHANNEL_NOWPLAYING_ARTIST: - case CHANNEL_NOWPLAYING_ARTWORK: - case CHANNEL_NOWPLAYING_DESCRIPTION: - case CHANNEL_NOWPLAYING_GENRE: - case CHANNEL_NOWPLAYING_ITEMNAME: - case CHANNEL_NOWPLAYING_STATIONLOCATION: - case CHANNEL_NOWPLAYING_STATIONNAME: - case CHANNEL_NOWPLAYING_TRACK: - case CHANNEL_RATEENABLED: - case CHANNEL_SKIPENABLED: - case CHANNEL_SKIPPREVIOUSENABLED: - commandExecutor.getInformations(APIRequest.NOW_PLAYING); - break; - case CHANNEL_VOLUME: - commandExecutor.getInformations(APIRequest.VOLUME); - break; - default: - logger.debug("{} : Got command '{}' for channel '{}' which is unhandled!", getDeviceName(), command, - channelUID.getId()); - } - return; - } - switch (channelUID.getIdWithoutGroup()) { - case CHANNEL_POWER: - if (command instanceof OnOffType) { - commandExecutor.postPower((OnOffType) command); - } else { - logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); - } - break; - case CHANNEL_VOLUME: - if (command instanceof PercentType) { - commandExecutor.postVolume((PercentType) command); - } else { - logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); - } - break; - case CHANNEL_MUTE: - if (command instanceof OnOffType) { - commandExecutor.postVolumeMuted((OnOffType) command); - } else { - logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); - } - break; - case CHANNEL_OPERATIONMODE: - if (command instanceof StringType) { - String cmd = command.toString().toUpperCase().trim(); - try { - OperationModeType mode = OperationModeType.valueOf(cmd); - commandExecutor.postOperationMode(mode); - } catch (IllegalArgumentException iae) { - logger.warn("{}: OperationMode \"{}\" is not valid!", getDeviceName(), cmd); - } - } - break; - case CHANNEL_PLAYER_CONTROL: - if ((command instanceof PlayPauseType) || (command instanceof NextPreviousType)) { - commandExecutor.postPlayerControl(command); - } else { - logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); - } - break; - case CHANNEL_PRESET: - if (command instanceof DecimalType) { - commandExecutor.postPreset((DecimalType) command); - } else { - logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); - } - break; - case CHANNEL_BASS: - if (command instanceof DecimalType) { - commandExecutor.postBass((DecimalType) command); - } else { - logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); - } - break; - case CHANNEL_SAVE_AS_PRESET: - if (command instanceof DecimalType) { - commandExecutor.addCurrentContentItemToPresetContainer((DecimalType) command); - } else { - logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); - } - break; - case CHANNEL_KEY_CODE: - if (command instanceof StringType) { - String cmd = command.toString().toUpperCase().trim(); - try { - RemoteKeyType keyCommand = RemoteKeyType.valueOf(cmd); - commandExecutor.postRemoteKey(keyCommand); - } catch (IllegalArgumentException e) { - logger.debug("{}: Unhandled remote key: {}", getDeviceName(), cmd); - } - } - break; - default: - Channel channel = getThing().getChannel(channelUID.getId()); - if (channel != null) { - ChannelTypeUID chTypeUid = channel.getChannelTypeUID(); - if (chTypeUid != null) { - switch (channel.getChannelTypeUID().getId()) { - case CHANNEL_NOTIFICATION_SOUND: - String appKey = Objects.toString(getConfig().get(BoseSoundTouchConfiguration.APP_KEY), - null); - if (appKey != null && !appKey.isEmpty()) { - if (command instanceof StringType) { - String url = command.toString(); - BoseSoundTouchNotificationChannelConfiguration notificationConfiguration = channel - .getConfiguration() - .as(BoseSoundTouchNotificationChannelConfiguration.class); - if (!url.isEmpty()) { - commandExecutor.playNotificationSound(appKey, notificationConfiguration, - url); - } - } - } else { - logger.warn("Missing app key - cannot use notification api"); - } - return; - } - } - } - logger.warn("{} : Got command '{}' for channel '{}' which is unhandled!", getDeviceName(), command, - channelUID.getId()); - break; - } - } - - /** - * Returns the CommandExecutor of this handler - * - * @return the CommandExecutor of this handler - */ - public CommandExecutor getCommandExecutor() { - return commandExecutor; - } - - /** - * Returns the Session this handler has opened - * - * @return the Session this handler has opened - */ - public Session getSession() { - return session; - } - - /** - * Returns the name of the device delivered from itself - * - * @return the name of the device delivered from itself - */ - public String getDeviceName() { - return getThing().getProperties().get(DEVICE_INFO_NAME); - } - - /** - * Returns the type of the device delivered from itself - * - * @return the type of the device delivered from itself - */ - public String getDeviceType() { - return getThing().getProperties().get(DEVICE_INFO_TYPE); - } - - /** - * Returns the MAC Address of this device - * - * @return the MAC Address of this device (in format "123456789ABC") - */ - public String getMacAddress() { - return ((String) getThing().getConfiguration().get(BoseSoundTouchConfiguration.MAC_ADDRESS)).replaceAll(":", - ""); - } - - /** - * Returns the IP Address of this device - * - * @return the IP Address of this device - */ - public String getIPAddress() { - return (String) getThing().getConfiguration().getProperties().get(BoseSoundTouchConfiguration.HOST); - } - - /** - * Provides the handler internal scheduler instance - * - * @return the {@link ScheduledExecutorService} instance used by this handler - */ - public ScheduledExecutorService getScheduler() { - return scheduler; - } - - public PresetContainer getPresetContainer() { - return this.presetContainer; - } - - @Override - public void onWebSocketConnect(Session session) { - logger.debug("{}: onWebSocketConnect('{}')", getDeviceName(), session); - this.session = session; - commandExecutor = new CommandExecutor(this); - updateStatus(ThingStatus.ONLINE); - } - - @Override - public void onWebSocketError(Throwable e) { - logger.debug("{}: Error during websocket communication: {}", getDeviceName(), e.getMessage(), e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); - if (commandExecutor != null) { - commandExecutor.postOperationMode(OperationModeType.OFFLINE); - commandExecutor = null; - } - if (session != null) { - session.close(StatusCode.SERVER_ERROR, getDeviceName() + ": Failure: " + e.getMessage()); - session = null; - } - } - - @Override - public void onWebSocketText(String msg) { - logger.debug("{}: onWebSocketText('{}')", getDeviceName(), msg); - try { - xmlResponseProcessor.handleMessage(msg); - } catch (Exception e) { - logger.warn("{}: Could not parse XML from string '{}'.", getDeviceName(), msg, e); - } - } - - @Override - public void onWebSocketBinary(byte[] arr, int pos, int len) { - // we don't expect binary data so just dump if we get some... - logger.debug("{}: onWebSocketBinary({}, {}, '{}')", getDeviceName(), pos, len, Arrays.toString(arr)); - } - - @Override - public void onWebSocketClose(int code, String reason) { - logger.debug("{}: onClose({}, '{}')", getDeviceName(), code, reason); - missedPongsCount = 0; - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, reason); - if (commandExecutor != null) { - commandExecutor.postOperationMode(OperationModeType.OFFLINE); - } - } - - @Override - public void onWebSocketFrame(Frame frame) { - if (frame.getType() == Type.PONG) { - missedPongsCount = 0; - } - } - - private synchronized void openConnection() { - closeConnection(); - try { - client = new WebSocketClient(); - // we need longer timeouts for web socket. - client.setMaxIdleTimeout(360 * 1000); - // Port seems to be hard coded, therefore no user input or discovery is necessary - String wsUrl = "ws://" + getIPAddress() + ":8080/"; - logger.debug("{}: Connecting to: {}", getDeviceName(), wsUrl); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - request.setSubProtocols("gabbo"); - client.setStopTimeout(1000); - client.start(); - client.connect(this, new URI(wsUrl), request); - } catch (Exception e) { - onWebSocketError(e); - } - } - - private synchronized void closeConnection() { - if (session != null) { - try { - session.close(StatusCode.NORMAL, "Binding shutdown"); - } catch (Exception e) { - logger.debug("{}: Error while closing websocket communication: {} ({})", getDeviceName(), - e.getClass().getName(), e.getMessage()); - } - session = null; - } - if (client != null) { - try { - client.stop(); - client.destroy(); - } catch (Exception e) { - logger.debug("{}: Error while closing websocket communication: {} ({})", getDeviceName(), - e.getClass().getName(), e.getMessage()); - } - client = null; - } - - commandExecutor = null; - } - - private void checkConnection() { - if (getThing().getStatus() != ThingStatus.ONLINE || session == null || client == null - || commandExecutor == null) { - openConnection(); // try to reconnect.... - } - - if (getThing().getStatus() == ThingStatus.ONLINE && this.session != null && this.session.isOpen()) { - try { - this.session.getRemote().sendPing(null); - missedPongsCount++; - } catch (IOException | NullPointerException e) { - onWebSocketError(e); - closeConnection(); - openConnection(); - } - - if (missedPongsCount >= MAX_MISSED_PONGS_COUNT) { - logger.debug("{}: Closing connection because of too many missed PONGs: {} (max allowed {}) ", - getDeviceName(), missedPongsCount, MAX_MISSED_PONGS_COUNT); - missedPongsCount = 0; - closeConnection(); - openConnection(); - } - } - } - - public void refreshPresetChannel() { - List stateOptions = presetContainer.getAllPresets().stream().map(e -> e.toStateOption()) - .sorted(Comparator.comparing(StateOption::getValue)).collect(Collectors.toList()); - stateOptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_PRESET), stateOptions); - } - - public void handleGroupUpdated(BoseSoundTouchConfiguration masterPlayerConfiguration) { - String deviceId = getMacAddress(); - - if (masterPlayerConfiguration != null && masterPlayerConfiguration.macAddress != null) { - // Stereo pair - if (Objects.equals(masterPlayerConfiguration.macAddress, deviceId)) { - if (getThing().getThingTypeUID().equals(BST_10_THING_TYPE_UID)) { - logger.debug("{}: Stereo Pair was created and this is the master device.", getDeviceName()); - } else { - logger.debug("{}: Unsupported operation for player of type: {}", getDeviceName(), - getThing().getThingTypeUID()); - } - } else { - if (getThing().getThingTypeUID().equals(BST_10_THING_TYPE_UID)) { - logger.debug("{}: Stereo Pair was created and this is NOT the master device.", getDeviceName()); - updateThing(editThing().withChannels(Collections.emptyList()).build()); - } else { - logger.debug("{}: Unsupported operation for player of type: {}", getDeviceName(), - getThing().getThingTypeUID()); - } - } - } else { - // NO Stereo Pair - if (getThing().getThingTypeUID().equals(BST_10_THING_TYPE_UID)) { - if (getThing().getChannels().isEmpty()) { - logger.debug("{}: Stereo Pair was disbounded. Restoring channels", getDeviceName()); - updateThing(editThing().withChannels(getAllChannels(BST_10_THING_TYPE_UID)).build()); - } else { - logger.debug("{}: Stereo Pair was disbounded.", getDeviceName()); - } - } else { - logger.debug("{}: Unsupported operation for player of type: {}", getDeviceName(), - getThing().getThingTypeUID()); - } - } - } - - private List getAllChannels(ThingTypeUID thingTypeUID) { - ThingHandlerCallback callback = getCallback(); - if (callback == null) { - return Collections.emptyList(); - } - - return CHANNEL_IDS.stream() - .map(channelId -> callback.createChannelBuilder(new ChannelUID(getThing().getUID(), channelId), - createChannelTypeUID(thingTypeUID, channelId)).build()) - .collect(Collectors.toList()); - } - - private ChannelTypeUID createChannelTypeUID(ThingTypeUID thingTypeUID, String channelId) { - if (CHANNEL_OPERATIONMODE.equals(channelId)) { - return createOperationModeChannelTypeUID(thingTypeUID); - } - - return new ChannelTypeUID(BINDING_ID, channelId); - } - - private ChannelTypeUID createOperationModeChannelTypeUID(ThingTypeUID thingTypeUID) { - String channelTypeId = CHANNEL_TYPE_OPERATION_MODE_DEFAULT; - - if (BST_10_THING_TYPE_UID.equals(thingTypeUID) || BST_20_THING_TYPE_UID.equals(thingTypeUID) - || BST_30_THING_TYPE_UID.equals(thingTypeUID)) { - channelTypeId = CHANNEL_TYPE_OPERATION_MODE_BST_10_20_30; - } else if (BST_300_THING_TYPE_UID.equals(thingTypeUID)) { - channelTypeId = CHANNEL_TYPE_OPERATION_MODE_BST_300; - } else if (BST_SA5A_THING_TYPE_UID.equals(thingTypeUID)) { - channelTypeId = CHANNEL_TYPE_OPERATION_MODE_BST_SA5A; - } else if (BST_WLA_THING_TYPE_UID.equals(thingTypeUID)) { - channelTypeId = CHANNEL_TYPE_OPERATION_MODE_BST_WLA; - } else if (BST_WSMS_THING_TYPE_UID.equals(thingTypeUID)) { - channelTypeId = CHANNEL_TYPE_OPERATION_MODE_DEFAULT; - } - - return new ChannelTypeUID(BINDING_ID, channelTypeId); - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bosesoundtouch.internal.handler; + +import static org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchBindingConstants.*; + +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import org.eclipse.jetty.websocket.api.Session; +import org.eclipse.jetty.websocket.api.StatusCode; +import org.eclipse.jetty.websocket.api.WebSocketFrameListener; +import org.eclipse.jetty.websocket.api.WebSocketListener; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.Frame.Type; +import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; +import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.NextPreviousType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.library.types.PlayPauseType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerCallback; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.StateOption; +import org.openhab.binding.bosesoundtouch.internal.APIRequest; +import org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchConfiguration; +import org.openhab.binding.bosesoundtouch.internal.BoseSoundTouchNotificationChannelConfiguration; +import org.openhab.binding.bosesoundtouch.internal.BoseStateDescriptionOptionProvider; +import org.openhab.binding.bosesoundtouch.internal.CommandExecutor; +import org.openhab.binding.bosesoundtouch.internal.OperationModeType; +import org.openhab.binding.bosesoundtouch.internal.PresetContainer; +import org.openhab.binding.bosesoundtouch.internal.RemoteKeyType; +import org.openhab.binding.bosesoundtouch.internal.XMLResponseProcessor; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link BoseSoundTouchHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Christian Niessner - Initial contribution + * @author Thomas Traunbauer - Initial contribution + * @author Kai Kreuzer - code clean up + * @author Alexander Kostadinov - Handling of websocket ping-pong mechanism for thing status check + */ +public class BoseSoundTouchHandler extends BaseThingHandler implements WebSocketListener, WebSocketFrameListener { + + private static final int MAX_MISSED_PONGS_COUNT = 2; + + private static final int RETRY_INTERVAL_IN_SECS = 30; + + private final Logger logger = LoggerFactory.getLogger(BoseSoundTouchHandler.class); + + private ScheduledFuture connectionChecker; + private WebSocketClient client; + private volatile Session session; + private volatile CommandExecutor commandExecutor; + private volatile int missedPongsCount = 0; + + private XMLResponseProcessor xmlResponseProcessor; + + private PresetContainer presetContainer; + private BoseStateDescriptionOptionProvider stateOptionProvider; + + /** + * Creates a new instance of this class for the {@link Thing}. + * + * @param thing the thing that should be handled, not null + * @param presetContainer the preset container instance to use for managing presets + * + * @throws IllegalArgumentException if thing or factory argument is null + */ + public BoseSoundTouchHandler(Thing thing, PresetContainer presetContainer, + BoseStateDescriptionOptionProvider stateOptionProvider) { + super(thing); + this.presetContainer = presetContainer; + this.stateOptionProvider = stateOptionProvider; + xmlResponseProcessor = new XMLResponseProcessor(this); + } + + @Override + public void initialize() { + connectionChecker = scheduler.scheduleWithFixedDelay(() -> checkConnection(), 0, RETRY_INTERVAL_IN_SECS, + TimeUnit.SECONDS); + } + + @Override + public void dispose() { + if (connectionChecker != null && !connectionChecker.isCancelled()) { + connectionChecker.cancel(true); + connectionChecker = null; + } + closeConnection(); + super.dispose(); + } + + @Override + public void handleRemoval() { + presetContainer.clear(); + super.handleRemoval(); + } + + @Override + public void updateState(String channelID, State state) { + // don't update channel if it's not linked (in case of Stereo Pair slave device) + if (isLinked(channelID)) { + super.updateState(channelID, state); + } else { + logger.debug("{}: Skipping state update because of not linked channel '{}'", getDeviceName(), channelID); + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (commandExecutor == null) { + logger.debug("{}: Can't handle command '{}' for channel '{}' because of not initialized connection.", + getDeviceName(), command, channelUID); + return; + } else { + logger.debug("{}: handleCommand({}, {});", getDeviceName(), channelUID, command); + } + + if (command.equals(RefreshType.REFRESH)) { + switch (channelUID.getIdWithoutGroup()) { + case CHANNEL_BASS: + commandExecutor.getInformations(APIRequest.BASS); + break; + case CHANNEL_KEY_CODE: + // refresh makes no sense... ? + break; + case CHANNEL_NOWPLAYING_ALBUM: + case CHANNEL_NOWPLAYING_ARTIST: + case CHANNEL_NOWPLAYING_ARTWORK: + case CHANNEL_NOWPLAYING_DESCRIPTION: + case CHANNEL_NOWPLAYING_GENRE: + case CHANNEL_NOWPLAYING_ITEMNAME: + case CHANNEL_NOWPLAYING_STATIONLOCATION: + case CHANNEL_NOWPLAYING_STATIONNAME: + case CHANNEL_NOWPLAYING_TRACK: + case CHANNEL_RATEENABLED: + case CHANNEL_SKIPENABLED: + case CHANNEL_SKIPPREVIOUSENABLED: + commandExecutor.getInformations(APIRequest.NOW_PLAYING); + break; + case CHANNEL_VOLUME: + commandExecutor.getInformations(APIRequest.VOLUME); + break; + default: + logger.debug("{} : Got command '{}' for channel '{}' which is unhandled!", getDeviceName(), command, + channelUID.getId()); + } + return; + } + switch (channelUID.getIdWithoutGroup()) { + case CHANNEL_POWER: + if (command instanceof OnOffType) { + commandExecutor.postPower((OnOffType) command); + } else { + logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); + } + break; + case CHANNEL_VOLUME: + if (command instanceof PercentType) { + commandExecutor.postVolume((PercentType) command); + } else { + logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); + } + break; + case CHANNEL_MUTE: + if (command instanceof OnOffType) { + commandExecutor.postVolumeMuted((OnOffType) command); + } else { + logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); + } + break; + case CHANNEL_OPERATIONMODE: + if (command instanceof StringType) { + String cmd = command.toString().toUpperCase().trim(); + try { + OperationModeType mode = OperationModeType.valueOf(cmd); + commandExecutor.postOperationMode(mode); + } catch (IllegalArgumentException iae) { + logger.warn("{}: OperationMode \"{}\" is not valid!", getDeviceName(), cmd); + } + } + break; + case CHANNEL_PLAYER_CONTROL: + if ((command instanceof PlayPauseType) || (command instanceof NextPreviousType)) { + commandExecutor.postPlayerControl(command); + } else { + logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); + } + break; + case CHANNEL_PRESET: + if (command instanceof DecimalType) { + commandExecutor.postPreset((DecimalType) command); + } else { + logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); + } + break; + case CHANNEL_BASS: + if (command instanceof DecimalType) { + commandExecutor.postBass((DecimalType) command); + } else { + logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); + } + break; + case CHANNEL_SAVE_AS_PRESET: + if (command instanceof DecimalType) { + commandExecutor.addCurrentContentItemToPresetContainer((DecimalType) command); + } else { + logger.debug("{}: Unhandled command type: {}: {}", getDeviceName(), command.getClass(), command); + } + break; + case CHANNEL_KEY_CODE: + if (command instanceof StringType) { + String cmd = command.toString().toUpperCase().trim(); + try { + RemoteKeyType keyCommand = RemoteKeyType.valueOf(cmd); + commandExecutor.postRemoteKey(keyCommand); + } catch (IllegalArgumentException e) { + logger.debug("{}: Unhandled remote key: {}", getDeviceName(), cmd); + } + } + break; + default: + Channel channel = getThing().getChannel(channelUID.getId()); + if (channel != null) { + ChannelTypeUID chTypeUid = channel.getChannelTypeUID(); + if (chTypeUid != null) { + switch (channel.getChannelTypeUID().getId()) { + case CHANNEL_NOTIFICATION_SOUND: + String appKey = Objects.toString(getConfig().get(BoseSoundTouchConfiguration.APP_KEY), + null); + if (appKey != null && !appKey.isEmpty()) { + if (command instanceof StringType) { + String url = command.toString(); + BoseSoundTouchNotificationChannelConfiguration notificationConfiguration = channel + .getConfiguration() + .as(BoseSoundTouchNotificationChannelConfiguration.class); + if (!url.isEmpty()) { + commandExecutor.playNotificationSound(appKey, notificationConfiguration, + url); + } + } + } else { + logger.warn("Missing app key - cannot use notification api"); + } + return; + } + } + } + logger.warn("{} : Got command '{}' for channel '{}' which is unhandled!", getDeviceName(), command, + channelUID.getId()); + break; + } + } + + /** + * Returns the CommandExecutor of this handler + * + * @return the CommandExecutor of this handler + */ + public CommandExecutor getCommandExecutor() { + return commandExecutor; + } + + /** + * Returns the Session this handler has opened + * + * @return the Session this handler has opened + */ + public Session getSession() { + return session; + } + + /** + * Returns the name of the device delivered from itself + * + * @return the name of the device delivered from itself + */ + public String getDeviceName() { + return getThing().getProperties().get(DEVICE_INFO_NAME); + } + + /** + * Returns the type of the device delivered from itself + * + * @return the type of the device delivered from itself + */ + public String getDeviceType() { + return getThing().getProperties().get(DEVICE_INFO_TYPE); + } + + /** + * Returns the MAC Address of this device + * + * @return the MAC Address of this device (in format "123456789ABC") + */ + public String getMacAddress() { + return ((String) getThing().getConfiguration().get(BoseSoundTouchConfiguration.MAC_ADDRESS)).replaceAll(":", + ""); + } + + /** + * Returns the IP Address of this device + * + * @return the IP Address of this device + */ + public String getIPAddress() { + return (String) getThing().getConfiguration().getProperties().get(BoseSoundTouchConfiguration.HOST); + } + + /** + * Provides the handler internal scheduler instance + * + * @return the {@link ScheduledExecutorService} instance used by this handler + */ + public ScheduledExecutorService getScheduler() { + return scheduler; + } + + public PresetContainer getPresetContainer() { + return this.presetContainer; + } + + @Override + public void onWebSocketConnect(Session session) { + logger.debug("{}: onWebSocketConnect('{}')", getDeviceName(), session); + this.session = session; + commandExecutor = new CommandExecutor(this); + updateStatus(ThingStatus.ONLINE); + } + + @Override + public void onWebSocketError(Throwable e) { + logger.debug("{}: Error during websocket communication: {}", getDeviceName(), e.getMessage(), e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + if (commandExecutor != null) { + commandExecutor.postOperationMode(OperationModeType.OFFLINE); + commandExecutor = null; + } + if (session != null) { + session.close(StatusCode.SERVER_ERROR, getDeviceName() + ": Failure: " + e.getMessage()); + session = null; + } + } + + @Override + public void onWebSocketText(String msg) { + logger.debug("{}: onWebSocketText('{}')", getDeviceName(), msg); + try { + xmlResponseProcessor.handleMessage(msg); + } catch (Exception e) { + logger.warn("{}: Could not parse XML from string '{}'.", getDeviceName(), msg, e); + } + } + + @Override + public void onWebSocketBinary(byte[] arr, int pos, int len) { + // we don't expect binary data so just dump if we get some... + logger.debug("{}: onWebSocketBinary({}, {}, '{}')", getDeviceName(), pos, len, Arrays.toString(arr)); + } + + @Override + public void onWebSocketClose(int code, String reason) { + logger.debug("{}: onClose({}, '{}')", getDeviceName(), code, reason); + missedPongsCount = 0; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, reason); + if (commandExecutor != null) { + commandExecutor.postOperationMode(OperationModeType.OFFLINE); + } + } + + @Override + public void onWebSocketFrame(Frame frame) { + if (frame.getType() == Type.PONG) { + missedPongsCount = 0; + } + } + + private synchronized void openConnection() { + closeConnection(); + try { + client = new WebSocketClient(); + // we need longer timeouts for web socket. + client.setMaxIdleTimeout(360 * 1000); + // Port seems to be hard coded, therefore no user input or discovery is necessary + String wsUrl = "ws://" + getIPAddress() + ":8080/"; + logger.debug("{}: Connecting to: {}", getDeviceName(), wsUrl); + ClientUpgradeRequest request = new ClientUpgradeRequest(); + request.setSubProtocols("gabbo"); + client.setStopTimeout(1000); + client.start(); + client.connect(this, new URI(wsUrl), request); + } catch (Exception e) { + onWebSocketError(e); + } + } + + private synchronized void closeConnection() { + if (session != null) { + try { + session.close(StatusCode.NORMAL, "Binding shutdown"); + } catch (Exception e) { + logger.debug("{}: Error while closing websocket communication: {} ({})", getDeviceName(), + e.getClass().getName(), e.getMessage()); + } + session = null; + } + if (client != null) { + try { + client.stop(); + client.destroy(); + } catch (Exception e) { + logger.debug("{}: Error while closing websocket communication: {} ({})", getDeviceName(), + e.getClass().getName(), e.getMessage()); + } + client = null; + } + + commandExecutor = null; + } + + private void checkConnection() { + if (getThing().getStatus() != ThingStatus.ONLINE || session == null || client == null + || commandExecutor == null) { + openConnection(); // try to reconnect.... + } + + if (getThing().getStatus() == ThingStatus.ONLINE && this.session != null && this.session.isOpen()) { + try { + this.session.getRemote().sendPing(null); + missedPongsCount++; + } catch (IOException | NullPointerException e) { + onWebSocketError(e); + closeConnection(); + openConnection(); + } + + if (missedPongsCount >= MAX_MISSED_PONGS_COUNT) { + logger.debug("{}: Closing connection because of too many missed PONGs: {} (max allowed {}) ", + getDeviceName(), missedPongsCount, MAX_MISSED_PONGS_COUNT); + missedPongsCount = 0; + closeConnection(); + openConnection(); + } + } + } + + public void refreshPresetChannel() { + List stateOptions = presetContainer.getAllPresets().stream().map(e -> e.toStateOption()) + .sorted(Comparator.comparing(StateOption::getValue)).collect(Collectors.toList()); + stateOptionProvider.setStateOptions(new ChannelUID(getThing().getUID(), CHANNEL_PRESET), stateOptions); + } + + public void handleGroupUpdated(BoseSoundTouchConfiguration masterPlayerConfiguration) { + String deviceId = getMacAddress(); + + if (masterPlayerConfiguration != null && masterPlayerConfiguration.macAddress != null) { + // Stereo pair + if (Objects.equals(masterPlayerConfiguration.macAddress, deviceId)) { + if (getThing().getThingTypeUID().equals(BST_10_THING_TYPE_UID)) { + logger.debug("{}: Stereo Pair was created and this is the master device.", getDeviceName()); + } else { + logger.debug("{}: Unsupported operation for player of type: {}", getDeviceName(), + getThing().getThingTypeUID()); + } + } else { + if (getThing().getThingTypeUID().equals(BST_10_THING_TYPE_UID)) { + logger.debug("{}: Stereo Pair was created and this is NOT the master device.", getDeviceName()); + updateThing(editThing().withChannels(Collections.emptyList()).build()); + } else { + logger.debug("{}: Unsupported operation for player of type: {}", getDeviceName(), + getThing().getThingTypeUID()); + } + } + } else { + // NO Stereo Pair + if (getThing().getThingTypeUID().equals(BST_10_THING_TYPE_UID)) { + if (getThing().getChannels().isEmpty()) { + logger.debug("{}: Stereo Pair was disbounded. Restoring channels", getDeviceName()); + updateThing(editThing().withChannels(getAllChannels(BST_10_THING_TYPE_UID)).build()); + } else { + logger.debug("{}: Stereo Pair was disbounded.", getDeviceName()); + } + } else { + logger.debug("{}: Unsupported operation for player of type: {}", getDeviceName(), + getThing().getThingTypeUID()); + } + } + } + + private List getAllChannels(ThingTypeUID thingTypeUID) { + ThingHandlerCallback callback = getCallback(); + if (callback == null) { + return Collections.emptyList(); + } + + return CHANNEL_IDS.stream() + .map(channelId -> callback.createChannelBuilder(new ChannelUID(getThing().getUID(), channelId), + createChannelTypeUID(thingTypeUID, channelId)).build()) + .collect(Collectors.toList()); + } + + private ChannelTypeUID createChannelTypeUID(ThingTypeUID thingTypeUID, String channelId) { + if (CHANNEL_OPERATIONMODE.equals(channelId)) { + return createOperationModeChannelTypeUID(thingTypeUID); + } + + return new ChannelTypeUID(BINDING_ID, channelId); + } + + private ChannelTypeUID createOperationModeChannelTypeUID(ThingTypeUID thingTypeUID) { + String channelTypeId = CHANNEL_TYPE_OPERATION_MODE_DEFAULT; + + if (BST_10_THING_TYPE_UID.equals(thingTypeUID) || BST_20_THING_TYPE_UID.equals(thingTypeUID) + || BST_30_THING_TYPE_UID.equals(thingTypeUID)) { + channelTypeId = CHANNEL_TYPE_OPERATION_MODE_BST_10_20_30; + } else if (BST_300_THING_TYPE_UID.equals(thingTypeUID)) { + channelTypeId = CHANNEL_TYPE_OPERATION_MODE_BST_300; + } else if (BST_SA5A_THING_TYPE_UID.equals(thingTypeUID)) { + channelTypeId = CHANNEL_TYPE_OPERATION_MODE_BST_SA5A; + } else if (BST_WLA_THING_TYPE_UID.equals(thingTypeUID)) { + channelTypeId = CHANNEL_TYPE_OPERATION_MODE_BST_WLA; + } else if (BST_WSMS_THING_TYPE_UID.equals(thingTypeUID)) { + channelTypeId = CHANNEL_TYPE_OPERATION_MODE_DEFAULT; + } + + return new ChannelTypeUID(BINDING_ID, channelTypeId); + } +} diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/config/config.xml index c9160a16d4f2c..5e54b6a895401 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/config/config.xml @@ -1,8 +1,8 @@ - + xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd"> @@ -17,40 +17,47 @@ An authorization key used to identify the client application. - Should be requested from the developer portal. + Should be requested from the developer + portal. - + - This indicates the desired volume level while playing the notification. - The value represents a percentage (0 to 100) of the full audible range of the speaker device. - A value less than 10 or greater than 70 will result in an error and not play the notification. - Upon completion of the notification, the speaker volume will return to its original value. - If not present, the notification will play at the existing volume level. + This indicates the desired volume level while playing the notification. + The value represents a percentage + (0 to 100) of the full audible range of the speaker device. + A value less than 10 or greater than 70 will result in an + error and not play the notification. + Upon completion of the notification, the speaker volume will return to its + original value. + If not present, the notification will play at the existing volume level. - This indicates the service providing the notification. - This text will appear on the device display (when available) and the SoundTouch application screen. + This indicates the service providing the notification. + This text will appear on the device display (when + available) and the SoundTouch application screen. Notification - This indicates the reason for the notification. - This text will appear on the device display (when available) and the SoundTouch application screen. - If a reason string is not provided, the field with be blank. + This indicates the reason for the notification. + This text will appear on the device display (when + available) and the SoundTouch application screen. + If a reason string is not provided, the field with be blank. - This indicates further details about the notification. - This text will appear on the device display (when available) and the SoundTouch application screen. - If a message string is not provided, the field with be blank. + This indicates further details about the notification. + This text will appear on the device display (when + available) and the SoundTouch application screen. + If a message string is not provided, the field with be blank. diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch10.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch10.xml index 275f769cdc6fb..6bf9414780f31 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch10.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch10.xml @@ -1,5 +1,6 @@ - @@ -8,30 +9,30 @@ Bose SoundTouch 10 Speaker - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + - + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch20.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch20.xml index a8646dc40d072..61fd4c6c20de3 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch20.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch20.xml @@ -1,37 +1,38 @@ - - + Bose SoundTouch 20 Speaker - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + - + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch30.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch30.xml index 80bead5df424f..48f6985c5d793 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch30.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch30.xml @@ -1,5 +1,6 @@ - @@ -8,30 +9,30 @@ Bose SoundTouch 30 Speaker - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + - + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch300.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch300.xml index 469fc47350d94..461743833f54e 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch300.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouch300.xml @@ -1,5 +1,6 @@ - @@ -8,27 +9,27 @@ Bose SoundTouch 300 Speaker - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouchSA5Amplifier.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouchSA5Amplifier.xml index 9b343830caaf3..26973335e009c 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouchSA5Amplifier.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouchSA5Amplifier.xml @@ -1,5 +1,6 @@ - @@ -8,28 +9,28 @@ A Bose SoundTouch SA-5 Amplifier - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouchWirelessLinkAdapter.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouchWirelessLinkAdapter.xml index 3c09402a1daba..a101b1400727d 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouchWirelessLinkAdapter.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/SoundTouchWirelessLinkAdapter.xml @@ -1,5 +1,6 @@ - @@ -8,27 +9,27 @@ Bose SoundTouch Wireless Link Adapter - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/UnknownSoundTouch.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/UnknownSoundTouch.xml index 17829b56f492b..de403aa9ab147 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/UnknownSoundTouch.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/UnknownSoundTouch.xml @@ -1,5 +1,6 @@ - @@ -8,28 +9,28 @@ Aan unknown Bose SoundTouch Device - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/WaveSoundTouchMusicSystemIV.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/WaveSoundTouchMusicSystemIV.xml index 865fa4ea4b346..8d96187fb56d3 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/WaveSoundTouchMusicSystemIV.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/WaveSoundTouchMusicSystemIV.xml @@ -1,5 +1,6 @@ - @@ -8,28 +9,28 @@ A Bose Wave SoundTouch Music System IV - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/channels.xml index ae82eee4f9267..7882cbe0e7734 100644 --- a/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.bosesoundtouch/src/main/resources/ESH-INF/thing/channels.xml @@ -1,5 +1,6 @@ - @@ -51,63 +52,63 @@ String Current playing album name - + String Current playing artist name - + Image Artwork for the current playing song - + String Description to current playing song - + String Genre of current playing song - + String Visible description shown in display - + String Location of current playing radio station - + String Name of current playing radio station - + String Track currently playing - + @@ -158,7 +159,7 @@ Switch Current source allows rating - + @@ -171,14 +172,14 @@ Switch Current source allows skipping to next track - + Switch Current source allows scrolling through tracks - + @@ -193,7 +194,7 @@ Number Bass (-9 minimum, 0 maximum) - + @@ -286,6 +287,6 @@ String Play a notification sound by a given URI - + diff --git a/bundles/org.openhab.binding.bsblan/.classpath b/bundles/org.openhab.binding.bsblan/.classpath index e74dbb099f67d..39abf1c5e9102 100644 --- a/bundles/org.openhab.binding.bsblan/.classpath +++ b/bundles/org.openhab.binding.bsblan/.classpath @@ -1,49 +1,49 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.bsblan/pom.xml b/bundles/org.openhab.binding.bsblan/pom.xml index 677cb300fb537..61bde7a4fb432 100644 --- a/bundles/org.openhab.binding.bsblan/pom.xml +++ b/bundles/org.openhab.binding.bsblan/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.bsblan diff --git a/bundles/org.openhab.binding.bsblan/src/main/feature/feature.xml b/bundles/org.openhab.binding.bsblan/src/main/feature/feature.xml index 318cf1cfb3d5f..2deb90ee88871 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.bsblan/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.bsblan/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.bsblan/${project.version} + diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/BsbLanHandlerFactory.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/BsbLanHandlerFactory.java index a35bbe3b88643..38ae3cc454100 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/BsbLanHandlerFactory.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/BsbLanHandlerFactory.java @@ -1,67 +1,67 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bsblan.internal; - -import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; - -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; -import org.openhab.binding.bsblan.internal.handler.BsbLanBridgeHandler; -import org.openhab.binding.bsblan.internal.handler.BsbLanParameterHandler; -import org.osgi.service.component.annotations.Component; - -/** - * The {@link BsbLanHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Peter Schraffl - Initial contribution - */ -@NonNullByDefault -@Component(service = ThingHandlerFactory.class, configurationPid = "binding.bsblan") -public class BsbLanHandlerFactory extends BaseThingHandlerFactory { - - private static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet() { - - private static final long serialVersionUID = 1L; - { - add(THING_TYPE_PARAMETER); - add(THING_TYPE_BRIDGE); - } - }; - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected @Nullable ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - if (thingTypeUID.equals(THING_TYPE_PARAMETER)) { - return new BsbLanParameterHandler(thing); - } else if (thingTypeUID.equals(THING_TYPE_BRIDGE)) { - return new BsbLanBridgeHandler((Bridge) thing); - } - return null; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bsblan.internal; + +import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.bsblan.internal.handler.BsbLanBridgeHandler; +import org.openhab.binding.bsblan.internal.handler.BsbLanParameterHandler; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link BsbLanHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Peter Schraffl - Initial contribution + */ +@NonNullByDefault +@Component(service = ThingHandlerFactory.class, configurationPid = "binding.bsblan") +public class BsbLanHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet() { + + private static final long serialVersionUID = 1L; + { + add(THING_TYPE_PARAMETER); + add(THING_TYPE_BRIDGE); + } + }; + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(THING_TYPE_PARAMETER)) { + return new BsbLanParameterHandler(thing); + } else if (thingTypeUID.equals(THING_TYPE_BRIDGE)) { + return new BsbLanBridgeHandler((Bridge) thing); + } + return null; + } +} diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/BsbLanApiCaller.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/BsbLanApiCaller.java index 50f97f5555aed..1d027d49cb0b0 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/BsbLanApiCaller.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/BsbLanApiCaller.java @@ -1,154 +1,156 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bsblan.internal.api; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.IOException; -import java.util.Set; -import java.util.HashSet; -import java.nio.charset.Charset; - -import org.apache.commons.lang.StringUtils; -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.io.net.http.HttpUtil; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterQueryResponseDTO; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetResponseDTO; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetResultDTO; -import org.openhab.binding.bsblan.internal.configuration.BsbLanBridgeConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; - -/** - * Utility class to call the BSB-LAN REST API. - * - * @author Peter Schraffl - Initial contribution - */ -@NonNullByDefault -public class BsbLanApiCaller { - - private final Logger logger = LoggerFactory.getLogger(BsbLanApiCaller.class); - private final BsbLanBridgeConfiguration bridgeConfig; - - public BsbLanApiCaller(BsbLanBridgeConfiguration config) { - bridgeConfig = config; - } - - public @Nullable BsbLanApiParameterQueryResponseDTO queryParameter(Integer parameterId) { - Set parameters = new HashSet<>(); - - parameters.add(parameterId); - return queryParameters(parameters); - } - - public @Nullable BsbLanApiParameterQueryResponseDTO queryParameters(Set parameterIds) { - // note: make the request even if parameterIds is empty as - // thing OFFLINE/ONLINE detection relies on a response - - String apiPath = String.format("/JQ=%s", StringUtils.join(parameterIds, ",")); - return makeRestCall(BsbLanApiParameterQueryResponseDTO.class, "GET", apiPath, null); - } - - public boolean setParameter(Integer parameterId, String value, BsbLanApiParameterSetRequestDTO.Type type) { - // prepare request content - BsbLanApiParameterSetRequestDTO request = new BsbLanApiParameterSetRequestDTO(); - request.parameter = parameterId.toString(); - request.value = value; - request.type = type; - - // make REST call and process response - BsbLanApiParameterSetResponseDTO setResponse = makeRestCall(BsbLanApiParameterSetResponseDTO.class, "POST", "/JS", request); - if (setResponse == null) { - logger.debug("Failed to set parameter {} to '{}': no response received", parameterId, value); - return false; - } - - BsbLanApiParameterSetResultDTO result = setResponse.getOrDefault(parameterId, null); - if (result == null) { - logger.debug("Failed to set parameter {} to '{}'': result is null", parameterId, value); - return false; - } - if (result.status == null) { - logger.debug("Failed to set parameter {} to '{}': status is null", parameterId, value); - return false; - } - if (result.status != BsbLanApiParameterSetResultDTO.Status.SUCCESS) { - logger.debug("Failed to set parameter {} to '{}': status = {}", parameterId, value, result.status); - return false; - } - return true; - } - - private String createApiBaseUrl() { - final String host = StringUtils.trimToEmpty(bridgeConfig.host); - final String username = StringUtils.trimToEmpty(bridgeConfig.username); - final String password = StringUtils.trimToEmpty(bridgeConfig.password); - final String passkey = StringUtils.trimToEmpty(bridgeConfig.passkey); - - StringBuilder url = new StringBuilder(); - url.append("http://"); - if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) { - url.append(username).append(":").append(password).append("@"); - } - url.append(host); - if (bridgeConfig.port != 80) { - url.append(":").append(bridgeConfig.port); - } - if (StringUtils.isNotBlank(passkey)) { - url.append("/").append(passkey); - } - return url.toString(); - } - - /** - * @param responseType response class type - * @param httpMethod to execute - * @param apiPath to request - * @param content to add to request - * @return the object representation of the json response - */ - private @Nullable T makeRestCall(Class responseType, String httpMethod, String apiPath, @Nullable BsbLanApiContentDTO request) { - try { - String url = createApiBaseUrl() + apiPath; - logger.trace("api request url = '{}'", url); - - InputStream contentStream = null; - String contentType = null; - if (request != null) { - String content = BsbLanApiContentConverter.toJson(request); - logger.trace("api request content: '{}'", content); - if (StringUtils.isNotBlank(content)) { - contentStream = new ByteArrayInputStream(content.getBytes(Charset.forName("UTF-8"))); - contentType = "application/json"; - } - } - - String response = HttpUtil.executeUrl(httpMethod, url, contentStream, contentType, API_TIMEOUT); - if (response == null) { - logger.debug("no response returned"); - return null; - } - - logger.trace("api response content: '{}'", response); - return BsbLanApiContentConverter.fromJson(response, responseType); - } catch (IOException | IllegalStateException e) { - logger.debug("Error executing bsb-lan api request: {}", e.getMessage()); - return null; - } - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bsblan.internal.api; + +import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.io.net.http.HttpUtil; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterQueryResponseDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetResponseDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetResultDTO; +import org.openhab.binding.bsblan.internal.configuration.BsbLanBridgeConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class to call the BSB-LAN REST API. + * + * @author Peter Schraffl - Initial contribution + */ +@NonNullByDefault +public class BsbLanApiCaller { + + private final Logger logger = LoggerFactory.getLogger(BsbLanApiCaller.class); + private final BsbLanBridgeConfiguration bridgeConfig; + + public BsbLanApiCaller(BsbLanBridgeConfiguration config) { + bridgeConfig = config; + } + + public @Nullable BsbLanApiParameterQueryResponseDTO queryParameter(Integer parameterId) { + Set parameters = new HashSet<>(); + + parameters.add(parameterId); + return queryParameters(parameters); + } + + public @Nullable BsbLanApiParameterQueryResponseDTO queryParameters(Set parameterIds) { + // note: make the request even if parameterIds is empty as + // thing OFFLINE/ONLINE detection relies on a response + + String apiPath = String.format("/JQ=%s", StringUtils.join(parameterIds, ",")); + return makeRestCall(BsbLanApiParameterQueryResponseDTO.class, "GET", apiPath, null); + } + + public boolean setParameter(Integer parameterId, String value, BsbLanApiParameterSetRequestDTO.Type type) { + // prepare request content + BsbLanApiParameterSetRequestDTO request = new BsbLanApiParameterSetRequestDTO(); + request.parameter = parameterId.toString(); + request.value = value; + request.type = type; + + // make REST call and process response + BsbLanApiParameterSetResponseDTO setResponse = makeRestCall(BsbLanApiParameterSetResponseDTO.class, "POST", + "/JS", request); + if (setResponse == null) { + logger.debug("Failed to set parameter {} to '{}': no response received", parameterId, value); + return false; + } + + BsbLanApiParameterSetResultDTO result = setResponse.getOrDefault(parameterId, null); + if (result == null) { + logger.debug("Failed to set parameter {} to '{}'': result is null", parameterId, value); + return false; + } + if (result.status == null) { + logger.debug("Failed to set parameter {} to '{}': status is null", parameterId, value); + return false; + } + if (result.status != BsbLanApiParameterSetResultDTO.Status.SUCCESS) { + logger.debug("Failed to set parameter {} to '{}': status = {}", parameterId, value, result.status); + return false; + } + return true; + } + + private String createApiBaseUrl() { + final String host = StringUtils.trimToEmpty(bridgeConfig.host); + final String username = StringUtils.trimToEmpty(bridgeConfig.username); + final String password = StringUtils.trimToEmpty(bridgeConfig.password); + final String passkey = StringUtils.trimToEmpty(bridgeConfig.passkey); + + StringBuilder url = new StringBuilder(); + url.append("http://"); + if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) { + url.append(username).append(":").append(password).append("@"); + } + url.append(host); + if (bridgeConfig.port != 80) { + url.append(":").append(bridgeConfig.port); + } + if (StringUtils.isNotBlank(passkey)) { + url.append("/").append(passkey); + } + return url.toString(); + } + + /** + * @param responseType response class type + * @param httpMethod to execute + * @param apiPath to request + * @param content to add to request + * @return the object representation of the json response + */ + private @Nullable T makeRestCall(Class responseType, String httpMethod, String apiPath, + @Nullable BsbLanApiContentDTO request) { + try { + String url = createApiBaseUrl() + apiPath; + logger.trace("api request url = '{}'", url); + + InputStream contentStream = null; + String contentType = null; + if (request != null) { + String content = BsbLanApiContentConverter.toJson(request); + logger.trace("api request content: '{}'", content); + if (StringUtils.isNotBlank(content)) { + contentStream = new ByteArrayInputStream(content.getBytes(Charset.forName("UTF-8"))); + contentType = "application/json"; + } + } + + String response = HttpUtil.executeUrl(httpMethod, url, contentStream, contentType, API_TIMEOUT); + if (response == null) { + logger.debug("no response returned"); + return null; + } + + logger.trace("api response content: '{}'", response); + return BsbLanApiContentConverter.fromJson(response, responseType); + } catch (IOException | IllegalStateException e) { + logger.debug("Error executing bsb-lan api request: {}", e.getMessage()); + return null; + } + } +} diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/BsbLanApiContentConverter.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/BsbLanApiContentConverter.java index 227abcae4d372..a5bc8d98e48c9 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/BsbLanApiContentConverter.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/BsbLanApiContentConverter.java @@ -1,52 +1,50 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bsblan.internal.api; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; - -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; - -/** - * Utility class to create JSON content. - * - * @author Peter Schraffl - Initial contribution - */ -@NonNullByDefault -public class BsbLanApiContentConverter { - private static final Logger LOGGER = LoggerFactory.getLogger(BsbLanApiContentConverter.class); - private static final Gson GSON = new Gson(); - - public static String toJson(BsbLanApiContentDTO request) { - return GSON.toJson(request); - } - - public static @Nullable T fromJson(String content, Class resultType) { - try { - T result = GSON.fromJson(content, resultType); - if (result == null) { - LOGGER.debug("result null after json parsing (response = {})", content); - } - return result; - } catch (JsonSyntaxException e) { - LOGGER.debug("Parsing JSON API response failed: {}", e.getMessage()); - return null; - } - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bsblan.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +/** + * Utility class to create JSON content. + * + * @author Peter Schraffl - Initial contribution + */ +@NonNullByDefault +public class BsbLanApiContentConverter { + private static final Logger LOGGER = LoggerFactory.getLogger(BsbLanApiContentConverter.class); + private static final Gson GSON = new Gson(); + + public static String toJson(BsbLanApiContentDTO request) { + return GSON.toJson(request); + } + + public static @Nullable T fromJson(String content, Class resultType) { + try { + T result = GSON.fromJson(content, resultType); + if (result == null) { + LOGGER.debug("result null after json parsing (response = {})", content); + } + return result; + } catch (JsonSyntaxException e) { + LOGGER.debug("Parsing JSON API response failed: {}", e.getMessage()); + return null; + } + } +} diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterDTO.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterDTO.java index 177218a705041..4cd0175def67c 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterDTO.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterDTO.java @@ -23,23 +23,23 @@ public class BsbLanApiParameterDTO { public enum DataType { @SerializedName("0") - DT_VALS(0), // plain value + DT_VALS(0), // plain value @SerializedName("1") - DT_ENUM(1), // value (8/16 Bit) followed by space followed by text + DT_ENUM(1), // value (8/16 Bit) followed by space followed by text @SerializedName("2") - DT_BITS(2), // bit value followed by bitmask followed by text + DT_BITS(2), // bit value followed by bitmask followed by text @SerializedName("3") - DT_WDAY(3), // weekday + DT_WDAY(3), // weekday @SerializedName("4") - DT_HHMM(4), // hour:minute + DT_HHMM(4), // hour:minute @SerializedName("5") - DT_DTTM(5), // date and time + DT_DTTM(5), // date and time @SerializedName("6") - DT_DDMM(6), // day and month + DT_DDMM(6), // day and month @SerializedName("7") - DT_STRN(7), // string + DT_STRN(7), // string @SerializedName("8") - DT_DWHM(8); // PPS time (day of week, hour:minute) + DT_DWHM(8); // PPS time (day of week, hour:minute) private final int value; diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterQueryResponseDTO.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterQueryResponseDTO.java index 2d3a60ee13fc7..f22bd2324f8fb 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterQueryResponseDTO.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterQueryResponseDTO.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.bsblan.internal.api.dto; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO; - import java.util.HashMap; /** @@ -23,5 +21,6 @@ * @author Peter Schraffl - Initial contribution */ @SuppressWarnings("serial") -public class BsbLanApiParameterQueryResponseDTO extends HashMap implements BsbLanApiContentDTO { +public class BsbLanApiParameterQueryResponseDTO extends HashMap + implements BsbLanApiContentDTO { } diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetRequestDTO.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetRequestDTO.java index 7eec3722ba29b..9ea962ace0066 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetRequestDTO.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetRequestDTO.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.bsblan.internal.api.dto; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO; - import com.google.gson.annotations.SerializedName; /** @@ -31,6 +29,7 @@ public enum Type { SET("SET"); private final String value; + Type(String value) { this.value = value; } diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetResponseDTO.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetResponseDTO.java index c63532cab847c..abb04c0e726df 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetResponseDTO.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetResponseDTO.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.bsblan.internal.api.dto; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiContentDTO; - import java.util.HashMap; /** @@ -23,5 +21,6 @@ * @author Peter Schraffl - Initial contribution */ @SuppressWarnings("serial") -public class BsbLanApiParameterSetResponseDTO extends HashMap implements BsbLanApiContentDTO { +public class BsbLanApiParameterSetResponseDTO extends HashMap + implements BsbLanApiContentDTO { } diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetResultDTO.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetResultDTO.java index a24abf02f13a3..4f12d1f4c7392 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetResultDTO.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/api/dto/BsbLanApiParameterSetResultDTO.java @@ -31,6 +31,7 @@ public enum Status { READ_ONLY(2); private final int value; + Status(int value) { this.value = value; } diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanBaseThingHandler.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanBaseThingHandler.java index 2cd0bf3b4e7ca..69148d09e430e 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanBaseThingHandler.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanBaseThingHandler.java @@ -23,10 +23,8 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; - -import org.openhab.binding.bsblan.internal.configuration.BsbLanBridgeConfiguration; import org.openhab.binding.bsblan.internal.api.BsbLanApiCaller; - +import org.openhab.binding.bsblan.internal.configuration.BsbLanBridgeConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,7 +72,7 @@ public void initialize() { } ThingHandler handler = bridge.getHandler(); if (handler instanceof BsbLanBridgeHandler) { - this.bridgeHandler = (BsbLanBridgeHandler)handler; + this.bridgeHandler = (BsbLanBridgeHandler) handler; } } return this.bridgeHandler; diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanBridgeHandler.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanBridgeHandler.java index e8e6f14b03bc6..0fbabb89ccff7 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanBridgeHandler.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanBridgeHandler.java @@ -12,12 +12,13 @@ */ package org.openhab.binding.bsblan.internal.handler; +import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; + import java.util.HashSet; import java.util.Set; -import java.util.stream.*; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; - +import java.util.stream.*; import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -34,8 +35,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; - /** * Bridge for BSB-LAN devices. * @@ -81,14 +80,14 @@ public void initialize() { // validate 'host' configuration if (StringUtils.isBlank(bridgeConfig.host)) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Parameter 'host' is mandatory and must be configured"); + "Parameter 'host' is mandatory and must be configured"); return; } // validate 'refreshInterval' configuration - if (bridgeConfig.refreshInterval != null && bridgeConfig.refreshInterval < MIN_REFRESH_INTERVAL) { + if (bridgeConfig.refreshInterval != null && bridgeConfig.refreshInterval < MIN_REFRESH_INTERVAL) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - String.format("Parameter 'refreshInterval' must be at least %d seconds", MIN_REFRESH_INTERVAL)); + String.format("Parameter 'refreshInterval' must be at least %d seconds", MIN_REFRESH_INTERVAL)); return; } @@ -129,19 +128,18 @@ private void doRefresh() { BsbLanApiCaller apiCaller = new BsbLanApiCaller(bridgeConfig); // refresh all parameters - Set parameterIds = things.stream() - .filter(thing -> thing instanceof BsbLanParameterHandler) - .map(thing -> (BsbLanParameterHandler) thing) - .map(thing -> thing.getParameterId()) - .collect(Collectors.toSet()); + Set parameterIds = things.stream().filter(thing -> thing instanceof BsbLanParameterHandler) + .map(thing -> (BsbLanParameterHandler) thing).map(thing -> thing.getParameterId()) + .collect(Collectors.toSet()); cachedParameterQueryResponse = apiCaller.queryParameters(parameterIds); - // InetAddress.isReachable(...) check returned false on RPi although the device is reachable (worked on Windows). + // InetAddress.isReachable(...) check returned false on RPi although the device is reachable (worked on + // Windows). // Therefore we check status depending on the response. if (cachedParameterQueryResponse == null) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, - "Did not receive a response from BSB-LAN device. Check your configuration and if device is online."); + "Did not receive a response from BSB-LAN device. Check your configuration and if device is online."); // continue processing, so things can go to OFFLINE too } else { // response received, tread device as reachable, refresh state now @@ -160,7 +158,8 @@ private void startAutomaticRefresh(BsbLanBridgeConfiguration config) { // use a local variable to avoid the build warning "Potential null pointer access" ScheduledFuture localRefreshJob = refreshJob; if (localRefreshJob == null || localRefreshJob.isCancelled()) { - int interval = (config.refreshInterval != null) ? config.refreshInterval.intValue() : DEFAULT_REFRESH_INTERVAL; + int interval = (config.refreshInterval != null) ? config.refreshInterval.intValue() + : DEFAULT_REFRESH_INTERVAL; refreshJob = scheduler.scheduleWithFixedDelay(this::doRefresh, 0, interval, TimeUnit.SECONDS); } } diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanParameterHandler.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanParameterHandler.java index 9419a23246e55..833311464a915 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanParameterHandler.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/handler/BsbLanParameterHandler.java @@ -1,169 +1,172 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bsblan.internal.handler; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.Command; - -import org.openhab.binding.bsblan.internal.configuration.BsbLanBridgeConfiguration; -import org.openhab.binding.bsblan.internal.configuration.BsbLanParameterConfiguration; -import org.openhab.binding.bsblan.internal.api.BsbLanApiCaller; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterDTO; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterQueryResponseDTO; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO.Type; -import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; -import org.openhab.binding.bsblan.internal.helper.BsbLanParameterConverter; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link BsbLanParameterHandler} is responsible for updating the data, which are - * sent to one of the channels. - * - * @author Peter Schraffl - Initial contribution - */ -@NonNullByDefault -public class BsbLanParameterHandler extends BsbLanBaseThingHandler { - - private final Logger logger = LoggerFactory.getLogger(BsbLanParameterHandler.class); - private BsbLanParameterConfiguration parameterConfig = new BsbLanParameterConfiguration(); - - public BsbLanParameterHandler(Thing thing) { - super(thing); - } - - public Integer getParameterId() { - return parameterConfig.id; - } - - @Override - protected String getDescription() { - return "BSB-LAN Parameter"; - } - - @Override - public void refresh(BsbLanBridgeConfiguration bridgeConfiguration) { - updateChannels(); - } - - @Override - public void initialize() { - parameterConfig = getConfigAs(BsbLanParameterConfiguration.class); - super.initialize(); - - // validate 'setId' configuration -> fallback to value of 'id' if invalid or not specified - if (parameterConfig.setId == null || parameterConfig.setId <= 0) { - parameterConfig.setId = parameterConfig.id; - } - - // validate 'setType' configuration -> fallback to 'SET' if invalid or not specified - parameterConfig.setType = Type.getTypeWithFallback(parameterConfig.setType).toString(); - - // it will take up to refreshInterval seconds until we receive a value and thing goes online - // see notes in {@link BsbLanBridgeHandler#registerThing(BsbLanBaseThingHandler)} - updateStatus(ThingStatus.UNKNOWN); - } - - /** - * Update the channel from the last data retrieved - * - * @param channelId the id identifying the channel to be updated - */ - @Override - protected void updateChannel(String channelId) { - BsbLanApiParameterQueryResponseDTO data = null; - BsbLanBridgeHandler bridgeHandler = getBridgeHandler(); - if (bridgeHandler != null) { - data = bridgeHandler.getCachedParameterQueryResponse(); - } - updateChannel(channelId, data); - } - - private void updateChannel(String channelId, @Nullable BsbLanApiParameterQueryResponseDTO data) { - if (data == null) { - logger.debug("no data available while updating channel '{}' of parameter {}", channelId, parameterConfig.id); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE, - "No data received from BSB-LAN device"); - return; - } - - BsbLanApiParameterDTO parameter = data.getOrDefault(parameterConfig.id, null); - if (parameter == null) { - logger.debug("parameter {} is not part of response data while updating channel '{}' ", parameterConfig.id, channelId); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - String.format("No data received for parameter %s", parameterConfig.id)); - return; - } - - updateStatus(ThingStatus.ONLINE); - - if (!isLinked(channelId)) { - return; - } - - State state = BsbLanParameterConverter.getState(channelId, parameter); - if (state == null) { - return; - } - - updateState(channelId, state); - } - - /** - * Update the channel from the last data retrieved - * - * @param channelId the id identifying the channel to be updated - * @param command the value to be set - */ - @Override - protected void setChannel(String channelId, Command command) { - logger.trace("Received command '{}' for channel '{}'", command, channelId); - - if (!WRITEABLE_CHANNELS.contains(channelId)) { - logger.warn("Channel '{}' is read only. Ignoring command", channelId); - return; - } - - String value = BsbLanParameterConverter.getValue(channelId, command); - if (value == null) { - logger.warn("Channel '{}' is read only or conversion failed. Ignoring command", channelId); - return; - } - - BsbLanApiCaller api = getApiCaller(); - if (api == null) { - logger.debug("Failed to set parameter {} (API unavailable)", parameterConfig.setId); - return; - } - - boolean success = api.setParameter(parameterConfig.setId, value, Type.getTypeWithFallback(parameterConfig.setType)); - if (!success) { - logger.debug("Failed to set parameter {} to '{}' for channel '{}'", parameterConfig.setId, value, channelId); - } - - // refresh value - BsbLanApiParameterQueryResponseDTO queryResponse = api.queryParameter(parameterConfig.id); - if (queryResponse == null) { - logger.debug("Failed to refresh parameter {} after set request", parameterConfig.id); - return; - } - - updateChannel(channelId, queryResponse); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bsblan.internal.handler; + +import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.State; +import org.openhab.binding.bsblan.internal.api.BsbLanApiCaller; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterQueryResponseDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO.Type; +import org.openhab.binding.bsblan.internal.configuration.BsbLanBridgeConfiguration; +import org.openhab.binding.bsblan.internal.configuration.BsbLanParameterConfiguration; +import org.openhab.binding.bsblan.internal.helper.BsbLanParameterConverter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link BsbLanParameterHandler} is responsible for updating the data, which are + * sent to one of the channels. + * + * @author Peter Schraffl - Initial contribution + */ +@NonNullByDefault +public class BsbLanParameterHandler extends BsbLanBaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(BsbLanParameterHandler.class); + private BsbLanParameterConfiguration parameterConfig = new BsbLanParameterConfiguration(); + + public BsbLanParameterHandler(Thing thing) { + super(thing); + } + + public Integer getParameterId() { + return parameterConfig.id; + } + + @Override + protected String getDescription() { + return "BSB-LAN Parameter"; + } + + @Override + public void refresh(BsbLanBridgeConfiguration bridgeConfiguration) { + updateChannels(); + } + + @Override + public void initialize() { + parameterConfig = getConfigAs(BsbLanParameterConfiguration.class); + super.initialize(); + + // validate 'setId' configuration -> fallback to value of 'id' if invalid or not specified + if (parameterConfig.setId == null || parameterConfig.setId <= 0) { + parameterConfig.setId = parameterConfig.id; + } + + // validate 'setType' configuration -> fallback to 'SET' if invalid or not specified + parameterConfig.setType = Type.getTypeWithFallback(parameterConfig.setType).toString(); + + // it will take up to refreshInterval seconds until we receive a value and thing goes online + // see notes in {@link BsbLanBridgeHandler#registerThing(BsbLanBaseThingHandler)} + updateStatus(ThingStatus.UNKNOWN); + } + + /** + * Update the channel from the last data retrieved + * + * @param channelId the id identifying the channel to be updated + */ + @Override + protected void updateChannel(String channelId) { + BsbLanApiParameterQueryResponseDTO data = null; + BsbLanBridgeHandler bridgeHandler = getBridgeHandler(); + if (bridgeHandler != null) { + data = bridgeHandler.getCachedParameterQueryResponse(); + } + updateChannel(channelId, data); + } + + private void updateChannel(String channelId, @Nullable BsbLanApiParameterQueryResponseDTO data) { + if (data == null) { + logger.debug("no data available while updating channel '{}' of parameter {}", channelId, + parameterConfig.id); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE, + "No data received from BSB-LAN device"); + return; + } + + BsbLanApiParameterDTO parameter = data.getOrDefault(parameterConfig.id, null); + if (parameter == null) { + logger.debug("parameter {} is not part of response data while updating channel '{}' ", parameterConfig.id, + channelId); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + String.format("No data received for parameter %s", parameterConfig.id)); + return; + } + + updateStatus(ThingStatus.ONLINE); + + if (!isLinked(channelId)) { + return; + } + + State state = BsbLanParameterConverter.getState(channelId, parameter); + if (state == null) { + return; + } + + updateState(channelId, state); + } + + /** + * Update the channel from the last data retrieved + * + * @param channelId the id identifying the channel to be updated + * @param command the value to be set + */ + @Override + protected void setChannel(String channelId, Command command) { + logger.trace("Received command '{}' for channel '{}'", command, channelId); + + if (!WRITEABLE_CHANNELS.contains(channelId)) { + logger.warn("Channel '{}' is read only. Ignoring command", channelId); + return; + } + + String value = BsbLanParameterConverter.getValue(channelId, command); + if (value == null) { + logger.warn("Channel '{}' is read only or conversion failed. Ignoring command", channelId); + return; + } + + BsbLanApiCaller api = getApiCaller(); + if (api == null) { + logger.debug("Failed to set parameter {} (API unavailable)", parameterConfig.setId); + return; + } + + boolean success = api.setParameter(parameterConfig.setId, value, + Type.getTypeWithFallback(parameterConfig.setType)); + if (!success) { + logger.debug("Failed to set parameter {} to '{}' for channel '{}'", parameterConfig.setId, value, + channelId); + } + + // refresh value + BsbLanApiParameterQueryResponseDTO queryResponse = api.queryParameter(parameterConfig.id); + if (queryResponse == null) { + logger.debug("Failed to refresh parameter {} after set request", parameterConfig.id); + return; + } + + updateChannel(channelId, queryResponse); + } +} diff --git a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/helper/BsbLanParameterConverter.java b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/helper/BsbLanParameterConverter.java index 6fbc2d8ac97cb..39e09a48201c9 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/helper/BsbLanParameterConverter.java +++ b/bundles/org.openhab.binding.bsblan/src/main/java/org/openhab/binding/bsblan/internal/helper/BsbLanParameterConverter.java @@ -1,165 +1,163 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bsblan.internal.helper; - -import org.apache.commons.lang.StringEscapeUtils; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.State; - -import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterDTO; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link BsbLanParameterHandler} is responsible for updating the data, which are - * sent to one of the channels. - * - * @author Peter Schraffl - Initial contribution - */ -@NonNullByDefault -public class BsbLanParameterConverter { - - private static final Logger LOGGER = LoggerFactory.getLogger(BsbLanParameterConverter.class); - - public static @Nullable State getState(String channelId, BsbLanApiParameterDTO parameter) { - switch (channelId) { - case PARAMETER_CHANNEL_NAME: - return getStateForNameChannel(parameter); - - case PARAMETER_CHANNEL_DESCRIPTION: - return getStateForDescriptionChannel(parameter); - - case PARAMETER_CHANNEL_DATATYPE: - return getStateForDatatypeChannel(parameter); - - case PARAMETER_CHANNEL_NUMBER_VALUE: - return getStateForNumberValueChannel(parameter); - - case PARAMETER_CHANNEL_STRING_VALUE: - return getStateForStringValueChannel(parameter); - - case PARAMETER_CHANNEL_SWITCH_VALUE: - return getStateForSwitchValueChannel(parameter); - - case PARAMETER_CHANNEL_UNIT: - return getStateForUnitChannel(parameter); - } - - LOGGER.debug("unsupported channel '{}' while updating state", channelId); - return null; - } - - private static State getStateForNameChannel(BsbLanApiParameterDTO parameter) { - return new StringType(parameter.name); - } - - private static State getStateForDescriptionChannel(BsbLanApiParameterDTO parameter) { - return new StringType(parameter.description); - } - - private static State getStateForUnitChannel(BsbLanApiParameterDTO parameter) { - String value = StringEscapeUtils.unescapeHtml(parameter.unit); - return new StringType(value); - } - - private static State getStateForDatatypeChannel(BsbLanApiParameterDTO parameter) { - int value = parameter.dataType.getValue(); - return new DecimalType(value); - } - - private static @Nullable State getStateForNumberValueChannel(BsbLanApiParameterDTO parameter) { - try { - switch (parameter.dataType) { - // parse enum data type as integer - case DT_ENUM: - return new DecimalType(Integer.parseInt(parameter.value)); - - default: - return new DecimalType(Double.parseDouble(parameter.value)); - } - } - catch (NumberFormatException e) { - // silently ignore - there is not "tryParse" - } - return null; - } - - private static State getStateForStringValueChannel(BsbLanApiParameterDTO parameter) { - return new StringType(parameter.value); - } - - private static State getStateForSwitchValueChannel(BsbLanApiParameterDTO parameter) { - // treat "0" as OFF and everything else as ON - return parameter.value.equals("0") ? OnOffType.OFF : OnOffType.ON; - } - - /** - * Converts a Command back to a value which is sent to the BSB-LAN device afterwards. - * @param channelId - * @param command - * @return null if conversion fails or channel is readonly. - */ - public static @Nullable String getValue(String channelId, Command command) { - switch (channelId) { - case PARAMETER_CHANNEL_NUMBER_VALUE: - return getValueForNumberValueChannel(command); - - case PARAMETER_CHANNEL_STRING_VALUE: - return getValueForStringValueChannel(command); - - case PARAMETER_CHANNEL_SWITCH_VALUE: - return getValueForSwitchValueChannel(command); - - default: - LOGGER.debug("Channel '{}' is read only. Ignoring command", channelId); - return null; - } - } - - private static @Nullable String getValueForNumberValueChannel(Command command) { - // check if numeric - if (command.toString().matches("-?\\d+(\\.\\d+)?")) { - return command.toString(); - } - LOGGER.warn("Command '{}' is not a valid number value", command); - return null; - } - - private static String getValueForStringValueChannel(Command command) { - // special OnOffType handling - if (command.equals(OnOffType.ON)) { - return "1"; - } else if (command.equals(OnOffType.OFF)) { - return "0"; - } - return command.toString(); - } - - private static @Nullable String getValueForSwitchValueChannel(Command command) { - if (command.equals(OnOffType.ON)) { - return "1"; - } else if (command.equals(OnOffType.OFF)) { - return "0"; - } - LOGGER.warn("Command '{}' is not a valid switch value", command); - return null; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bsblan.internal.helper; + +import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; + +import org.apache.commons.lang.StringEscapeUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.State; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterDTO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link BsbLanParameterHandler} is responsible for updating the data, which are + * sent to one of the channels. + * + * @author Peter Schraffl - Initial contribution + */ +@NonNullByDefault +public class BsbLanParameterConverter { + + private static final Logger LOGGER = LoggerFactory.getLogger(BsbLanParameterConverter.class); + + public static @Nullable State getState(String channelId, BsbLanApiParameterDTO parameter) { + switch (channelId) { + case PARAMETER_CHANNEL_NAME: + return getStateForNameChannel(parameter); + + case PARAMETER_CHANNEL_DESCRIPTION: + return getStateForDescriptionChannel(parameter); + + case PARAMETER_CHANNEL_DATATYPE: + return getStateForDatatypeChannel(parameter); + + case PARAMETER_CHANNEL_NUMBER_VALUE: + return getStateForNumberValueChannel(parameter); + + case PARAMETER_CHANNEL_STRING_VALUE: + return getStateForStringValueChannel(parameter); + + case PARAMETER_CHANNEL_SWITCH_VALUE: + return getStateForSwitchValueChannel(parameter); + + case PARAMETER_CHANNEL_UNIT: + return getStateForUnitChannel(parameter); + } + + LOGGER.debug("unsupported channel '{}' while updating state", channelId); + return null; + } + + private static State getStateForNameChannel(BsbLanApiParameterDTO parameter) { + return new StringType(parameter.name); + } + + private static State getStateForDescriptionChannel(BsbLanApiParameterDTO parameter) { + return new StringType(parameter.description); + } + + private static State getStateForUnitChannel(BsbLanApiParameterDTO parameter) { + String value = StringEscapeUtils.unescapeHtml(parameter.unit); + return new StringType(value); + } + + private static State getStateForDatatypeChannel(BsbLanApiParameterDTO parameter) { + int value = parameter.dataType.getValue(); + return new DecimalType(value); + } + + private static @Nullable State getStateForNumberValueChannel(BsbLanApiParameterDTO parameter) { + try { + switch (parameter.dataType) { + // parse enum data type as integer + case DT_ENUM: + return new DecimalType(Integer.parseInt(parameter.value)); + + default: + return new DecimalType(Double.parseDouble(parameter.value)); + } + } catch (NumberFormatException e) { + // silently ignore - there is not "tryParse" + } + return null; + } + + private static State getStateForStringValueChannel(BsbLanApiParameterDTO parameter) { + return new StringType(parameter.value); + } + + private static State getStateForSwitchValueChannel(BsbLanApiParameterDTO parameter) { + // treat "0" as OFF and everything else as ON + return parameter.value.equals("0") ? OnOffType.OFF : OnOffType.ON; + } + + /** + * Converts a Command back to a value which is sent to the BSB-LAN device afterwards. + * + * @param channelId + * @param command + * @return null if conversion fails or channel is readonly. + */ + public static @Nullable String getValue(String channelId, Command command) { + switch (channelId) { + case PARAMETER_CHANNEL_NUMBER_VALUE: + return getValueForNumberValueChannel(command); + + case PARAMETER_CHANNEL_STRING_VALUE: + return getValueForStringValueChannel(command); + + case PARAMETER_CHANNEL_SWITCH_VALUE: + return getValueForSwitchValueChannel(command); + + default: + LOGGER.debug("Channel '{}' is read only. Ignoring command", channelId); + return null; + } + } + + private static @Nullable String getValueForNumberValueChannel(Command command) { + // check if numeric + if (command.toString().matches("-?\\d+(\\.\\d+)?")) { + return command.toString(); + } + LOGGER.warn("Command '{}' is not a valid number value", command); + return null; + } + + private static String getValueForStringValueChannel(Command command) { + // special OnOffType handling + if (command.equals(OnOffType.ON)) { + return "1"; + } else if (command.equals(OnOffType.OFF)) { + return "0"; + } + return command.toString(); + } + + private static @Nullable String getValueForSwitchValueChannel(Command command) { + if (command.equals(OnOffType.ON)) { + return "1"; + } else if (command.equals(OnOffType.OFF)) { + return "0"; + } + LOGGER.warn("Command '{}' is not a valid switch value", command); + return null; + } +} diff --git a/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/binding/binding.xml index 22ef6d080f44e..e6027d385e254 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + BSB-LAN Binding Binding for BSB-LAN Gateway. diff --git a/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/thing/bridge.xml index 15864e1e729b7..81583d1f8bab7 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/thing/thing-types.xml index 9f9586c095fea..9703981f69533 100644 --- a/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.bsblan/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,24 +1,25 @@ - - + Represents a single parameter available at the BSB-LAN device and identified by a numeric id. - - - - - - - + + + + + + + @@ -62,7 +63,7 @@ Value of the parameter - + Switch Value of the parameter diff --git a/bundles/org.openhab.binding.bsblan/src/test/java/org/openhab/binding/bsblan/internal/api/BsbLanApiContentConverterTests.java b/bundles/org.openhab.binding.bsblan/src/test/java/org/openhab/binding/bsblan/internal/api/BsbLanApiContentConverterTests.java index db18998f3568e..b9900cba5e144 100644 --- a/bundles/org.openhab.binding.bsblan/src/test/java/org/openhab/binding/bsblan/internal/api/BsbLanApiContentConverterTests.java +++ b/bundles/org.openhab.binding.bsblan/src/test/java/org/openhab/binding/bsblan/internal/api/BsbLanApiContentConverterTests.java @@ -1,87 +1,80 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bsblan.internal.api; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.junit.Test; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterQueryResponseDTO; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO.Type; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterDTO; - -import com.google.gson.JsonParser; -import com.google.gson.JsonObject; - -/** - * The {@link BsbLanApiContentConverterTests} class implements tests - * for {@link BsbLanApiContentConverter}. - * - * @author Peter Schraffl - Initial contribution - */ -@NonNullByDefault -public class BsbLanApiContentConverterTests { - - @Test - public void parseBsbLanApiParameterQueryResponse() { - String content = - "{\r\n" + - "\"700\": {\r\n" + - "\"name\": \"Betriebsart\",\r\n" + - "\"value\": \"0\",\r\n" + - "\"unit\": \"\",\r\n" + - "\"desc\": \"Schutzbetrieb\",\r\n" + - "\"dataType\": 1\r\n" + - "}\r\n" + - "}"; - - BsbLanApiParameterQueryResponseDTO r = BsbLanApiContentConverter.fromJson(content, BsbLanApiParameterQueryResponseDTO.class); - assertNotNull(r); - assertTrue(r.containsKey(700)); - - BsbLanApiParameterDTO p = r.get(700); - assertEquals("Betriebsart", p.name); - assertEquals("0", p.value); - assertEquals("", p.unit); - assertEquals("Schutzbetrieb", p.description); - assertEquals(BsbLanApiParameterDTO .DataType.DT_ENUM, p.dataType); - } - - @Test - public void serializeBsbLanApiParameterSetRequest() { - BsbLanApiParameterSetRequestDTO request = new BsbLanApiParameterSetRequestDTO(); - request.parameter = "1234"; - request.value = "Hello World"; - request.type = Type.SET; - - String serializedRequest = BsbLanApiContentConverter.toJson(request); - - // verify serialized content - JsonParser parser = new JsonParser(); - JsonObject json = parser.parse(serializedRequest).getAsJsonObject(); - - // Although specifying the parameter as int (which would be nicer) also seems to work, - // we use a String here as this is the way it is noted in the documentation. - // So ensure there is a 'Parameter' and it is serialized as string. - assertEquals("1234", json.get("Parameter").getAsString()); - - // ensure there is a 'Value' and it is serialized as string - assertEquals("Hello World", json.get("Value").getAsString()); - - // ensure there is a 'Type' and it is serialized as number - assertEquals(1, json.get("Type").getAsInt()); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bsblan.internal.api; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Test; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterQueryResponseDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterSetRequestDTO.Type; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * The {@link BsbLanApiContentConverterTests} class implements tests + * for {@link BsbLanApiContentConverter}. + * + * @author Peter Schraffl - Initial contribution + */ +@NonNullByDefault +public class BsbLanApiContentConverterTests { + + @Test + public void parseBsbLanApiParameterQueryResponse() { + String content = "{\r\n" + "\"700\": {\r\n" + "\"name\": \"Betriebsart\",\r\n" + "\"value\": \"0\",\r\n" + + "\"unit\": \"\",\r\n" + "\"desc\": \"Schutzbetrieb\",\r\n" + "\"dataType\": 1\r\n" + "}\r\n" + "}"; + + BsbLanApiParameterQueryResponseDTO r = BsbLanApiContentConverter.fromJson(content, + BsbLanApiParameterQueryResponseDTO.class); + assertNotNull(r); + assertTrue(r.containsKey(700)); + + BsbLanApiParameterDTO p = r.get(700); + assertEquals("Betriebsart", p.name); + assertEquals("0", p.value); + assertEquals("", p.unit); + assertEquals("Schutzbetrieb", p.description); + assertEquals(BsbLanApiParameterDTO.DataType.DT_ENUM, p.dataType); + } + + @Test + public void serializeBsbLanApiParameterSetRequest() { + BsbLanApiParameterSetRequestDTO request = new BsbLanApiParameterSetRequestDTO(); + request.parameter = "1234"; + request.value = "Hello World"; + request.type = Type.SET; + + String serializedRequest = BsbLanApiContentConverter.toJson(request); + + // verify serialized content + JsonParser parser = new JsonParser(); + JsonObject json = parser.parse(serializedRequest).getAsJsonObject(); + + // Although specifying the parameter as int (which would be nicer) also seems to work, + // we use a String here as this is the way it is noted in the documentation. + // So ensure there is a 'Parameter' and it is serialized as string. + assertEquals("1234", json.get("Parameter").getAsString()); + + // ensure there is a 'Value' and it is serialized as string + assertEquals("Hello World", json.get("Value").getAsString()); + + // ensure there is a 'Type' and it is serialized as number + assertEquals(1, json.get("Type").getAsInt()); + } +} diff --git a/bundles/org.openhab.binding.bsblan/src/test/java/org/openhab/binding/bsblan/internal/helper/BsbLanParameterConverterTests.java b/bundles/org.openhab.binding.bsblan/src/test/java/org/openhab/binding/bsblan/internal/helper/BsbLanParameterConverterTests.java index 95acd9103dd90..2feeb8e1600db 100644 --- a/bundles/org.openhab.binding.bsblan/src/test/java/org/openhab/binding/bsblan/internal/helper/BsbLanParameterConverterTests.java +++ b/bundles/org.openhab.binding.bsblan/src/test/java/org/openhab/binding/bsblan/internal/helper/BsbLanParameterConverterTests.java @@ -1,253 +1,254 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.bsblan.internal.helper; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; - -import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; -import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterDTO; - -import org.junit.Test; - -/** - * The {@link BsbLanParameterConverterTests} class implements tests - * for {@link BsbLanParameterConverter}. - * - * @author Peter Schraffl - Initial contribution - */ -@NonNullByDefault -public class BsbLanParameterConverterTests { - - @Test - public void testGetStatesForStringParameter() { - BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); - parameter.dataType = BsbLanApiParameterDTO.DataType.DT_STRN; - parameter.description = "Test-Description"; - parameter.name = "Test-Name"; - parameter.unit = "Test-Unit"; - parameter.value = "Test-Value"; - - State state = null; - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DATATYPE, parameter); - assertNotNull(state); - assertEquals(new DecimalType(BsbLanApiParameterDTO.DataType.DT_STRN.getValue()), state.as(DecimalType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DESCRIPTION, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Description"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NAME, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Name"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Unit"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NUMBER_VALUE, parameter); - assertNull(state); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_STRING_VALUE, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Value"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_SWITCH_VALUE, parameter); - assertNotNull(state); - assertEquals(OnOffType.ON, state); - } - - @Test - public void testGetStatesForEnumParameterValue1() { - BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); - parameter.dataType = BsbLanApiParameterDTO.DataType.DT_ENUM; - parameter.description = "Test-Description"; - parameter.name = "Test-Name"; - parameter.unit = "Test-Unit"; - parameter.value = "1"; - - State state = null; - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DATATYPE, parameter); - assertNotNull(state); - assertEquals(new DecimalType(BsbLanApiParameterDTO.DataType.DT_ENUM.getValue()), state.as(DecimalType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DESCRIPTION, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Description"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NAME, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Name"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Unit"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NUMBER_VALUE, parameter); - assertNotNull(state); - assertEquals(new DecimalType(1), state.as(DecimalType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_STRING_VALUE, parameter); - assertNotNull(state); - assertEquals(new StringType("1"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_SWITCH_VALUE, parameter); - assertNotNull(state); - assertEquals(OnOffType.ON, state); - } - - @Test - public void testGetStatesForEnumParameterValue0() { - BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); - parameter.dataType = BsbLanApiParameterDTO.DataType.DT_ENUM; - parameter.description = "Test-Description"; - parameter.name = "Test-Name"; - parameter.unit = "Test-Unit"; - parameter.value = "0"; - - State state = null; - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DATATYPE, parameter); - assertNotNull(state); - assertEquals(new DecimalType(BsbLanApiParameterDTO.DataType.DT_ENUM.getValue()), state.as(DecimalType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DESCRIPTION, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Description"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NAME, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Name"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Unit"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NUMBER_VALUE, parameter); - assertNotNull(state); - assertEquals(new DecimalType(0), state.as(DecimalType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_STRING_VALUE, parameter); - assertNotNull(state); - assertEquals(new StringType("0"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_SWITCH_VALUE, parameter); - assertNotNull(state); - assertEquals(OnOffType.OFF, state); - } - - @Test - public void testGetStatesForValueParameterValue() { - BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); - parameter.dataType = BsbLanApiParameterDTO.DataType.DT_VALS; - parameter.description = "Test-Description"; - parameter.name = "Test-Name"; - parameter.unit = "Test-Unit"; - parameter.value = "22.5"; - - State state = null; - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DATATYPE, parameter); - assertNotNull(state); - assertEquals(new DecimalType(BsbLanApiParameterDTO.DataType.DT_VALS.getValue()), state.as(DecimalType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DESCRIPTION, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Description"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NAME, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Name"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); - assertNotNull(state); - assertEquals(new StringType("Test-Unit"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NUMBER_VALUE, parameter); - assertNotNull(state); - assertEquals(new DecimalType(22.5), state.as(DecimalType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_STRING_VALUE, parameter); - assertNotNull(state); - assertEquals(new StringType("22.5"), state.as(StringType.class)); - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_SWITCH_VALUE, parameter); - assertNotNull(state); - assertEquals(OnOffType.ON, state); - } - - @Test - public void testGetStatesEscapesHtml() { - BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); - parameter.dataType = BsbLanApiParameterDTO.DataType.DT_VALS; - parameter.description = "Test-Description"; - parameter.name = "Test-Name"; - parameter.unit = "°C"; - parameter.value = "22.5"; - - State state = null; - - state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); - assertNotNull(state); - assertEquals(new StringType("°C"), state.as(StringType.class)); - } - - @Test - public void testGetValueForReadonlyChannels() { - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_DATATYPE, OnOffType.ON)); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_DESCRIPTION, OnOffType.ON)); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NAME, OnOffType.ON)); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_UNIT, OnOffType.ON)); - } - - @Test - public void testGetValueForNumberValueChannel() { - assertNull("1", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, OnOffType.ON)); - assertNull("0", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, OnOffType.OFF)); - assertEquals("42", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, new DecimalType(42))); - assertEquals("22.5", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, new DecimalType(22.5))); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, new StringType("Not a number value"))); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, new StringType(""))); - } - - @Test - public void testGetValueForSwitchValueChannel() { - assertEquals("1", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, OnOffType.ON)); - assertEquals("0", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, OnOffType.OFF)); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new DecimalType(1))); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new DecimalType(0))); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new DecimalType(42))); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new DecimalType(22.5))); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new StringType("Not a number value"))); - assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new StringType(""))); - } - - @Test - public void testGetValueForStringValueChannel() { - assertEquals("1", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, OnOffType.ON)); - assertEquals("0", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, OnOffType.OFF)); - assertEquals("42", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, new DecimalType(42))); - assertEquals("22.5", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, new DecimalType(22.5))); - assertEquals("A string value", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, new StringType("A string value"))); - assertEquals("", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, new StringType(""))); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.bsblan.internal.helper; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.openhab.binding.bsblan.internal.BsbLanBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.types.State; +import org.junit.Test; +import org.openhab.binding.bsblan.internal.api.dto.BsbLanApiParameterDTO; + +/** + * The {@link BsbLanParameterConverterTests} class implements tests + * for {@link BsbLanParameterConverter}. + * + * @author Peter Schraffl - Initial contribution + */ +@NonNullByDefault +public class BsbLanParameterConverterTests { + + @Test + public void testGetStatesForStringParameter() { + BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); + parameter.dataType = BsbLanApiParameterDTO.DataType.DT_STRN; + parameter.description = "Test-Description"; + parameter.name = "Test-Name"; + parameter.unit = "Test-Unit"; + parameter.value = "Test-Value"; + + State state = null; + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DATATYPE, parameter); + assertNotNull(state); + assertEquals(new DecimalType(BsbLanApiParameterDTO.DataType.DT_STRN.getValue()), state.as(DecimalType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DESCRIPTION, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Description"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NAME, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Name"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Unit"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NUMBER_VALUE, parameter); + assertNull(state); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_STRING_VALUE, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Value"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_SWITCH_VALUE, parameter); + assertNotNull(state); + assertEquals(OnOffType.ON, state); + } + + @Test + public void testGetStatesForEnumParameterValue1() { + BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); + parameter.dataType = BsbLanApiParameterDTO.DataType.DT_ENUM; + parameter.description = "Test-Description"; + parameter.name = "Test-Name"; + parameter.unit = "Test-Unit"; + parameter.value = "1"; + + State state = null; + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DATATYPE, parameter); + assertNotNull(state); + assertEquals(new DecimalType(BsbLanApiParameterDTO.DataType.DT_ENUM.getValue()), state.as(DecimalType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DESCRIPTION, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Description"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NAME, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Name"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Unit"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NUMBER_VALUE, parameter); + assertNotNull(state); + assertEquals(new DecimalType(1), state.as(DecimalType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_STRING_VALUE, parameter); + assertNotNull(state); + assertEquals(new StringType("1"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_SWITCH_VALUE, parameter); + assertNotNull(state); + assertEquals(OnOffType.ON, state); + } + + @Test + public void testGetStatesForEnumParameterValue0() { + BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); + parameter.dataType = BsbLanApiParameterDTO.DataType.DT_ENUM; + parameter.description = "Test-Description"; + parameter.name = "Test-Name"; + parameter.unit = "Test-Unit"; + parameter.value = "0"; + + State state = null; + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DATATYPE, parameter); + assertNotNull(state); + assertEquals(new DecimalType(BsbLanApiParameterDTO.DataType.DT_ENUM.getValue()), state.as(DecimalType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DESCRIPTION, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Description"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NAME, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Name"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Unit"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NUMBER_VALUE, parameter); + assertNotNull(state); + assertEquals(new DecimalType(0), state.as(DecimalType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_STRING_VALUE, parameter); + assertNotNull(state); + assertEquals(new StringType("0"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_SWITCH_VALUE, parameter); + assertNotNull(state); + assertEquals(OnOffType.OFF, state); + } + + @Test + public void testGetStatesForValueParameterValue() { + BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); + parameter.dataType = BsbLanApiParameterDTO.DataType.DT_VALS; + parameter.description = "Test-Description"; + parameter.name = "Test-Name"; + parameter.unit = "Test-Unit"; + parameter.value = "22.5"; + + State state = null; + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DATATYPE, parameter); + assertNotNull(state); + assertEquals(new DecimalType(BsbLanApiParameterDTO.DataType.DT_VALS.getValue()), state.as(DecimalType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_DESCRIPTION, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Description"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NAME, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Name"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); + assertNotNull(state); + assertEquals(new StringType("Test-Unit"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_NUMBER_VALUE, parameter); + assertNotNull(state); + assertEquals(new DecimalType(22.5), state.as(DecimalType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_STRING_VALUE, parameter); + assertNotNull(state); + assertEquals(new StringType("22.5"), state.as(StringType.class)); + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_SWITCH_VALUE, parameter); + assertNotNull(state); + assertEquals(OnOffType.ON, state); + } + + @Test + public void testGetStatesEscapesHtml() { + BsbLanApiParameterDTO parameter = new BsbLanApiParameterDTO(); + parameter.dataType = BsbLanApiParameterDTO.DataType.DT_VALS; + parameter.description = "Test-Description"; + parameter.name = "Test-Name"; + parameter.unit = "°C"; + parameter.value = "22.5"; + + State state = null; + + state = BsbLanParameterConverter.getState(PARAMETER_CHANNEL_UNIT, parameter); + assertNotNull(state); + assertEquals(new StringType("°C"), state.as(StringType.class)); + } + + @Test + public void testGetValueForReadonlyChannels() { + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_DATATYPE, OnOffType.ON)); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_DESCRIPTION, OnOffType.ON)); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NAME, OnOffType.ON)); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_UNIT, OnOffType.ON)); + } + + @Test + public void testGetValueForNumberValueChannel() { + assertNull("1", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, OnOffType.ON)); + assertNull("0", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, OnOffType.OFF)); + assertEquals("42", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, new DecimalType(42))); + assertEquals("22.5", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, new DecimalType(22.5))); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, + new StringType("Not a number value"))); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_NUMBER_VALUE, new StringType(""))); + } + + @Test + public void testGetValueForSwitchValueChannel() { + assertEquals("1", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, OnOffType.ON)); + assertEquals("0", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, OnOffType.OFF)); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new DecimalType(1))); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new DecimalType(0))); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new DecimalType(42))); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new DecimalType(22.5))); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, + new StringType("Not a number value"))); + assertNull(BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_SWITCH_VALUE, new StringType(""))); + } + + @Test + public void testGetValueForStringValueChannel() { + assertEquals("1", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, OnOffType.ON)); + assertEquals("0", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, OnOffType.OFF)); + assertEquals("42", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, new DecimalType(42))); + assertEquals("22.5", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, new DecimalType(22.5))); + assertEquals("A string value", + BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, new StringType("A string value"))); + assertEquals("", BsbLanParameterConverter.getValue(PARAMETER_CHANNEL_STRING_VALUE, new StringType(""))); + } +} diff --git a/bundles/org.openhab.binding.buienradar/pom.xml b/bundles/org.openhab.binding.buienradar/pom.xml index 79f93e23cd49f..427563120fffc 100644 --- a/bundles/org.openhab.binding.buienradar/pom.xml +++ b/bundles/org.openhab.binding.buienradar/pom.xml @@ -1,9 +1,11 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.buienradar openHAB Add-ons :: Bundles :: Buienradar Binding diff --git a/bundles/org.openhab.binding.buienradar/src/main/feature/feature.xml b/bundles/org.openhab.binding.buienradar/src/main/feature/feature.xml index a5ecbeaf6b236..1519b57efc09d 100644 --- a/bundles/org.openhab.binding.buienradar/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.buienradar/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.buienradar/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.buienradar/${project.version} + diff --git a/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/BuienradarBindingConstants.java b/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/BuienradarBindingConstants.java index 445ed12743ef0..410d76415f447 100644 --- a/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/BuienradarBindingConstants.java +++ b/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/BuienradarBindingConstants.java @@ -54,5 +54,4 @@ public class BuienradarBindingConstants { public static final String FORECAST_105 = "forecast_105"; public static final String FORECAST_110 = "forecast_110"; public static final String FORECAST_115 = "forecast_115"; - } diff --git a/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/buienradarapi/BuienradarParseException.java b/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/buienradarapi/BuienradarParseException.java index a04bd7f5e53b6..9a1ca66316874 100644 --- a/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/buienradarapi/BuienradarParseException.java +++ b/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/buienradarapi/BuienradarParseException.java @@ -44,5 +44,4 @@ public BuienradarParseException(String message, Throwable cause, boolean enableS boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } - } diff --git a/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/buienradarapi/BuienradarPredictionAPI.java b/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/buienradarapi/BuienradarPredictionAPI.java index d7be1ae52a2bd..e617ce704daa6 100644 --- a/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/buienradarapi/BuienradarPredictionAPI.java +++ b/bundles/org.openhab.binding.buienradar/src/main/java/org/openhab/binding/buienradar/internal/buienradarapi/BuienradarPredictionAPI.java @@ -170,5 +170,4 @@ public Optional> getPredictions(PointType location) throws IOEx } return Optional.of(predictions); } - } diff --git a/bundles/org.openhab.binding.buienradar/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.buienradar/src/main/resources/ESH-INF/binding/binding.xml index 7467ff2d25851..b47a3cd2868db 100644 --- a/bundles/org.openhab.binding.buienradar/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.buienradar/src/main/resources/ESH-INF/binding/binding.xml @@ -4,7 +4,8 @@ xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd"> Buienradar Binding - The Buienradar Binding periodically (5 minutes) retrieves results from the Buienradar API. For personal use only. + The Buienradar Binding periodically (5 minutes) retrieves results from the Buienradar API. For personal + use only. Edwin de Jong diff --git a/bundles/org.openhab.binding.buienradar/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.buienradar/src/main/resources/ESH-INF/thing/thing-types.xml index 9331977e8d02b..1f869648c0ed3 100644 --- a/bundles/org.openhab.binding.buienradar/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.buienradar/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,34 +7,36 @@ Does a simple rain forecast at the specified longitude/latitude of - two hours, in 5 minute increments using the buienradar.nl webservice. + two hours, in 5 minute increments using + the buienradar.nl webservice. + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -59,7 +61,8 @@ - Exponential back-off base value for retries in seconds. For example, when this is 2 seconds, will retry at 2, 4, 8, 16, 32, 64 seconds. + Exponential back-off base value for retries in seconds. For example, when this is 2 seconds, will retry + at 2, 4, 8, 16, 32, 64 seconds. 5 @@ -70,175 +73,175 @@ DateTime The actual date and time when the prediction was made." - + Number:Speed Current rainfall - + Number:Speed Rainfall in 5 minutes - + Number:Speed Rainfall in 10 minutes - + Number:Speed Rainfall in 15 minutes - + Number:Speed Rainfall in 20 minutes - + Number:Speed Rainfall in 25 minutes - + Number:Speed Rainfall in 30 minutes - + Number:Speed Rainfall in 35 minutes - + Number:Speed Rainfall in 40 minutes - + Number:Speed Rainfall in 45 minutes - + Number:Speed Rainfall in 50 minutes - + Number:Speed Rainfall in 55 minutes - + Number:Speed Rainfall in 60 minutes - + Number:Speed Rainfall in 65 minutes - + Number:Speed Rainfall in 70 minutes - + Number:Speed Rainfall in 75 minutes - + Number:Speed Rainfall in 80 minutes - + Number:Speed Rainfall in 85 minutes - + Number:Speed Rainfall in 90 minutes - + Number:Speed Rainfall in 95 minutes - + Number:Speed Rainfall in 100 minutes - + Number:Speed Rainfall in 105 minutes - + Number:Speed Rainfall in 110 minutes - + Number:Speed Rainfall in 115 minutes - + diff --git a/bundles/org.openhab.binding.buienradar/src/test/java/org/openhab/binding/buienradar/BuienradarPredictionAPITest.java b/bundles/org.openhab.binding.buienradar/src/test/java/org/openhab/binding/buienradar/BuienradarPredictionAPITest.java index 5ccec06efbf87..a336b1a33c337 100644 --- a/bundles/org.openhab.binding.buienradar/src/test/java/org/openhab/binding/buienradar/BuienradarPredictionAPITest.java +++ b/bundles/org.openhab.binding.buienradar/src/test/java/org/openhab/binding/buienradar/BuienradarPredictionAPITest.java @@ -85,5 +85,4 @@ public void testParseLine() throws BuienradarParseException { parsed.getDateTimeOfPrediction()); assertEquals(BigDecimal.valueOf(0, 2), parsed.getIntensity()); } - } diff --git a/bundles/org.openhab.binding.cbus/pom.xml b/bundles/org.openhab.binding.cbus/pom.xml index 4e0878d052feb..4614d6ee86629 100644 --- a/bundles/org.openhab.binding.cbus/pom.xml +++ b/bundles/org.openhab.binding.cbus/pom.xml @@ -1,4 +1,6 @@ - + + 4.0.0 @@ -6,7 +8,7 @@ org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.cbus diff --git a/bundles/org.openhab.binding.cbus/src/main/java/org/openhab/binding/cbus/internal/discovery/CBusNetworkDiscovery.java b/bundles/org.openhab.binding.cbus/src/main/java/org/openhab/binding/cbus/internal/discovery/CBusNetworkDiscovery.java index d6b6aac8ef8c4..604648849a9cd 100644 --- a/bundles/org.openhab.binding.cbus/src/main/java/org/openhab/binding/cbus/internal/discovery/CBusNetworkDiscovery.java +++ b/bundles/org.openhab.binding.cbus/src/main/java/org/openhab/binding/cbus/internal/discovery/CBusNetworkDiscovery.java @@ -79,5 +79,4 @@ protected synchronized void stopScan() { super.stopScan(); removeOlderResults(getTimestampOfLastScan()); } - } diff --git a/bundles/org.openhab.binding.cbus/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.cbus/src/main/resources/ESH-INF/thing/thing-types.xml index 68f1dbfe07d01..bf223c1f1de09 100644 --- a/bundles/org.openhab.binding.cbus/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.cbus/src/main/resources/ESH-INF/thing/thing-types.xml @@ -6,19 +6,19 @@ - + Lighting Group - - + + - - - + + + @@ -31,18 +31,18 @@ - + Temperature Group - + - - - + + + @@ -55,18 +55,18 @@ - + Trigger Group - + - - - + + + @@ -79,18 +79,18 @@ - + DALI Group - + - - - + + + @@ -122,7 +122,7 @@ Group channel for CBus temperature groups Temperature - + diff --git a/bundles/org.openhab.binding.chromecast/pom.xml b/bundles/org.openhab.binding.chromecast/pom.xml index efa98d8c26873..746c6d0c57f3e 100644 --- a/bundles/org.openhab.binding.chromecast/pom.xml +++ b/bundles/org.openhab.binding.chromecast/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.chromecast diff --git a/bundles/org.openhab.binding.chromecast/src/main/java/org/openhab/binding/chromecast/internal/factory/ChromecastHandlerFactory.java b/bundles/org.openhab.binding.chromecast/src/main/java/org/openhab/binding/chromecast/internal/factory/ChromecastHandlerFactory.java index e5412bb67fc94..67eef1437bbe4 100644 --- a/bundles/org.openhab.binding.chromecast/src/main/java/org/openhab/binding/chromecast/internal/factory/ChromecastHandlerFactory.java +++ b/bundles/org.openhab.binding.chromecast/src/main/java/org/openhab/binding/chromecast/internal/factory/ChromecastHandlerFactory.java @@ -114,5 +114,4 @@ public void unregisterHandler(Thing thing) { ServiceRegistration reg = audioSinkRegistrations.get(thing.getUID().toString()); reg.unregister(); } - } diff --git a/bundles/org.openhab.binding.chromecast/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.chromecast/src/main/resources/ESH-INF/thing/thing-types.xml index fb72781df70d1..0c3de8ed9def9 100644 --- a/bundles/org.openhab.binding.chromecast/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.chromecast/src/main/resources/ESH-INF/thing/thing-types.xml @@ -10,48 +10,48 @@ A Google Chromecast Audio Group device - - - - - + + + + + - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + deviceId - + @@ -60,48 +60,48 @@ A Google Chromecast Audio device - - - - - + + + + + - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + deviceId - + @@ -110,48 +110,48 @@ A Google Chromecast streaming device - - - - - + + + + + - - - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + deviceId - + @@ -171,28 +171,28 @@ Switch Is Chromecast active or idling - + String Name of the currently running application - + String Id of the currently running application - + String Status reported by the current application - + @@ -200,14 +200,14 @@ Number:Time Current time of currently playing media - + Number:Time Length of currently playing media - + @@ -217,11 +217,11 @@ The type of the currently playing media. One of GENERIC, MOVIE, TV_SHOW, AUDIO_TRACK, PHOTO - @@ -230,111 +230,111 @@ String The name of the album's artist - + String The name of the album - + DateTime The broadcast date of the currently playing media - + String The composer of the current track - + DateTime The creation date of the currently playing media - + Number The disc number of the currently playing media - + Number The episode number of the currently playing media - + String The image URL that represents this media. Normally cover-art or scene from a movie - + Image The image that represents this media. Normally cover-art or scene from a movie - + String The location of where the current media was taken - + DateTime The release date of the currently playing media - + Number The season number of the currently playing media - + String The series title of the currently playing media - + String The studio of the currently playing media - + String The subtitle of the currently playing media - + Number The track number of the currently playing media - + diff --git a/bundles/org.openhab.binding.cm11a/pom.xml b/bundles/org.openhab.binding.cm11a/pom.xml index 66ea0619cf3ee..ff59eb2aa57a9 100644 --- a/bundles/org.openhab.binding.cm11a/pom.xml +++ b/bundles/org.openhab.binding.cm11a/pom.xml @@ -1,15 +1,21 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.cm11a openHAB Add-ons :: Bundles :: CM11A Binding + + gnu.io;version="[3.12,6)" + + diff --git a/bundles/org.openhab.binding.cm11a/src/main/feature/feature.xml b/bundles/org.openhab.binding.cm11a/src/main/feature/feature.xml index 18a0f4dcce5ad..b26bb9d5e77c9 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.cm11a/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.cm11a/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.cm11a/${project.version} + diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/CM11ABindingConstants.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/CM11ABindingConstants.java index 80a5a72e87108..50b81cbb9f88e 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/CM11ABindingConstants.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/CM11ABindingConstants.java @@ -42,5 +42,4 @@ public class CM11ABindingConstants { */ public static final String CHANNEL_LIGHTLEVEL = "lightlevel"; public static final String CHANNEL_SWITCH = "switchstatus"; - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/InvalidAddressException.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/InvalidAddressException.java index 1232884e13cce..cd63d62ce7ede 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/InvalidAddressException.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/InvalidAddressException.java @@ -24,5 +24,4 @@ public class InvalidAddressException extends Exception { public InvalidAddressException(String string) { super(string); } - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/X10Interface.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/X10Interface.java index 9560b33f3c585..9d05e785dc4ac 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/X10Interface.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/X10Interface.java @@ -805,5 +805,4 @@ public void disconnect() { serialPort.close(); } } - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/X10ReceivedData.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/X10ReceivedData.java index d3e271cc22ced..f02f14875e8b6 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/X10ReceivedData.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/X10ReceivedData.java @@ -150,5 +150,4 @@ public boolean equals(Object obj) { } return true; } - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/config/Cm11aConfig.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/config/Cm11aConfig.java index d7dacf5e2751c..ffea1578bac42 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/config/Cm11aConfig.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/config/Cm11aConfig.java @@ -29,5 +29,4 @@ public class Cm11aConfig { * refresh rate - I don't think we will need this */ public int refresh = 60; - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aAbstractHandler.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aAbstractHandler.java index 32089eb176e97..30a53fc0b95a7 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aAbstractHandler.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aAbstractHandler.java @@ -180,5 +180,4 @@ public State addDimsToCurrentState(int dims) { public State addBrightsToCurrentState(int dims) { return addDimsToCurrentState(-dims); } - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aApplianceHandler.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aApplianceHandler.java index c85cd19f54e45..1700a447d0cad 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aApplianceHandler.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aApplianceHandler.java @@ -93,5 +93,4 @@ public void updateHardware(X10Interface x10Interface) throws IOException, Invali } } } - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aLampHandler.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aLampHandler.java index d168f1bc8bd1f..e797f302e0946 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aLampHandler.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/Cm11aLampHandler.java @@ -149,5 +149,4 @@ public void updateHardware(X10Interface x10Interface) throws IOException, Invali } } } - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/ReceivedDataListener.java b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/ReceivedDataListener.java index e09e79e591a2e..bc24c54d00792 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/ReceivedDataListener.java +++ b/bundles/org.openhab.binding.cm11a/src/main/java/org/openhab/binding/cm11a/internal/handler/ReceivedDataListener.java @@ -29,5 +29,4 @@ public interface ReceivedDataListener { * @param rd */ void receivedX10Data(X10ReceivedData rd); - } diff --git a/bundles/org.openhab.binding.cm11a/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.cm11a/src/main/resources/ESH-INF/binding/binding.xml index 1d26560603b00..de1c05eeec675 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.cm11a/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + CM11A Binding This is the binding for the X10 Cm11a interface diff --git a/bundles/org.openhab.binding.cm11a/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.cm11a/src/main/resources/ESH-INF/thing/thing-types.xml index 99a27a40b31ee..33ed5062077a5 100644 --- a/bundles/org.openhab.binding.cm11a/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.cm11a/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -10,9 +10,10 @@ CM11 is a device that allows control of X10 devices for a computer. - + serial-port + false Serial port used to communicate with the CM11a diff --git a/bundles/org.openhab.binding.coolmasternet/pom.xml b/bundles/org.openhab.binding.coolmasternet/pom.xml index d5873298b7c90..1fe607ded4597 100644 --- a/bundles/org.openhab.binding.coolmasternet/pom.xml +++ b/bundles/org.openhab.binding.coolmasternet/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.coolmasternet diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/feature/feature.xml b/bundles/org.openhab.binding.coolmasternet/src/main/feature/feature.xml index 419f735e4e4ab..053ffbed4ce91 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.coolmasternet/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.coolmasternet/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.coolmasternet/${project.version} + diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/ControllerHandler.java b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/ControllerHandler.java index f92c4239353b0..e39096a16a3b8 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/ControllerHandler.java +++ b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/ControllerHandler.java @@ -12,23 +12,27 @@ */ package org.openhab.binding.coolmasternet.internal; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.util.concurrent.TimeUnit.SECONDS; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.Reader; +import java.io.Writer; import java.net.InetSocketAddress; import java.net.Socket; -import java.net.SocketException; import java.net.SocketTimeoutException; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; + +import javax.measure.Unit; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.unit.ImperialUnits; +import org.eclipse.smarthome.core.library.unit.SIUnits; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; @@ -44,232 +48,326 @@ /** * Bridge to access a CoolMasterNet unit's ASCII protocol via TCP socket. * - * A single CoolMasterNet can be connected to one or more HVAC units, each with a unique UID. - * These are individual Things inside the bridge. + *

+ * A single CoolMasterNet can be connected to one or more HVAC units, each with + * a unique UID. Each HVAC is an individual thing inside the bridge. * * @author Angus Gratton - Initial contribution * @author Wouter Born - Fix null pointer exceptions and stop refresh job on update/dispose */ @NonNullByDefault -public class ControllerHandler extends BaseBridgeHandler { - private static final int SOCKET_TIMEOUT = 2000; +public final class ControllerHandler extends BaseBridgeHandler { + private static final String LF = "\n"; + private static final byte PROMPT = ">".getBytes(US_ASCII)[0]; + private static final int LS_LINE_LENGTH = 36; + private static final int LS_LINE_TEMP_SCALE_OFFSET = 13; + private static final int MAX_VALID_LINE_LENGTH = LS_LINE_LENGTH * 20; + private static final int SINK_TIMEOUT_MS = 25; + private static final int SOCKET_TIMEOUT_MS = 2000; + private ControllerConfiguration cfg = new ControllerConfiguration(); + private Unit unit = SIUnits.CELSIUS; private final Logger logger = LoggerFactory.getLogger(ControllerHandler.class); - private final Object refreshLock = new Object(); private final Object socketLock = new Object(); - private @Nullable ScheduledFuture refreshJob; + private @Nullable ScheduledFuture poller; private @Nullable Socket socket; - public ControllerHandler(Bridge thing) { + public ControllerHandler(final Bridge thing) { super(thing); } @Override public void initialize() { - logger.debug("Initializing CoolMasterNet Controller handler..."); - stopRefresh(); - startRefresh(); + cfg = getConfigAs(ControllerConfiguration.class); + updateStatus(ThingStatus.UNKNOWN); + determineTemperatureUnits(); + stopPoller(); + startPoller(); } @Override public void dispose() { - stopRefresh(); - super.dispose(); + updateStatus(ThingStatus.OFFLINE); + stopPoller(); + disconnect(); + } + + /** + * Obtain the temperature unit configured for this controller. + * + *

+ * CoolMasterNet defaults to Celsius, but allows a user to change the scale + * on a per-controller basis using the ASCII I/F "set deg" command. Given + * changing the unit is very rarely performed, there is no direct support + * for doing so within this binding. + * + * @return the unit as determined from the first line of the "ls" command + */ + public Unit getUnit() { + return unit; } - private void startRefresh() { - synchronized (refreshLock) { - ControllerConfiguration config = getConfigAs(ControllerConfiguration.class); - logger.debug("Scheduling new refresh job"); - refreshJob = scheduler.scheduleWithFixedDelay(this::refreshHVACUnits, 0, config.refresh, TimeUnit.SECONDS); + private void determineTemperatureUnits() { + synchronized (socketLock) { + try { + checkConnection(); + final String ls = sendCommand("ls"); + if (ls.length() < LS_LINE_LENGTH) { + throw new CoolMasterClientError("Invalid 'ls' response: '%s'", ls); + } + final char scale = ls.charAt(LS_LINE_TEMP_SCALE_OFFSET); + unit = scale == 'C' ? SIUnits.CELSIUS : ImperialUnits.FAHRENHEIT; + logger.trace("Temperature scale '{}' set to {}", scale, unit); + } catch (final IOException ioe) { + logger.warn("Could not determine temperature scale", ioe); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, ioe.getMessage()); + } } } - private void stopRefresh() { - synchronized (refreshLock) { - ScheduledFuture localRefreshJob = refreshJob; - if (localRefreshJob != null && !localRefreshJob.isCancelled()) { - logger.debug("Cancelling existing refresh job"); - localRefreshJob.cancel(true); - refreshJob = null; + private void startPoller() { + synchronized (scheduler) { + logger.debug("Scheduling new poller"); + poller = scheduler.scheduleWithFixedDelay(this::poll, 0, cfg.refresh, SECONDS); + } + } + + private void stopPoller() { + synchronized (scheduler) { + final ScheduledFuture poller = this.poller; + if (poller != null) { + logger.debug("Cancelling existing poller"); + poller.cancel(true); + this.poller = null; } } } - private void refreshHVACUnits() { + private void poll() { try { checkConnection(); - updateStatus(ThingStatus.ONLINE); - for (Thing t : getThing().getThings()) { - HVACHandler h = (HVACHandler) t.getHandler(); - if (h != null) { - h.refresh(); - } + } catch (final IOException ioe) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, ioe.getMessage()); + return; + } + for (Thing t : getThing().getThings()) { + final HVACHandler h = (HVACHandler) t.getHandler(); + if (h != null) { + h.refresh(); } - } catch (CoolMasterClientError e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + if (isConnected()) { + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); } } - /* - * Return true if the client socket is connected. + /** + * Passively determine if the client socket appears to be connected, but do + * modify the connection state. * - * Use checkConnection() to probe if the coolmasternet is responding correctly, - * and try to re-establish the connection if possible. + *

+ * Use {@link #checkConnection()} if active verification (and potential + * reconnection) of the CoolNetMaster connection is required. */ public boolean isConnected() { synchronized (socketLock) { - Socket localSocket = socket; - return localSocket != null && localSocket.isConnected() && !localSocket.isClosed(); + final Socket socket = this.socket; + return socket != null && socket.isConnected() && !socket.isClosed(); } } - /* - * Send a particular ASCII command to the CoolMasterNet, and return the successful response as a string. + /** + * Send a specific ASCII I/F command to CoolMasterNet and return its response. + * + *

+ * This method automatically acquires a connection. * - * If the "OK" prompt is not received then a CoolMasterClientError is thrown that contains whatever - * error message was printed by the CoolMasterNet. + * @return the server response to the command (never empty) + * @throws {@link IOException} if communications failed with the server */ - @SuppressWarnings("resource") - public @Nullable String sendCommand(String command) throws CoolMasterClientError { + public String sendCommand(final String command) throws IOException { synchronized (socketLock) { checkConnection(); - StringBuilder response = new StringBuilder(); + final StringBuilder response = new StringBuilder(); try { - Socket localSocket = socket; - if (localSocket == null || !isConnected()) { + final Socket socket = this.socket; + if (socket == null || !isConnected()) { throw new CoolMasterClientError(String.format("No connection for sending command %s", command)); } logger.trace("Sending command '{}'", command); - OutputStream out = localSocket.getOutputStream(); - out.write(command.getBytes()); - out.write("\r\n".getBytes()); + final Writer out = new OutputStreamWriter(socket.getOutputStream(), US_ASCII); + out.write(command); + out.write(LF); + out.flush(); - try (Reader isr = new InputStreamReader(localSocket.getInputStream()); - BufferedReader in = new BufferedReader(isr)) { - while (true) { - String line = in.readLine(); - logger.trace("Read result '{}'", line); - if ("OK".equals(line)) { - return response.toString(); - } - response.append(line); - if (response.length() > 100) { - /* - * Usually this loop times out on errors, but in the case that we just keep getting - * data we should also fail with an error. - */ - throw new CoolMasterClientError( - String.format("Got gibberish response to command %s", command)); - } + final Reader isr = new InputStreamReader(socket.getInputStream(), US_ASCII); + final BufferedReader in = new BufferedReader(isr); + while (true) { + String line = in.readLine(); + logger.trace("Read result '{}'", line); + if (line == null || "OK".equals(line)) { + return response.toString(); + } + response.append(line); + if (response.length() > MAX_VALID_LINE_LENGTH) { + throw new CoolMasterClientError("Command '%s' received unexpected response '%s'", command, + response); } } - } catch (SocketTimeoutException e) { + } catch (final SocketTimeoutException ste) { if (response.length() == 0) { - throw new CoolMasterClientError(String.format("No response to command %s", command)); + throw new CoolMasterClientError("Command '%s' received no response", command); } - throw new CoolMasterClientError(String.format("Command '%s' got error '%s'", command, response)); - } catch (IOException e) { - logger.error("{}", e.getLocalizedMessage(), e); - return null; + throw new CoolMasterClientError("Command '%s' received truncated response '%s'", command, response); } } } - /* - * Verify that the client socket is connected and responding, and try to reconnect if possible. - * May block for 1-2 seconds. + /** + * Ensure a client socket is connected and ready to receive commands. + * + *

+ * This method may block for up to {@link #SOCKET_TIMEOUT_MS}, depending on + * the state of the connection. This usual time is {@link #SINK_TIMEOUT_MS}. + * + *

+ * Return of this method guarantees the socket is ready to receive a + * command. If the socket could not be made ready, an exception is raised. * - * Throws CoolMasterNetClientError if there is a connection problem. + * @throws IOException if the socket could not be made ready */ - @SuppressWarnings("resource") - private void checkConnection() throws CoolMasterClientError { + private void checkConnection() throws IOException { synchronized (socketLock) { - ControllerConfiguration config = getConfigAs(ControllerConfiguration.class); try { - if (!isConnected()) { + // Longer sink time used for initial connection welcome > prompt + final int sinkTime; + if (isConnected()) { + sinkTime = SINK_TIMEOUT_MS; + } else { + sinkTime = SOCKET_TIMEOUT_MS; connect(); - if (!isConnected()) { - throw new CoolMasterClientError( - String.format("Failed to connect to %s:%s", config.host, config.port)); - } } - Socket localSocket = socket; - if (localSocket == null) { - throw new CoolMasterClientError( - String.format("Failed to connect to %s:%s", config.host, config.port)); + final Socket socket = this.socket; + if (socket == null) { + throw new IllegalStateException( + "Socket is null, which is unexpected because it was verified as available earlier in the same synchronized block; please log a bug report"); + } + final InputStream in = socket.getInputStream(); + + // Sink (clear) buffer until earlier of the sinkTime or > prompt + try { + socket.setSoTimeout(sinkTime); + logger.trace("Waiting {} ms for buffer to sink", sinkTime); + while (true) { + int b = in.read(); + if (b == -1) { + break; + } + if (b == PROMPT) { + if (in.available() > 0) { + throw new IOException("Unexpected data following prompt"); + } + logger.trace("Buffer empty following unsolicited > prompt"); + return; + } + } + } catch (final SocketTimeoutException expectedFromRead) { + } finally { + socket.setSoTimeout(SOCKET_TIMEOUT_MS); } - InputStream in = localSocket.getInputStream(); - /* Flush anything pending in the input stream */ - while (in.available() > 0) { - in.read(); + // Solicit for a prompt given we haven't received one earlier + final Writer out = new OutputStreamWriter(socket.getOutputStream(), US_ASCII); + out.write(LF); + out.flush(); + + // Block until the > prompt arrives or IOE if SOCKET_TIMEOUT_MS + final int b = in.read(); + if (b != PROMPT) { + throw new IOException("Unexpected character received"); } - /* Send a CRLF, expect a > prompt (and a CRLF) back */ - OutputStream out = localSocket.getOutputStream(); - out.write("\r\n".getBytes(StandardCharsets.US_ASCII)); - /* - * this will time out with IOException if it doesn't see that prompt - * with no other data following it, within 1 second (socket timeout) - */ - final byte prompt = ">".getBytes(StandardCharsets.US_ASCII)[0]; - while (in.read() != prompt || in.available() > 3) { - continue; // empty by design + if (in.available() > 0) { + throw new IOException("Unexpected data following prompt"); } - } catch (IOException e) { + logger.trace("Buffer empty following solicited > prompt"); + } catch (final IOException ioe) { disconnect(); - logger.debug("{}", e.getLocalizedMessage(), e); - throw new CoolMasterClientError( - String.format("No response from CoolMasterNet unit %s:%s", config.host, config.port)); + throw ioe; } } } + /** + * Opens the socket. + * + *

+ * Guarantees to either open the socket or thrown an exception. + * + * @throws IOException if the socket could not be opened + */ private void connect() throws IOException { synchronized (socketLock) { - ControllerConfiguration config = getConfigAs(ControllerConfiguration.class); try { - Socket localSocket = new Socket(); - localSocket.connect(new InetSocketAddress(config.host, config.port), SOCKET_TIMEOUT); - localSocket.setSoTimeout(SOCKET_TIMEOUT); - socket = localSocket; - } catch (UnknownHostException e) { - logger.error("Unknown socket host: {}", config.host); - socket = null; - } catch (SocketException e) { - logger.error("Failed to connect to {}:{}: {}", config.host, config.port, e.getLocalizedMessage(), e); + logger.debug("Connecting to {}:{}", cfg.host, cfg.port); + final Socket socket = new Socket(); + socket.connect(new InetSocketAddress(cfg.host, cfg.port), SOCKET_TIMEOUT_MS); + socket.setSoTimeout(SOCKET_TIMEOUT_MS); + this.socket = socket; + } catch (final IOException ioe) { socket = null; + throw ioe; } } } + /** + * Attempts to disconnect the socket. + * + *

+ * Disconnection failure is not considered an error, although will be logged. + */ private void disconnect() { synchronized (socketLock) { - Socket localSocket = socket; - if (localSocket != null) { + final Socket socket = this.socket; + if (socket != null) { + logger.debug("Disconnecting from {}:{}", cfg.host, cfg.port); try { - localSocket.close(); - } catch (IOException e1) { - logger.error("{}", e1.getLocalizedMessage(), e1); + socket.close(); + } catch (final IOException ioe) { + logger.warn("Could not disconnect", ioe); } - socket = null; + this.socket = null; } } } - public class CoolMasterClientError extends Exception { - private static final long serialVersionUID = 1L; + /** + * Encodes ASCII I/F protocol error messages. + * + *

+ * This exception is not used for normal socket and connection failures. + * It is only used when there is a protocol level error (eg unexpected + * messages or malformed content from the CoolNetMaster server). + */ + public class CoolMasterClientError extends IOException { + private static final long serialVersionUID = 2L; - public CoolMasterClientError(String message) { + public CoolMasterClientError(final String message) { super(message); } + + public CoolMasterClientError(String format, Object... args) { + super(String.format(format, args)); + } } @Override - public void handleCommand(ChannelUID channelUID, Command command) { + public void handleCommand(final ChannelUID channelUID, final Command command) { } } diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/CoolMasterNetBindingConstants.java b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/CoolMasterNetBindingConstants.java index 857fa0aa0b4ea..84cdbbbe85c48 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/CoolMasterNetBindingConstants.java +++ b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/CoolMasterNetBindingConstants.java @@ -20,8 +20,7 @@ import org.eclipse.smarthome.core.thing.ThingTypeUID; /** - * The {@link coolmasternetBinding} class defines common constants, which are - * used across the whole binding. + * Defines constants used across the whole binding. * * @author Angus Gratton - Initial contribution */ @@ -30,19 +29,18 @@ public class CoolMasterNetBindingConstants { public static final String BINDING_ID = "coolmasternet"; - // List of all Thing Type UIDs + // list of all Thing Type UIDs public static final ThingTypeUID THING_TYPE_CONTROLLER = new ThingTypeUID(BINDING_ID, "controller"); public static final ThingTypeUID THING_TYPE_HVAC = new ThingTypeUID(BINDING_ID, "hvac"); - // List of all Channel ids + // list of all Channel ids public static final String ON = "on"; public static final String MODE = "mode"; public static final String SET_TEMP = "set_temp"; public static final String FAN_SPEED = "fan_speed"; - public static final String LOUVRE = "louvre_angle"; + public static final String LOUVRE = "louvre"; public static final String CURRENT_TEMP = "current_temp"; public static final Set SUPPORTED_THING_TYPES_UIDS = Stream.of(THING_TYPE_CONTROLLER, THING_TYPE_HVAC) .collect(Collectors.toSet()); - } diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/CoolMasterNetHandlerFactory.java b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/CoolMasterNetHandlerFactory.java index 2fa4ae89dffde..c00b79bda2583 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/CoolMasterNetHandlerFactory.java +++ b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/CoolMasterNetHandlerFactory.java @@ -36,13 +36,13 @@ public class CoolMasterNetHandlerFactory extends BaseThingHandlerFactory { @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { + public boolean supportsThingType(final ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); } @Override - protected @Nullable ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + protected @Nullable ThingHandler createHandler(final Thing thing) { + final ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(THING_TYPE_CONTROLLER)) { return new ControllerHandler((Bridge) thing); @@ -52,5 +52,4 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return null; } - } diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/config/ControllerConfiguration.java b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/config/ControllerConfiguration.java index 6f559dd232325..9c008a7714fa7 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/config/ControllerConfiguration.java +++ b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/config/ControllerConfiguration.java @@ -28,5 +28,4 @@ public class ControllerConfiguration { public String host; public int port = 10102; public int refresh = 5; // seconds - } diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/config/HVACConfiguration.java b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/config/HVACConfiguration.java index 5c46a50418b8f..3d509eeda48b8 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/config/HVACConfiguration.java +++ b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/config/HVACConfiguration.java @@ -23,5 +23,4 @@ public class HVACConfiguration { public static final String UID = "uid"; public String uid; - } diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/handler/HVACHandler.java b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/handler/HVACHandler.java index 0aa4b8b279f30..c371c638fa87f 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/handler/HVACHandler.java +++ b/bundles/org.openhab.binding.coolmasternet/src/main/java/org/openhab/binding/coolmasternet/internal/handler/HVACHandler.java @@ -14,15 +14,17 @@ import static org.openhab.binding.coolmasternet.internal.CoolMasterNetBindingConstants.*; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; @@ -32,7 +34,6 @@ import org.eclipse.smarthome.core.types.RefreshType; import org.openhab.binding.coolmasternet.internal.ControllerHandler; import org.openhab.binding.coolmasternet.internal.ControllerHandler.CoolMasterClientError; -import org.openhab.binding.coolmasternet.internal.config.ControllerConfiguration; import org.openhab.binding.coolmasternet.internal.config.HVACConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,137 +48,189 @@ @NonNullByDefault public class HVACHandler extends BaseThingHandler { - private final Logger logger = LoggerFactory.getLogger(HVACHandler.class); - - public HVACHandler(Thing thing) { - super(thing); - } + /** + * The CoolMasterNet protocol's query command returns numbers 0-5 for fan + * speed, but the protocol's fan command (and matching binding command) use + * single-letter abbreviations. + */ + private static final Map FAN_NUM_TO_STR; - private @Nullable ControllerHandler getControllerHandler() { - Bridge bridge = getBridge(); - return bridge != null ? (ControllerHandler) bridge.getHandler() : null; - } + /** + * The CoolMasterNet query command returns numbers 0-5 for operation modes, + * but these don't map to any mode you can set on the device, so we use this + * lookup table. + */ + private static final Map MODE_NUM_TO_STR; - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - String uid = getConfigAs(HVACConfiguration.class).uid; - String channel = channelUID.getId(); - ControllerHandler controller = getControllerHandler(); + static { + FAN_NUM_TO_STR = new HashMap<>(); + FAN_NUM_TO_STR.put("0", "l"); // low + FAN_NUM_TO_STR.put("1", "m"); // medium + FAN_NUM_TO_STR.put("2", "h"); // high + FAN_NUM_TO_STR.put("3", "a"); // auto + FAN_NUM_TO_STR.put("4", "t"); // top - try { - Bridge bridge = getBridge(); - if (bridge == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "CoolMasterNet Controller bridge not set"); - } else if (controller == null || !controller.isConnected()) { - ControllerConfiguration config = bridge.getConfiguration().as(ControllerConfiguration.class); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - String.format("Could not connect to CoolMasterNet unit %s:%d", config.host, config.port)); - } else { - if (channel.endsWith(ON) && command instanceof OnOffType) { - OnOffType onoff = (OnOffType) command; - controller.sendCommand(String.format("%s %s", onoff == OnOffType.ON ? "on" : "off", uid)); - } else if (channel.endsWith(SET_TEMP) && command instanceof DecimalType) { - DecimalType temp = (DecimalType) command; - controller.sendCommand(String.format("temp %s %s", uid, temp)); - } else if (channel.endsWith(MODE) && command instanceof StringType) { - /* the mode value in the command is the actual CoolMasterNet protocol command */ - controller.sendCommand(String.format("%s %s", command, uid)); - } else if (channel.endsWith(FAN_SPEED) && command instanceof StringType) { - controller.sendCommand(String.format("fspeed %s %s", uid, command)); - } else if (channel.endsWith(LOUVRE) && command instanceof StringType) { - controller.sendCommand(String.format("swing %s %s", uid, command)); - } else if (command instanceof RefreshType) { - refresh(); - } - } - } catch (CoolMasterClientError e) { - logger.error("Failed to set channel {} -> {}: {}", channel, command, e.getMessage()); - } + MODE_NUM_TO_STR = new HashMap<>(); + MODE_NUM_TO_STR.put("0", "cool"); + MODE_NUM_TO_STR.put("1", "heat"); + MODE_NUM_TO_STR.put("2", "auto"); + MODE_NUM_TO_STR.put("3", "dry"); + // 4=='haux' but this mode doesn't have an equivalent command to set it + MODE_NUM_TO_STR.put("4", "heat"); + MODE_NUM_TO_STR.put("5", "fan"); } - @Override - public void initialize() { - logger.debug("Initializing CoolMasterNet HVAC handler..."); - updateStatus(ThingStatus.ONLINE); + private HVACConfiguration cfg = new HVACConfiguration(); + private final Logger logger = LoggerFactory.getLogger(HVACHandler.class); + + public HVACHandler(final Thing thing) { + super(thing); } - /* Update this HVAC unit's properties from the controller */ - public void refresh() { - String on = query("o"); - if (on != null) { - updateState(ON, "1".equals(on) ? OnOffType.ON : OnOffType.OFF); + /** + * Get the controller handler for this bridge. + * + *

+ * This method does not raise any exception, but if null is returned it will + * always update the Thing status with the reason. + * + *

+ * The returned handler may or may not be connected. This method will not + * change the Thing status simply because it is not connected, because a + * caller may wish to attempt an operation that would result in connection. + * + * @return the controller handler or null if the controller is unavailable + */ + private @Nullable ControllerHandler getControllerHandler() { + final Bridge bridge = getBridge(); + if (bridge == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "CoolMasterNet Controller bridge not configured"); + return null; } - String currentTemp = query("a"); - if (currentTemp != null) { - updateState(CURRENT_TEMP, new DecimalType(currentTemp)); - } + final ControllerHandler handler = (ControllerHandler) bridge.getHandler(); - String setTemp = query("t"); - if (setTemp != null) { - updateState(SET_TEMP, new DecimalType(setTemp)); + if (handler == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED, + "CoolMasterNet Controller bridge not initialized"); + return null; } - String mode = MODE_NUM_TO_STR.get(query("m")); - if (mode != null) { - updateState(MODE, new StringType(mode)); - } + return handler; + } - String louvre = query("s"); - if (louvre != null) { - updateState(LOUVRE, new StringType(louvre)); + @Override + public void handleCommand(final ChannelUID channelUID, final Command command) { + final ControllerHandler controller = getControllerHandler(); + if (controller == null) { + return; } - String fan = FAN_NUM_TO_STR.get(query("f")); - if (fan != null) { - updateState(FAN_SPEED, new StringType(fan)); - } - } + final String uid = cfg.uid; + final String channel = channelUID.getId(); - private @Nullable String query(String queryChar) { - String uid = getConfigAs(HVACConfiguration.class).uid; - String command = String.format("query %s %s", uid, queryChar); - ControllerHandler controller = getControllerHandler(); - if (controller != null) { - try { - return controller.sendCommand(command); - } catch (CoolMasterClientError e) { - logger.error("Query '{}' failed: {}", command, e.getMessage()); + try { + switch (channel) { + case CURRENT_TEMP: + if (command instanceof RefreshType) { + final String currentTemp = query(controller, "a"); + if (currentTemp != null) { + final Integer temp = new Integer(currentTemp); + final QuantityType value = new QuantityType<>(temp, controller.getUnit()); + updateState(CURRENT_TEMP, value); + } + } + break; + case ON: + if (command instanceof RefreshType) { + final String on = query(controller, "o"); + if (on != null) { + updateState(ON, "1".equals(on) ? OnOffType.ON : OnOffType.OFF); + } + } else if (command instanceof OnOffType) { + final OnOffType onoff = (OnOffType) command; + controller.sendCommand(String.format("%s %s", onoff == OnOffType.ON ? "on" : "off", uid)); + } + break; + case SET_TEMP: + if (command instanceof RefreshType) { + final String setTemp = query(controller, "t"); + if (setTemp != null) { + final Integer temp = new Integer(setTemp); + final QuantityType value = new QuantityType<>(temp, controller.getUnit()); + updateState(SET_TEMP, value); + } + } else if (command instanceof QuantityType) { + final QuantityType temp = (QuantityType) command; + final QuantityType converted = temp.toUnit(controller.getUnit()); + final String formatted = converted.format("%.1f"); + controller.sendCommand(String.format("temp %s %s", uid, formatted)); + } + break; + case MODE: + if (command instanceof RefreshType) { + final String mode = MODE_NUM_TO_STR.get(query(controller, "m")); + if (mode != null) { + updateState(MODE, new StringType(mode)); + } + } else if (command instanceof StringType) { + final String mode = ((StringType) command).toString(); + controller.sendCommand(String.format("%s %s", mode, uid)); + } + break; + case FAN_SPEED: + if (command instanceof RefreshType) { + final String fan = FAN_NUM_TO_STR.get(query(controller, "f")); + if (fan != null) { + updateState(FAN_SPEED, new StringType(fan)); + } + } else if (command instanceof StringType) { + final String fan = ((StringType) command).toString(); + controller.sendCommand(String.format("fspeed %s %s", uid, fan)); + } + break; + case LOUVRE: + if (command instanceof RefreshType) { + final String louvre = query(controller, "s"); + if (louvre != null) { + updateState(LOUVRE, new StringType(louvre)); + } + } else if (command instanceof StringType) { + final String louvre = ((StringType) command).toString(); + controller.sendCommand(String.format("swing %s %s", uid, louvre)); + } + break; + default: + logger.warn("Unknown command '{}' on channel '{}' for unit '{}'", command, channel, uid); } + updateStatus(ThingStatus.ONLINE); + } catch (final IOException ioe) { + logger.warn("Failed to handle command '{}' on channel '{}' for unit '{}' due to '{}'", command, channel, + uid, ioe.getLocalizedMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, ioe.getLocalizedMessage()); } - return null; /* passing back null sets an invalid value on the channel */ } - /* - * The CoolMasterNet query command returns numbers 0-5 for operation modes, - * but these don't map to any mode you can set on the device, so we use this - * lookup table. - */ - private static final Map MODE_NUM_TO_STR; - static { - MODE_NUM_TO_STR = new HashMap<>(); - MODE_NUM_TO_STR.put("0", "cool"); - MODE_NUM_TO_STR.put("1", "heat"); - MODE_NUM_TO_STR.put("2", "auto"); - MODE_NUM_TO_STR.put("3", "dry"); - /* 4=='haux' but this mode doesn't have an equivalent command to set it! */ - MODE_NUM_TO_STR.put("4", "heat"); - MODE_NUM_TO_STR.put("5", "fan"); + @Override + public void initialize() { + cfg = getConfigAs(HVACConfiguration.class); + updateStatus(ThingStatus.UNKNOWN); } - /* - * The CoolMasterNet protocol's query command returns numbers 0-5 - * for fan speed, but the protocol's fan command (& matching - * binding command) use single-letter abbreviations. + /** + * Update this HVAC unit's properties from the controller. */ - private static final Map FAN_NUM_TO_STR; - static { - FAN_NUM_TO_STR = new HashMap<>(); - FAN_NUM_TO_STR.put("0", "l"); /* Low */ - FAN_NUM_TO_STR.put("1", "m"); /* Medium */ - FAN_NUM_TO_STR.put("2", "h"); /* High */ - FAN_NUM_TO_STR.put("3", "a"); /* Auto */ - FAN_NUM_TO_STR.put("4", "t"); /* Top */ + public void refresh() { + for (final Channel channel : getThing().getChannels()) { + handleCommand(channel.getUID(), RefreshType.REFRESH); + } + } + + private @Nullable String query(final ControllerHandler controller, final String queryChar) + throws IOException, CoolMasterClientError { + final String uid = getConfigAs(HVACConfiguration.class).uid; + final String command = String.format("query %s %s", uid, queryChar); + return controller.sendCommand(command); } } diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.coolmasternet/src/main/resources/ESH-INF/binding/binding.xml index 56aacb355bff3..0c6e470fbbfdd 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.coolmasternet/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + CoolMasterNet Binding Binding for Cool Automation CoolMasterNet HVAC controllers. diff --git a/bundles/org.openhab.binding.coolmasternet/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.coolmasternet/src/main/resources/ESH-INF/thing/thing-types.xml index 3ac019c18fb18..d4b40c89e8f05 100644 --- a/bundles/org.openhab.binding.coolmasternet/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.coolmasternet/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -35,19 +36,19 @@ - + HVAC System connected to a controller (unique UID) - - - - - - + + + + + + @@ -85,19 +86,19 @@ - Number + Number:Temperature Temperature thermostat setpoint Temperature - + - Number + Number:Temperature Current system ambient temperature Temperature - + diff --git a/bundles/org.openhab.binding.coronastats/.classpath b/bundles/org.openhab.binding.coronastats/.classpath index e74dbb099f67d..39abf1c5e9102 100644 --- a/bundles/org.openhab.binding.coronastats/.classpath +++ b/bundles/org.openhab.binding.coronastats/.classpath @@ -1,49 +1,49 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.coronastats/.project b/bundles/org.openhab.binding.coronastats/.project index bff9deab3cfcf..a499b5f2528ff 100644 --- a/bundles/org.openhab.binding.coronastats/.project +++ b/bundles/org.openhab.binding.coronastats/.project @@ -1,23 +1,23 @@ - - - org.openhab.binding.coronastats - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - + + + org.openhab.binding.coronastats + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.coronastats/README.md b/bundles/org.openhab.binding.coronastats/README.md index 86d639c2937ae..0249aca3cbabb 100644 --- a/bundles/org.openhab.binding.coronastats/README.md +++ b/bundles/org.openhab.binding.coronastats/README.md @@ -1,127 +1,127 @@ -# CoronaStats Binding - -This binding provides the statistic about cases of COVID-19 from the website https://corona-stats.online/. - - -## Supported Things - -This binding supports a `world` thing, which polls the dataset in an adjustable interval as a bridge and provides the statistics for the whole world. -The `country` thing, representing the statistics for a specified country. - -## Discovery - -This binding adds a default `world` thing to the Inbox. -This can be used as bridge for country things you may add manually. - -## Thing Configuration - -### World - -| Parameter | Default | Required | Description | -| --------- | :-----: | :------: | ---------------------------------------------------------------------------------------- | -| `refresh` | 30 | no | Define the interval for polling the data from website in minutes. Minimum is 15 minutes. | - -### Country - -| Parameter | Default | Required | Description | -| ------------- | :-----: | :------: | ------------------------------------------------- | -| `countryCode` | - | yes | 2-letter code for the country you want to display | - -For the correct 2-letter country code have a look at the website https://corona-stats.online/ - -## Channels - -### World and Country - -| channels | type | description | -| -------------- | -------------------- | ---------------------------------------------- | -| `cases` | Number:Dimensionless | Total cases | -| `today_cases` | Number:Dimensionless | Increase of total cases today | -| `deaths` | Number:Dimensionless | Deaths | -| `today_deaths` | Number:Dimensionless | Increase of deaths | -| `recovered` | Number:Dimensionless | Recovered cases | -| `active` | Number:Dimensionless | Active cases | -| `critical` | Number:Dimensionless | Critical cases | -| `tests` | Number:Dimensionless | Count of reported tests (`country` thing only) | -| `updated` | Number:Dimensionless | Data last update time (`country` thing only) | - -## Full Example - -### Things - -``` -Bridge coronastats:world:stats "Corona Stats World" @ "Corona" [refresh=15] { - Thing country usa "Corona Stats USA" @ "Corona" [countryCode="US"] - Thing country germany "Corona Stats Germany" @ "Corona" [countryCode="DE"] - Thing country austria "Corona Stats Austria" @ "Corona" [countryCode="AT"] - Thing country italy "Corona Stats Italy" @ "Corona" [countryCode="IT"] - Thing country spain "Corona Stats Spain" @ "Corona" [countryCode="ES"] - Thing country uk "Corona Stats United Kingdom" @ "Corona" [countryCode="GB"] -} -``` - -### Items - -``` -Number:Dimensionless coronaCasesWorld "Total Cases World [%,d]" - {channel="coronastats:world:stats:cases"} - -Number:Dimensionless coronaDeathsWorld "Deaths World [%,d]" - {channel="coronastats:world:stats:deaths"} - -Number:Dimensionless coronaRecoveredWorld "Recovered Cases World [%,d]" - {channel="coronastats:world:stats:recovered"} - -Number:Dimensionless coronaActiveWorld "Active Cases World [%,d]" - {channel="coronastats:world:stats:active"} - -Number:Dimensionless coronaCriticalWorld "Critical Cases World [%,d]" - {channel="coronastats:world:stats:critical"} - -Number:Dimensionless coronaCasesUSA "Total Cases USA [%,d]" - {channel="coronastats:country:stats:usa:cases"} - -Number:Dimensionless coronaDeathsUSA "Deaths USA [%,d]" - {channel="coronastats:country:stats:usa:deaths"} - -Number:Dimensionless coronaRecoveredUSA "Recovered Cases USA [%,d]" - {channel="coronastats:country:stats:usa:recovered"} - -Number:Dimensionless coronaActiveUSA "Active Cases USA [%,d]" - {channel="coronastats:country:stats:usa:active"} - -Number:Dimensionless coronaCriticalUSA "Critical Cases USA [%,d]" - {channel="coronastats:country:stats:usa:critical"} - -Number:Dimensionless coronaTestsUSA "Tests USA [%d]" - {channel="coronastats:country:stats:usa:cases"} - -DateTime coronaUpdatedUSA "Updated USA [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" - {channel="coronastats:country:stats:usa:updated"} -``` - -### Sitemap - -``` -Text label="Corona" { - Frame label="World" { - Text item=coronaCasesWorld - Text item=coronaActiveWorld - Text item=coronaRecoveredWorld - Text item=coronaDeathsWorld - Text item=coronaCriticalWorld - Text item=coronaTestUSA - } - - Frame label="USA" { - Text item=coronaCasesUSA - Text item=coronaActiveUSA - Text item=coronaRecoveredUSA - Text item=coronaDeathsUSA - Text item=coronaCriticalUSA - Text item=coronaTestsUSA - Text item=coronaUpdatedUSA - } -} - -``` +# CoronaStats Binding + +This binding provides the statistic about cases of COVID-19 from the website https://corona-stats.online/. + + +## Supported Things + +This binding supports a `world` thing, which polls the dataset in an adjustable interval as a bridge and provides the statistics for the whole world. +The `country` thing, representing the statistics for a specified country. + +## Discovery + +This binding adds a default `world` thing to the Inbox. +This can be used as bridge for country things you may add manually. + +## Thing Configuration + +### World + +| Parameter | Default | Required | Description | +| --------- | :-----: | :------: | ---------------------------------------------------------------------------------------- | +| `refresh` | 30 | no | Define the interval for polling the data from website in minutes. Minimum is 15 minutes. | + +### Country + +| Parameter | Default | Required | Description | +| ------------- | :-----: | :------: | ------------------------------------------------- | +| `countryCode` | - | yes | 2-letter code for the country you want to display | + +For the correct 2-letter country code have a look at the website https://corona-stats.online/ + +## Channels + +### World and Country + +| channels | type | description | +| -------------- | -------------------- | ---------------------------------------------- | +| `cases` | Number:Dimensionless | Total cases | +| `today_cases` | Number:Dimensionless | Increase of total cases today | +| `deaths` | Number:Dimensionless | Deaths | +| `today_deaths` | Number:Dimensionless | Increase of deaths | +| `recovered` | Number:Dimensionless | Recovered cases | +| `active` | Number:Dimensionless | Active cases | +| `critical` | Number:Dimensionless | Critical cases | +| `tests` | Number:Dimensionless | Count of reported tests (`country` thing only) | +| `updated` | Number:Dimensionless | Data last update time (`country` thing only) | + +## Full Example + +### Things + +``` +Bridge coronastats:world:stats "Corona Stats World" @ "Corona" [refresh=15] { + Thing country usa "Corona Stats USA" @ "Corona" [countryCode="US"] + Thing country germany "Corona Stats Germany" @ "Corona" [countryCode="DE"] + Thing country austria "Corona Stats Austria" @ "Corona" [countryCode="AT"] + Thing country italy "Corona Stats Italy" @ "Corona" [countryCode="IT"] + Thing country spain "Corona Stats Spain" @ "Corona" [countryCode="ES"] + Thing country uk "Corona Stats United Kingdom" @ "Corona" [countryCode="GB"] +} +``` + +### Items + +``` +Number:Dimensionless coronaCasesWorld "Total Cases World [%,d]" + {channel="coronastats:world:stats:cases"} + +Number:Dimensionless coronaDeathsWorld "Deaths World [%,d]" + {channel="coronastats:world:stats:deaths"} + +Number:Dimensionless coronaRecoveredWorld "Recovered Cases World [%,d]" + {channel="coronastats:world:stats:recovered"} + +Number:Dimensionless coronaActiveWorld "Active Cases World [%,d]" + {channel="coronastats:world:stats:active"} + +Number:Dimensionless coronaCriticalWorld "Critical Cases World [%,d]" + {channel="coronastats:world:stats:critical"} + +Number:Dimensionless coronaCasesUSA "Total Cases USA [%,d]" + {channel="coronastats:country:stats:usa:cases"} + +Number:Dimensionless coronaDeathsUSA "Deaths USA [%,d]" + {channel="coronastats:country:stats:usa:deaths"} + +Number:Dimensionless coronaRecoveredUSA "Recovered Cases USA [%,d]" + {channel="coronastats:country:stats:usa:recovered"} + +Number:Dimensionless coronaActiveUSA "Active Cases USA [%,d]" + {channel="coronastats:country:stats:usa:active"} + +Number:Dimensionless coronaCriticalUSA "Critical Cases USA [%,d]" + {channel="coronastats:country:stats:usa:critical"} + +Number:Dimensionless coronaTestsUSA "Tests USA [%d]" + {channel="coronastats:country:stats:usa:cases"} + +DateTime coronaUpdatedUSA "Updated USA [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" + {channel="coronastats:country:stats:usa:updated"} +``` + +### Sitemap + +``` +Text label="Corona" { + Frame label="World" { + Text item=coronaCasesWorld + Text item=coronaActiveWorld + Text item=coronaRecoveredWorld + Text item=coronaDeathsWorld + Text item=coronaCriticalWorld + Text item=coronaTestUSA + } + + Frame label="USA" { + Text item=coronaCasesUSA + Text item=coronaActiveUSA + Text item=coronaRecoveredUSA + Text item=coronaDeathsUSA + Text item=coronaCriticalUSA + Text item=coronaTestsUSA + Text item=coronaUpdatedUSA + } +} + +``` diff --git a/bundles/org.openhab.binding.coronastats/pom.xml b/bundles/org.openhab.binding.coronastats/pom.xml index 6477001f82c98..9d92ab82cc2c4 100644 --- a/bundles/org.openhab.binding.coronastats/pom.xml +++ b/bundles/org.openhab.binding.coronastats/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.coronastats diff --git a/bundles/org.openhab.binding.coronastats/src/main/feature/feature.xml b/bundles/org.openhab.binding.coronastats/src/main/feature/feature.xml index 44f384a8e0539..d3576274073b9 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.coronastats/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.coronastats/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.coronastats/${project.version} + diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsBindingConstants.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsBindingConstants.java index d9534ddcabf05..a85c7c256c976 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsBindingConstants.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsBindingConstants.java @@ -1,62 +1,62 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.coronastats.internal; - -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.core.thing.ThingTypeUID; - -/** - * The {@link CoronaStatsBindingConstants} class defines common constants, which are - * used across the whole binding. - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class CoronaStatsBindingConstants { - public static final String BINDING_ID = "coronastats"; - - // World - public static final ThingTypeUID THING_TYPE_WORLD = new ThingTypeUID(BINDING_ID, "world"); - public static final String STATS = "stats"; - public static final String WORLD_LABEL = "Corona Statistics (World)"; - - // Country - public static final ThingTypeUID THING_TYPE_COUNTRY = new ThingTypeUID(BINDING_ID, "country"); - - // @formatter:off - public static final Set SUPPORTED_THING_TYPES_UIDS = - Collections.unmodifiableSet(Stream - .of(THING_TYPE_WORLD, THING_TYPE_COUNTRY) - .collect(Collectors.toSet()) - ); - // @formatter:on - - // Properties country - public static final String PROPERTY_COUNTRY = "country"; - - // Channels world/country - public static final String CHANNEL_CASES = "cases"; - public static final String CHANNEL_NEW_CASES = "today_cases"; - public static final String CHANNEL_DEATHS = "deaths"; - public static final String CHANNEL_NEW_DEATHS = "today_deaths"; - public static final String CHANNEL_RECOVERED = "recovered"; - public static final String CHANNEL_ACTIVE = "active"; - public static final String CHANNEL_CRITICAL = "critical"; - public static final String CHANNEL_TESTS = "tests"; - public static final String CHANNEL_UPDATED = "updated"; -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.coronastats.internal; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link CoronaStatsBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class CoronaStatsBindingConstants { + public static final String BINDING_ID = "coronastats"; + + // World + public static final ThingTypeUID THING_TYPE_WORLD = new ThingTypeUID(BINDING_ID, "world"); + public static final String STATS = "stats"; + public static final String WORLD_LABEL = "Corona Statistics (World)"; + + // Country + public static final ThingTypeUID THING_TYPE_COUNTRY = new ThingTypeUID(BINDING_ID, "country"); + + // @formatter:off + public static final Set SUPPORTED_THING_TYPES_UIDS = + Collections.unmodifiableSet(Stream + .of(THING_TYPE_WORLD, THING_TYPE_COUNTRY) + .collect(Collectors.toSet()) + ); + // @formatter:on + + // Properties country + public static final String PROPERTY_COUNTRY = "country"; + + // Channels world/country + public static final String CHANNEL_CASES = "cases"; + public static final String CHANNEL_NEW_CASES = "today_cases"; + public static final String CHANNEL_DEATHS = "deaths"; + public static final String CHANNEL_NEW_DEATHS = "today_deaths"; + public static final String CHANNEL_RECOVERED = "recovered"; + public static final String CHANNEL_ACTIVE = "active"; + public static final String CHANNEL_CRITICAL = "critical"; + public static final String CHANNEL_TESTS = "tests"; + public static final String CHANNEL_UPDATED = "updated"; +} diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsHandlerFactory.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsHandlerFactory.java index 281ae94f46cd4..2c6cd6d4515e0 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsHandlerFactory.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsHandlerFactory.java @@ -1,66 +1,66 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.coronastats.internal; - -import static org.openhab.binding.coronastats.internal.CoronaStatsBindingConstants.*; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; -import org.eclipse.smarthome.io.net.http.HttpClientFactory; -import org.openhab.binding.coronastats.internal.handler.CoronaStatsWorldHandler; -import org.openhab.binding.coronastats.internal.handler.CoronaStatsCountryHandler; -import org.osgi.service.component.annotations.Activate; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; - -/** - * The {@link CoronaStatsHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -@Component(configurationPid = "binding.coronastats", service = ThingHandlerFactory.class) -public class CoronaStatsHandlerFactory extends BaseThingHandlerFactory { - private final HttpClient httpClient; - - @Activate - public CoronaStatsHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { - this.httpClient = httpClientFactory.getCommonHttpClient(); - } - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected @Nullable ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - if (THING_TYPE_WORLD.equals(thingTypeUID)) { - return new CoronaStatsWorldHandler((Bridge) thing, httpClient); - } else if (THING_TYPE_COUNTRY.equals(thingTypeUID)) { - return new CoronaStatsCountryHandler(thing); - } - - return null; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.coronastats.internal; + +import static org.openhab.binding.coronastats.internal.CoronaStatsBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.net.http.HttpClientFactory; +import org.openhab.binding.coronastats.internal.handler.CoronaStatsCountryHandler; +import org.openhab.binding.coronastats.internal.handler.CoronaStatsWorldHandler; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link CoronaStatsHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.coronastats", service = ThingHandlerFactory.class) +public class CoronaStatsHandlerFactory extends BaseThingHandlerFactory { + private final HttpClient httpClient; + + @Activate + public CoronaStatsHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_WORLD.equals(thingTypeUID)) { + return new CoronaStatsWorldHandler((Bridge) thing, httpClient); + } else if (THING_TYPE_COUNTRY.equals(thingTypeUID)) { + return new CoronaStatsCountryHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsPollingException.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsPollingException.java index 8a96145c21026..1029d213b103b 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsPollingException.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/CoronaStatsPollingException.java @@ -1,33 +1,33 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.coronastats.internal; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * The {@link CoronaStatsPollingException} class is the exception for all polling errors. - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class CoronaStatsPollingException extends Exception { - private static final long serialVersionUID = 1L; - - public CoronaStatsPollingException(String message) { - super(message); - } - - public CoronaStatsPollingException(String message, Throwable throwable) { - super(message, throwable); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.coronastats.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link CoronaStatsPollingException} class is the exception for all polling errors. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class CoronaStatsPollingException extends Exception { + private static final long serialVersionUID = 1L; + + public CoronaStatsPollingException(String message) { + super(message); + } + + public CoronaStatsPollingException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/config/CoronaStatsCountryConfiguration.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/config/CoronaStatsCountryConfiguration.java index 62cdcf74c7886..a62a915f7aa2b 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/config/CoronaStatsCountryConfiguration.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/config/CoronaStatsCountryConfiguration.java @@ -1,33 +1,33 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.coronastats.internal.config; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * Configuration for the {@link CoronaStatsCountryHandler} - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class CoronaStatsCountryConfiguration { - private String countryCode = ""; - - public String getCountryCode() { - return countryCode.toUpperCase(); - } - - public boolean isValid() { - return !"".equals(countryCode); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.coronastats.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Configuration for the {@link CoronaStatsCountryHandler} + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class CoronaStatsCountryConfiguration { + private String countryCode = ""; + + public String getCountryCode() { + return countryCode.toUpperCase(); + } + + public boolean isValid() { + return !"".equals(countryCode); + } +} diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/config/CoronaStatsWorldConfiguration.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/config/CoronaStatsWorldConfiguration.java index 654e7d77a5dd8..bd498a79e2bb0 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/config/CoronaStatsWorldConfiguration.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/config/CoronaStatsWorldConfiguration.java @@ -1,29 +1,29 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.coronastats.internal.config; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * Configuration for the {@link CoronaStatsWorldHandler} - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class CoronaStatsWorldConfiguration { - public int refresh = 30; - - public boolean isValid() { - return refresh >= 15; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.coronastats.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Configuration for the {@link CoronaStatsWorldHandler} + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class CoronaStatsWorldConfiguration { + public int refresh = 30; + + public boolean isValid() { + return refresh >= 15; + } +} diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/dto/CoronaStats.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/dto/CoronaStats.java index 80ed30029f804..195fb1edac3b9 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/dto/CoronaStats.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/dto/CoronaStats.java @@ -14,11 +14,11 @@ import java.util.Set; -import com.google.gson.annotations.SerializedName; - import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import com.google.gson.annotations.SerializedName; + /** * The {@link CoronaStats} class is internal CoronaStats structure. * diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/dto/CoronaStatsCases.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/dto/CoronaStatsCases.java index 2a5fd8a12e4f6..33ecbf70d13ad 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/dto/CoronaStatsCases.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/dto/CoronaStatsCases.java @@ -17,11 +17,15 @@ import java.util.HashMap; import java.util.Map; +import javax.measure.quantity.Dimensionless; + import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; +import tec.uom.se.AbstractUnit; + /** * The {@link CoronaStatsCountry} class holds the internal data representation of each Country * @@ -55,7 +59,7 @@ protected State parseToState(int count) { if (count == -1) { return UnDefType.NULL; } else { - return new DecimalType(count); + return new QuantityType(count, AbstractUnit.ONE); } } } diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/handler/CoronaStatsCountryHandler.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/handler/CoronaStatsCountryHandler.java index c8f4400de5e84..7fdab2d6fbdfb 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/handler/CoronaStatsCountryHandler.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/handler/CoronaStatsCountryHandler.java @@ -1,110 +1,110 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.coronastats.internal.handler; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.coronastats.internal.config.CoronaStatsCountryConfiguration; -import org.openhab.binding.coronastats.internal.dto.CoronaStats; -import org.openhab.binding.coronastats.internal.dto.CoronaStatsCountry; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link CoronaStatsCountryHandler} is the handler for country thing - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class CoronaStatsCountryHandler extends BaseThingHandler { - private final Logger logger = LoggerFactory.getLogger(CoronaStatsCountryHandler.class); - - private CoronaStatsCountryConfiguration thingConfig = new CoronaStatsCountryConfiguration(); - - public CoronaStatsCountryHandler(Thing thing) { - super(thing); - } - - @Override - public void initialize() { - thingConfig = getConfigAs(CoronaStatsCountryConfiguration.class); - logger.debug("Initializing Corona Stats country handler for country code {}", thingConfig.getCountryCode()); - - if (thingConfig.isValid()) { - CoronaStatsWorldHandler handler = getBridgeHandler(); - if (handler == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge handler missing"); - } else { - updateStatus(ThingStatus.ONLINE); - } - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No valid country code given."); - } - } - - @Override - public void dispose() { - logger.debug("CoronaStats country handler disposes."); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - if (command instanceof RefreshType) { - refresh(); - } - } - - private void refresh() { - CoronaStatsWorldHandler handler = getBridgeHandler(); - if (handler != null) { - CoronaStats coronaStats = handler.getCoronaStats(); - if (coronaStats != null) { - notifyOnUpdate(coronaStats); - } - } - } - - private @Nullable CoronaStatsWorldHandler getBridgeHandler() { - Bridge bridge = getBridge(); - if (bridge != null) { - ThingHandler handler = bridge.getHandler(); - if (handler instanceof CoronaStatsWorldHandler) { - return (CoronaStatsWorldHandler) handler; - } - } - - return null; - } - - public void notifyOnUpdate(CoronaStats coronaStats) { - CoronaStatsCountry country = coronaStats.getCountry(thingConfig.getCountryCode()); - if (country == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Country not found"); - return; - } - - updateStatus(ThingStatus.ONLINE); - updateProperties(country.getProperties()); - - country.getChannelsStateMap().forEach(this::updateState); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.coronastats.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.coronastats.internal.config.CoronaStatsCountryConfiguration; +import org.openhab.binding.coronastats.internal.dto.CoronaStats; +import org.openhab.binding.coronastats.internal.dto.CoronaStatsCountry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link CoronaStatsCountryHandler} is the handler for country thing + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class CoronaStatsCountryHandler extends BaseThingHandler { + private final Logger logger = LoggerFactory.getLogger(CoronaStatsCountryHandler.class); + + private CoronaStatsCountryConfiguration thingConfig = new CoronaStatsCountryConfiguration(); + + public CoronaStatsCountryHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + thingConfig = getConfigAs(CoronaStatsCountryConfiguration.class); + logger.debug("Initializing Corona Stats country handler for country code {}", thingConfig.getCountryCode()); + + if (thingConfig.isValid()) { + CoronaStatsWorldHandler handler = getBridgeHandler(); + if (handler == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge handler missing"); + } else { + updateStatus(ThingStatus.ONLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No valid country code given."); + } + } + + @Override + public void dispose() { + logger.debug("CoronaStats country handler disposes."); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + refresh(); + } + } + + private void refresh() { + CoronaStatsWorldHandler handler = getBridgeHandler(); + if (handler != null) { + CoronaStats coronaStats = handler.getCoronaStats(); + if (coronaStats != null) { + notifyOnUpdate(coronaStats); + } + } + } + + private @Nullable CoronaStatsWorldHandler getBridgeHandler() { + Bridge bridge = getBridge(); + if (bridge != null) { + ThingHandler handler = bridge.getHandler(); + if (handler instanceof CoronaStatsWorldHandler) { + return (CoronaStatsWorldHandler) handler; + } + } + + return null; + } + + public void notifyOnUpdate(CoronaStats coronaStats) { + CoronaStatsCountry country = coronaStats.getCountry(thingConfig.getCountryCode()); + if (country == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Country not found"); + return; + } + + updateStatus(ThingStatus.ONLINE); + updateProperties(country.getProperties()); + + country.getChannelsStateMap().forEach(this::updateState); + } +} diff --git a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/handler/CoronaStatsWorldHandler.java b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/handler/CoronaStatsWorldHandler.java index 8fccba708fecf..c407e40525af2 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/handler/CoronaStatsWorldHandler.java +++ b/bundles/org.openhab.binding.coronastats/src/main/java/org/openhab/binding/coronastats/internal/handler/CoronaStatsWorldHandler.java @@ -1,219 +1,219 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.coronastats.internal.handler; - -import java.net.URI; -import java.util.Set; -import java.net.SocketTimeoutException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.client.util.BufferingResponseListener; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.coronastats.internal.CoronaStatsPollingException; -import org.openhab.binding.coronastats.internal.config.CoronaStatsWorldConfiguration; -import org.openhab.binding.coronastats.internal.dto.CoronaStats; -import org.openhab.binding.coronastats.internal.dto.CoronaStatsWorld; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link CoronaStatsWorldHandler} is the handler for bridge thing - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class CoronaStatsWorldHandler extends BaseBridgeHandler { - private static final String CORONASTATS_URL = "https://corona-stats.online/?format=json"; - - private final Logger logger = LoggerFactory.getLogger(CoronaStatsWorldHandler.class); - - private CoronaStatsWorldConfiguration worldConfig = new CoronaStatsWorldConfiguration(); - private @Nullable ScheduledFuture pollingJob; - private @Nullable CoronaStats coronaStats; - private final Set countryListeners = ConcurrentHashMap.newKeySet(); - private final HttpClient client; - private final Gson gson = new Gson(); - - public CoronaStatsWorldHandler(Bridge bridge, HttpClient client) { - super(bridge); - this.client = client; - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - if (command instanceof RefreshType) { - final CoronaStats localCoronaStats = coronaStats; - if (localCoronaStats != null) { - notifyOnUpdate(localCoronaStats); - } - } - } - - @Override - public void initialize() { - logger.debug("Initializing Corona Stats bridge handler"); - worldConfig = getConfigAs(CoronaStatsWorldConfiguration.class); - - if (worldConfig.isValid()) { - startPolling(); - updateStatus(ThingStatus.UNKNOWN); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Refresh interval has to be at least 15 minutes."); - } - } - - @Override - public void dispose() { - logger.debug("Handler disposed."); - stopPolling(); - } - - private void startPolling() { - final ScheduledFuture localPollingJob = this.pollingJob; - if (localPollingJob == null || localPollingJob.isCancelled()) { - logger.debug("Start polling."); - pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, worldConfig.refresh, TimeUnit.MINUTES); - } - } - - private void stopPolling() { - final ScheduledFuture localPollingJob = this.pollingJob; - if (localPollingJob != null && !localPollingJob.isCancelled()) { - logger.debug("Stop polling."); - localPollingJob.cancel(true); - pollingJob = null; - } - } - - private void poll() { - logger.debug("Polling"); - requestRefresh().handle((resultCoronaStats, pollException) -> { - if (resultCoronaStats == null) { - if (pollException == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - pollException.getMessage()); - } - } else { - updateStatus(ThingStatus.ONLINE); - notifyOnUpdate(resultCoronaStats); - } - - return null; - }); - } - - private CompletableFuture<@Nullable CoronaStats> requestRefresh() { - CompletableFuture<@Nullable CoronaStats> f = new CompletableFuture<>(); - Request request = client.newRequest(URI.create(CORONASTATS_URL)); - - request.method(HttpMethod.GET).timeout(2000, TimeUnit.SECONDS).send(new BufferingResponseListener() { - @NonNullByDefault({}) - @Override - public void onComplete(Result result) { - final HttpResponse response = (HttpResponse) result.getResponse(); - if (result.getFailure() != null) { - Throwable e = result.getFailure(); - if (e instanceof SocketTimeoutException || e instanceof TimeoutException) { - f.completeExceptionally(new CoronaStatsPollingException("Request timeout", e)); - } else { - f.completeExceptionally(new CoronaStatsPollingException("Request failed", e)); - } - } else if (response.getStatus() != 200) { - f.completeExceptionally(new CoronaStatsPollingException(getContentAsString())); - } else { - try { - CoronaStats coronaStatsJSON = gson.fromJson(getContentAsString(), CoronaStats.class); - f.complete(coronaStatsJSON); - } catch (JsonSyntaxException parseException) { - logger.error("Parsing failed: {}", parseException.getMessage()); - f.completeExceptionally(new CoronaStatsPollingException("Parsing of response failed")); - } - } - } - }); - - return f; - } - - @Override - public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { - if (childHandler instanceof CoronaStatsCountryHandler) { - logger.debug("Register thing listener."); - final CoronaStatsCountryHandler listener = (CoronaStatsCountryHandler) childHandler; - if (countryListeners.add(listener)) { - final CoronaStats localCoronaStats = coronaStats; - if (localCoronaStats != null) { - listener.notifyOnUpdate(localCoronaStats); - } - } else { - logger.warn("Tried to add listener {} but it was already present. This is probably an error.", - childHandler); - } - } - } - - @Override - public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { - if (childHandler instanceof CoronaStatsCountryHandler) { - logger.debug("Unregister thing listener."); - if (!countryListeners.remove((CoronaStatsCountryHandler) childHandler)) { - logger.warn("Tried to remove listener {} but it was not registered. This is probably an error.", - childHandler); - } - } - } - - public void notifyOnUpdate(@Nullable CoronaStats newCoronaStats) { - if (newCoronaStats != null) { - coronaStats = newCoronaStats; - - CoronaStatsWorld world = newCoronaStats.getWorld(); - if (world == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "World stats not found"); - return; - } - - world.getChannelsStateMap().forEach(this::updateState); - countryListeners.forEach(listener -> listener.notifyOnUpdate(newCoronaStats)); - } - } - - public @Nullable CoronaStats getCoronaStats() { - return coronaStats; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.coronastats.internal.handler; + +import java.net.SocketTimeoutException; +import java.net.URI; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.util.BufferingResponseListener; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.coronastats.internal.CoronaStatsPollingException; +import org.openhab.binding.coronastats.internal.config.CoronaStatsWorldConfiguration; +import org.openhab.binding.coronastats.internal.dto.CoronaStats; +import org.openhab.binding.coronastats.internal.dto.CoronaStatsWorld; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +/** + * The {@link CoronaStatsWorldHandler} is the handler for bridge thing + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class CoronaStatsWorldHandler extends BaseBridgeHandler { + private static final String CORONASTATS_URL = "https://corona-stats.online/?format=json"; + + private final Logger logger = LoggerFactory.getLogger(CoronaStatsWorldHandler.class); + + private CoronaStatsWorldConfiguration worldConfig = new CoronaStatsWorldConfiguration(); + private @Nullable ScheduledFuture pollingJob; + private @Nullable CoronaStats coronaStats; + private final Set countryListeners = ConcurrentHashMap.newKeySet(); + private final HttpClient client; + private final Gson gson = new Gson(); + + public CoronaStatsWorldHandler(Bridge bridge, HttpClient client) { + super(bridge); + this.client = client; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + final CoronaStats localCoronaStats = coronaStats; + if (localCoronaStats != null) { + notifyOnUpdate(localCoronaStats); + } + } + } + + @Override + public void initialize() { + logger.debug("Initializing Corona Stats bridge handler"); + worldConfig = getConfigAs(CoronaStatsWorldConfiguration.class); + + if (worldConfig.isValid()) { + startPolling(); + updateStatus(ThingStatus.UNKNOWN); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Refresh interval has to be at least 15 minutes."); + } + } + + @Override + public void dispose() { + logger.debug("Handler disposed."); + stopPolling(); + } + + private void startPolling() { + final ScheduledFuture localPollingJob = this.pollingJob; + if (localPollingJob == null || localPollingJob.isCancelled()) { + logger.debug("Start polling."); + pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, worldConfig.refresh, TimeUnit.MINUTES); + } + } + + private void stopPolling() { + final ScheduledFuture localPollingJob = this.pollingJob; + if (localPollingJob != null && !localPollingJob.isCancelled()) { + logger.debug("Stop polling."); + localPollingJob.cancel(true); + pollingJob = null; + } + } + + private void poll() { + logger.debug("Polling"); + requestRefresh().handle((resultCoronaStats, pollException) -> { + if (resultCoronaStats == null) { + if (pollException == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + pollException.getMessage()); + } + } else { + updateStatus(ThingStatus.ONLINE); + notifyOnUpdate(resultCoronaStats); + } + + return null; + }); + } + + private CompletableFuture<@Nullable CoronaStats> requestRefresh() { + CompletableFuture<@Nullable CoronaStats> f = new CompletableFuture<>(); + Request request = client.newRequest(URI.create(CORONASTATS_URL)); + + request.method(HttpMethod.GET).timeout(2000, TimeUnit.SECONDS).send(new BufferingResponseListener() { + @NonNullByDefault({}) + @Override + public void onComplete(Result result) { + final HttpResponse response = (HttpResponse) result.getResponse(); + if (result.getFailure() != null) { + Throwable e = result.getFailure(); + if (e instanceof SocketTimeoutException || e instanceof TimeoutException) { + f.completeExceptionally(new CoronaStatsPollingException("Request timeout", e)); + } else { + f.completeExceptionally(new CoronaStatsPollingException("Request failed", e)); + } + } else if (response.getStatus() != 200) { + f.completeExceptionally(new CoronaStatsPollingException(getContentAsString())); + } else { + try { + CoronaStats coronaStatsJSON = gson.fromJson(getContentAsString(), CoronaStats.class); + f.complete(coronaStatsJSON); + } catch (JsonSyntaxException parseException) { + logger.error("Parsing failed: {}", parseException.getMessage()); + f.completeExceptionally(new CoronaStatsPollingException("Parsing of response failed")); + } + } + } + }); + + return f; + } + + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof CoronaStatsCountryHandler) { + logger.debug("Register thing listener."); + final CoronaStatsCountryHandler listener = (CoronaStatsCountryHandler) childHandler; + if (countryListeners.add(listener)) { + final CoronaStats localCoronaStats = coronaStats; + if (localCoronaStats != null) { + listener.notifyOnUpdate(localCoronaStats); + } + } else { + logger.warn("Tried to add listener {} but it was already present. This is probably an error.", + childHandler); + } + } + } + + @Override + public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof CoronaStatsCountryHandler) { + logger.debug("Unregister thing listener."); + if (!countryListeners.remove((CoronaStatsCountryHandler) childHandler)) { + logger.warn("Tried to remove listener {} but it was not registered. This is probably an error.", + childHandler); + } + } + } + + public void notifyOnUpdate(@Nullable CoronaStats newCoronaStats) { + if (newCoronaStats != null) { + coronaStats = newCoronaStats; + + CoronaStatsWorld world = newCoronaStats.getWorld(); + if (world == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "World stats not found"); + return; + } + + world.getChannelsStateMap().forEach(this::updateState); + countryListeners.forEach(listener -> listener.notifyOnUpdate(newCoronaStats)); + } + } + + public @Nullable CoronaStats getCoronaStats() { + return coronaStats; + } +} diff --git a/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/binding/binding.xml index 64f37199e739c..626172becc8c5 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/binding/binding.xml @@ -1,10 +1,10 @@ - - - - CoronaStats Binding - This is a binding for accessing data from https://corona-stats.online/ website. - Johannes Ott - - + + + + CoronaStats Binding + This is a binding for accessing data from https://corona-stats.online/ website. + Johannes Ott + + diff --git a/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/channel-type.xml b/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/channel-type.xml index cad00e91c2b66..93b8f68affd00 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/channel-type.xml +++ b/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/channel-type.xml @@ -1,61 +1,61 @@ - - - - - Number - - - - - - Number - - - - - - Number - - - - - - Number - - - - - - Number - - - - - - Number - - - - - - Number - - - - - - Number - - - - - - DateTime - - - - - + + + + + Number:Dimensionless + + + + + + Number:Dimensionless + + + + + + Number:Dimensionless + + + + + + Number:Dimensionless + + + + + + Number:Dimensionless + + + + + + Number:Dimensionless + + + + + + Number:Dimensionless + + + + + + Number:Dimensionless + + + + + + DateTime + + + + + diff --git a/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/country.xml b/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/country.xml index 27fd6e7e45441..de88d4f09ce77 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/country.xml +++ b/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/country.xml @@ -1,38 +1,38 @@ - - - - - - - - - - Corona statistics for a specific country - - - - - - - - - - - - - - - - - - - - - 2-letter Country Code - - - - + + + + + + + + + + Corona statistics for a specific country + + + + + + + + + + + + + + + + + + + + + 2-letter Country Code + + + + diff --git a/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/world.xml b/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/world.xml index 7c4c093b0df86..ef8e4bbcca1a6 100644 --- a/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/world.xml +++ b/bundles/org.openhab.binding.coronastats/src/main/resources/ESH-INF/thing/world.xml @@ -1,30 +1,30 @@ - - - - - - Bridge for accessing data from https://corona-stats.online/ website and representing world statistics. - - - - - - - - - - - - - - 30 - - Time between two API requests in minutes. Minimum 15 minutes. - - - - - + + + + + + Bridge for accessing data from https://corona-stats.online/ website and representing world statistics. + + + + + + + + + + + + + + 30 + + Time between two API requests in minutes. Minimum 15 minutes. + + + + + diff --git a/bundles/org.openhab.binding.daikin/README.md b/bundles/org.openhab.binding.daikin/README.md index 6631527058765..caeff8f2315d5 100644 --- a/bundles/org.openhab.binding.daikin/README.md +++ b/bundles/org.openhab.binding.daikin/README.md @@ -1,11 +1,11 @@ # Daikin Binding The Daikin binding allows you to control your Daikin air conditioning units with openHAB. -In order to do so, your Daikin air conditioning unit must have a BRP072A42 or BRP15B61 WiFi adapter installed. +In order to do so, your Daikin air conditioning unit must have a BRP072A42, BRP072C42 or BRP15B61 WiFi adapter installed. ## Supported Things -Daikin air conditioning units with a BRP072A42 or BRP15B61 installed. +Daikin air conditioning units with a BRP069B41, BRP072A42, BRP072C42 or BRP15B61 installed. This may work with the older KRP series of wired adapters, but has not been tested with them. ## Discovery @@ -13,15 +13,26 @@ This may work with the older KRP series of wired adapters, but has not been test This add-on will broadcast messages on your local network looking for Daikin air conditioning units and adding them to the queue of new items discovered. You can also manually add a new item if you know the IP address. +### BRP072C42 adapter discovery + +A BRP072C42 adapter requires a registered UUID to authenticate. Upon discovery, a UUID will be generated but the adapter's key must be entered in the Thing configuration to complete the UUID registration. + ## Thing Configuration -* host - The hostname of the Daikin air conditioner. Typically you'd use an IP address such as `192.168.0.5` for this field. -* refresh - The frequency with which to refresh information from the Daikin air conditioner specified in seconds. Defaults to 60 seconds. +* `host` - The hostname of the Daikin air conditioner. Typically you'd use an IP address such as `192.168.0.5` for this field. +* `refresh` - The frequency with which to refresh information from the Daikin air conditioner specified in seconds. Defaults to 60 seconds. + +### Additional Thing configurations for BRP072C42 adapter + +* `secure` - Must be set to true for BRP072C42 to access it through https. +* `uuid` - A UUID used to access the BRP072C42 adapter. A handy UUID generator can be found at https://www.uuidgenerator.net/. +* `key` - The 13-digit key from the Daikin adapter. + ## Channels The temperature channels have a precision of one half degree Celsius. -For the BRP072A42: +For the BRP072A42 and BRP072C42: | Channel Name | Description | |--------------|---------------------------------------------------------------------------------------------| @@ -31,9 +42,36 @@ For the BRP072A42: | outdoortemp | The outdoor temperature as measured by the external part of the air conditioning system. May not be available when unit is off. | | humidity | The indoor humidity as measured by the unit. This is not available on all units. | | mode | The mode set for the unit (AUTO, DEHUMIDIFIER, COLD, HEAT, FAN) | -| homekit mode | A mode that is compatible with homekit/alexa/google home (off, auto, heat, cool) | +| homekitmode | A mode that is compatible with homekit/alexa/google home (off, auto, heat, cool). Not tested for BRP069B41 | | fanspeed | The fan speed set for the unit (AUTO, SILENCE, LEVEL_1, LEVEL_2, LEVEL_3, LEVEL_4, LEVEL_5) | | fandir | The fan blade direction (STOPPED, VERTICAL, HORIZONTAL, VERTICAL_AND_HORIZONTAL) | +| cmpfrequency | The compressor frequency | +| specialmode | The special mode currently active (OFF, STREAMER, ECO, POWERFUL, POWERFUL & STREAMER, ECO & STREAMER). Not all modes might be available on the unit. | +| specialmode-powerful | Turns the powerful mode on/off for the air conditioning unit. | +| energyheatingcurrentyear-1 | The energy consumption when heating for current year January | +| energyheatingcurrentyear-2 | The energy consumption when heating for current year February | +| energyheatingcurrentyear-3 | The energy consumption when heating for current year March | +| energyheatingcurrentyear-4 | The energy consumption when heating for current year April | +| energyheatingcurrentyear-5 | The energy consumption when heating for current year May | +| energyheatingcurrentyear-6 | The energy consumption when heating for current year June | +| energyheatingcurrentyear-7 | The energy consumption when heating for current year July | +| energyheatingcurrentyear-8 | The energy consumption when heating for current year August | +| energyheatingcurrentyear-9 | The energy consumption when heating for current year September | +| energyheatingcurrentyear-10| The energy consumption when heating for current year October | +| energyheatingcurrentyear-11| The energy consumption when heating for current year November | +| energyheatingcurrentyear-12| The energy consumption when heating for current year December | +| energycoolingcurrentyear-1 | The energy consumption when cooling for current year January | +| energycoolingcurrentyear-2 | The energy consumption when cooling for current year February | +| energycoolingcurrentyear-3 | The energy consumption when cooling for current year March | +| energycoolingcurrentyear-4 | The energy consumption when cooling for current year April | +| energycoolingcurrentyear-5 | The energy consumption when cooling for current year May | +| energycoolingcurrentyear-6 | The energy consumption when cooling for current year June | +| energycoolingcurrentyear-7 | The energy consumption when cooling for current year July | +| energycoolingcurrentyear-8 | The energy consumption when cooling for current year August | +| energycoolingcurrentyear-9 | The energy consumption when cooling for current year September | +| energycoolingcurrentyear-10| The energy consumption when cooling for current year October | +| energycoolingcurrentyear-11| The energy consumption when cooling for current year November | +| energycoolingcurrentyear-12| The energy consumption when cooling for current year December | For the BRP15B61: @@ -44,7 +82,7 @@ For the BRP15B61: | indoortemp | The indoor temperature as measured by the unit. | | outdoortemp | The outdoor temperature as measured by the external part of the air conditioning system. May not be available when unit is off. | | mode | The mode set for the unit (AUTO, DEHUMIDIFIER, COLD, HEAT, FAN) | -| homekit mode | A mode that is compatible with homekit/alexa/google home (off, auto, heat, cool) | +| homekitmode | A mode that is compatible with homekit/alexa/google home (off, auto, heat, cool) | | airbasefanspeed | The fan speed set for the unit (AUTO, AIRSIDE, LEVEL_1, LEVEL_2, LEVEL_3, LEVEL_4, LEVEL_5, AUTO_LEVEL_1, AUTO_LEVEL_2, AUTO_LEVEL_3, AUTO_LEVEL_4, AUTO_LEVEL_5) | | zone1 | Turns zone 1 on/off for the air conditioning unit (if a zone controller is installed.) | | zone2 | Turns zone 2 on/off for the air conditioning unit. | @@ -60,13 +98,19 @@ For the BRP15B61: daikin.things: ``` +// for BRP069B41 or BRP072A42 daikin:ac_unit:living_room_ac [ host="192.168.0.5" ] +// for BRP072C42 +daikin:ac_unit:living_room_ac [ host="192.168.0.5", secure=true, uuid="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", key="xxxxxxxxxxxxx" ] +// for Airbase (BRP15B61) daikin:airbase_ac_unit:living_room_ac [ host="192.168.0.5" ] ``` + daikin.items: ``` +// for BRP069B41, BRP072A42 or BRP072C42 Switch DaikinACUnit_Power { channel="daikin:ac_unit:living_room_ac:power" } Number:Temperature DaikinACUnit_SetPoint { channel="daikin:ac_unit:living_room_ac:settemp" } String DaikinACUnit_Mode { channel="daikin:ac_unit:living_room_ac:mode" } @@ -75,7 +119,16 @@ String DaikinACUnit_Fan { channel="daikin:ac_unit:living_room_ac:fanspeed" } String DaikinACUnit_Fan_Movement { channel="daikin:ac_unit:living_room_ac:fandir" } Number:Temperature DaikinACUnit_IndoorTemperature { channel="daikin:ac_unit:living_room_ac:indoortemp" } Number:Temperature DaikinACUnit_OutdoorTemperature { channel="daikin:ac_unit:living_room_ac:outdoortemp" } -# Additional items for BRP1B61 + + +// for Airbase (BRP15B61) +Switch DaikinACUnit_Power { channel="daikin:airbase_ac_unit:living_room_ac:power" } +Number:Temperature DaikinACUnit_SetPoint { channel="daikin:airbase_ac_unit:living_room_ac:settemp" } +String DaikinACUnit_Mode { channel="daikin:airbase_ac_unit:living_room_ac:mode" } +String DaikinACUnit_HomekitMode { channel="daikin:airbase_ac_unit:living_room_ac:homekitmode" } +String DaikinACUnit_Fan { channel="daikin:airbase_ac_unit:living_room_ac:fanspeed" } +Number:Temperature DaikinACUnit_IndoorTemperature { channel="daikin:airbase_ac_unit:living_room_ac:indoortemp" } +Number:Temperature DaikinACUnit_OutdoorTemperature { channel="daikin:airbase_ac_unit:living_room_ac:outdoortemp" } Switch DaikinACUnit_Zone1 { channel="daikin:airbase_ac_unit:living_room_ac:zone1" } Switch DaikinACUnit_Zone2 { channel="daikin:airbase_ac_unit:living_room_ac:zone2" } Switch DaikinACUnit_Zone3 { channel="daikin:airbase_ac_unit:living_room_ac:zone3" } @@ -90,13 +143,22 @@ Switch DaikinACUnit_Zone8 { channel="daikin:airbase_ac_unit:living_room_ac:zone8 daikin.sitemap: ``` +// for BRP069B41, BRP072A42 or BRP072C42 Switch item=DaikinACUnit_Power Setpoint item=DaikinACUnit_SetPoint visibility=[DaikinACUnit_Power==ON] Selection item=DaikinACUnit_Mode mappings=["AUTO"="Auto", "DEHUMIDIFIER"="Dehumidifier", "COLD"="Cold", "HEAT"="Heat", "FAN"="Fan"] visibility=[DaikinACUnit_Power==ON] Selection item=DaikinACUnit_Fan mappings=["AUTO"="Auto", "SILENCE"="Silence", "LEVEL_1"="Level 1", "LEVEL_2"="Level 2", "LEVEL_3"="Level 3", "LEVEL_4"="Level 4", "LEVEL_5"="Level 5"] visibility=[DaikinACUnit_Power==ON] +Selection item=DaikinACUnit_Fan_Movement mappings=["STOPPED"="Stopped", "VERTICAL"="Vertical", "HORIZONTAL"="Horizontal", "VERTICAL_AND_HORIZONTAL"="Vertical and Horizontal"] visibility=[DaikinACUnit_Power==ON] +Text item=DaikinACUnit_IndoorTemperature +Text item=DaikinACUnit_OutdoorTemperature + +// for Airbase (BRP15B61) +Switch item=DaikinACUnit_Power +Setpoint item=DaikinACUnit_SetPoint visibility=[DaikinACUnit_Power==ON] +Selection item=DaikinACUnit_Mode mappings=["AUTO"="Auto", "DEHUMIDIFIER"="Dehumidifier", "COLD"="Cold", "HEAT"="Heat", "FAN"="Fan"] visibility=[DaikinACUnit_Power==ON] +Selection item=DaikinACUnit_Fan visibility=[DaikinACUnit_Power==ON] Text item=DaikinACUnit_IndoorTemperature Text item=DaikinACUnit_OutdoorTemperature -# Additional items for BRP15B61 Switch item=DaikinACUnit_Zone1 visibility=[DaikinACUnit_Power==ON] Switch item=DaikinACUnit_Zone2 visibility=[DaikinACUnit_Power==ON] Switch item=DaikinACUnit_Zone3 visibility=[DaikinACUnit_Power==ON] diff --git a/bundles/org.openhab.binding.daikin/pom.xml b/bundles/org.openhab.binding.daikin/pom.xml index 4a52a1d92d6bf..de6bff7437a30 100644 --- a/bundles/org.openhab.binding.daikin/pom.xml +++ b/bundles/org.openhab.binding.daikin/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.daikin diff --git a/bundles/org.openhab.binding.daikin/src/main/feature/feature.xml b/bundles/org.openhab.binding.daikin/src/main/feature/feature.xml index 0406457d131c1..af3701df80b0b 100644 --- a/bundles/org.openhab.binding.daikin/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.daikin/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.daikin/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.daikin/${project.version} + diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinBindingConstants.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinBindingConstants.java index ce3935a552081..659fcb9827203 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinBindingConstants.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinBindingConstants.java @@ -46,6 +46,15 @@ public class DaikinBindingConstants { public static final String CHANNEL_AC_FAN_SPEED = "fanspeed"; public static final String CHANNEL_AC_FAN_DIR = "fandir"; public static final String CHANNEL_HUMIDITY = "humidity"; + public static final String CHANNEL_CMP_FREQ = "cmpfrequency"; + + // Prefix and channel id format for energy - currentyear + public static final String CHANNEL_ENERGY_HEATING_CURRENTYEAR_PREFIX = "energyheatingcurrentyear"; + public static final String CHANNEL_ENERGY_COOLING_CURRENTYEAR_PREFIX = "energycoolingcurrentyear"; + public static final String CHANNEL_ENERGY_STRING_FORMAT = "%s-%d"; + + public static final String CHANNEL_AC_SPECIALMODE = "specialmode"; + public static final String CHANNEL_AC_SPECIALMODE_POWERFUL = "specialmode-powerful"; // additional channels for Airbase Controller public static final String CHANNEL_AIRBASE_AC_FAN_SPEED = "airbasefanspeed"; diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinCommunicationException.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinCommunicationException.java index eff77e990bf5a..4d4c011533729 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinCommunicationException.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinCommunicationException.java @@ -14,12 +14,15 @@ import java.io.IOException; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * Exception for when an unexpected response is received from the Daikin controller. * * @author Tim Waterhouse - Initial contribution * */ +@NonNullByDefault public class DaikinCommunicationException extends IOException { private static final long serialVersionUID = 529232811860854017L; diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinCommunicationForbiddenException.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinCommunicationForbiddenException.java new file mode 100644 index 0000000000000..7424ce89625bd --- /dev/null +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinCommunicationForbiddenException.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.daikin.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Exception for when a 403 Forbidden error is received from the Daikin controller. + * + * @author Jimmy Tanagra - Initial contribution + * + */ +@NonNullByDefault +public class DaikinCommunicationForbiddenException extends DaikinCommunicationException { + + private static final long serialVersionUID = 1L; + + public DaikinCommunicationForbiddenException(String message) { + super(message); + } + + public DaikinCommunicationForbiddenException(Throwable ex) { + super(ex); + } + + public DaikinCommunicationForbiddenException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHandlerFactory.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHandlerFactory.java index de81dffab1580..be39a4a92d2f5 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHandlerFactory.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHandlerFactory.java @@ -14,6 +14,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; @@ -21,9 +22,9 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.openhab.binding.daikin.internal.handler.DaikinAcUnitHandler; import org.openhab.binding.daikin.internal.handler.DaikinAirbaseUnitHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; -import org.osgi.service.component.annotations.Activate; /** * The {@link DaikinHandlerFactory} is responsible for creating things and thing @@ -31,17 +32,20 @@ * * @author Tim Waterhouse - Initial contribution * @author Paul Smedley - Modifications to support Airbase Controllers - + * */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.daikin") @NonNullByDefault public class DaikinHandlerFactory extends BaseThingHandlerFactory { private final DaikinDynamicStateDescriptionProvider stateDescriptionProvider; + private final @Nullable HttpClient httpClient; @Activate - public DaikinHandlerFactory(@Reference DaikinDynamicStateDescriptionProvider stateDescriptionProvider) { + public DaikinHandlerFactory(@Reference DaikinDynamicStateDescriptionProvider stateDescriptionProvider, + @Reference DaikinHttpClientFactory httpClientFactory) { this.stateDescriptionProvider = stateDescriptionProvider; + this.httpClient = httpClientFactory.getHttpClient(); } @Override @@ -54,9 +58,9 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(DaikinBindingConstants.THING_TYPE_AC_UNIT)) { - return new DaikinAcUnitHandler(thing, stateDescriptionProvider); + return new DaikinAcUnitHandler(thing, stateDescriptionProvider, httpClient); } else if (thingTypeUID.equals(DaikinBindingConstants.THING_TYPE_AIRBASE_AC_UNIT)) { - return new DaikinAirbaseUnitHandler(thing, stateDescriptionProvider); + return new DaikinAirbaseUnitHandler(thing, stateDescriptionProvider, httpClient); } return null; } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHttpClientFactory.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHttpClientFactory.java new file mode 100644 index 0000000000000..b7b8bea5a0555 --- /dev/null +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHttpClientFactory.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.daikin.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; + +/** + * Factory class to create Jetty http clients + * + * @author Jimmy Tanagra - Initial contribution + */ +@NonNullByDefault +public interface DaikinHttpClientFactory { + + /** + * Returns the shared Jetty http client. You must not call any setter methods or {@code stop()} on it. + * The returned client is already started. + * + * @return the shared Jetty http client + */ + @Nullable + HttpClient getHttpClient(); +} diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHttpClientFactoryImpl.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHttpClientFactoryImpl.java new file mode 100644 index 0000000000000..f53c40e61eb73 --- /dev/null +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinHttpClientFactoryImpl.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.daikin.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Factory class to create Jetty web clients + * + * Some Daikin controllers communicate via https using a custom common name, + * and they are accessed using an ip address. + * + * The core HttpClientFactory creates a HttpClient that will fail because of this. + * This factory creates a HttpClient with SslContextFactory(true) + * which will accept any ssl certificate without checking for common name mismatches. + * + * @author Jimmy Tanagra - Initial contribution + */ +@Component +@NonNullByDefault +public class DaikinHttpClientFactoryImpl implements DaikinHttpClientFactory { + + private final Logger logger = LoggerFactory.getLogger(DaikinHttpClientFactoryImpl.class); + + private @Nullable HttpClient httpClient; + + @Deactivate + protected void deactivate() { + if (httpClient != null) { + try { + httpClient.stop(); + logger.debug("Daikin http client stopped"); + } catch (Exception e) { + logger.debug("error while stopping Daikin http client", e); + } + httpClient = null; + } + } + + @Override + public @Nullable HttpClient getHttpClient() { + initialize(); + return httpClient; + } + + private synchronized void initialize() { + if (httpClient == null) { + httpClient = new HttpClient(new SslContextFactory(true)); + try { + httpClient.start(); + logger.debug("Daikin http client started"); + } catch (Exception e) { + logger.warn("Could not start Daikin http client", e); + httpClient = null; + } + } + } +} diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java index 6a776d728c222..b6bd04d2a2c02 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/DaikinWebTargets.java @@ -15,17 +15,26 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import java.util.stream.IntStream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; import org.eclipse.smarthome.io.net.http.HttpUtil; +import org.openhab.binding.daikin.internal.api.BasicInfo; import org.openhab.binding.daikin.internal.api.ControlInfo; +import org.openhab.binding.daikin.internal.api.EnergyInfoYear; +import org.openhab.binding.daikin.internal.api.Enums.SpecialModeKind; import org.openhab.binding.daikin.internal.api.SensorInfo; -import org.openhab.binding.daikin.internal.api.airbase.AirbaseControlInfo; import org.openhab.binding.daikin.internal.api.airbase.AirbaseBasicInfo; +import org.openhab.binding.daikin.internal.api.airbase.AirbaseControlInfo; import org.openhab.binding.daikin.internal.api.airbase.AirbaseModelInfo; import org.openhab.binding.daikin.internal.api.airbase.AirbaseZoneInfo; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,14 +43,21 @@ * * @author Tim Waterhouse - Initial Contribution * @author Paul Smedley - Modifications to support Airbase Controllers + * @author Jimmy Tanagra - Add support for https and Daikin's uuid authentication * */ +@NonNullByDefault public class DaikinWebTargets { private static final int TIMEOUT_MS = 30000; + private String getBasicInfoUri; private String setControlInfoUri; private String getControlInfoUri; private String getSensorInfoUri; + private String registerUuidUri; + private String getEnergyInfoYearUri; + private String setSpecialModeUri; + private String setAirbaseControlInfoUri; private String getAirbaseControlInfoUri; private String getAirbaseSensorInfoUri; @@ -50,15 +66,26 @@ public class DaikinWebTargets { private String getAirbaseZoneInfoUri; private String setAirbaseZoneInfoUri; + private @Nullable String uuid; + private final @Nullable HttpClient httpClient; + private Logger logger = LoggerFactory.getLogger(DaikinWebTargets.class); - public DaikinWebTargets(String ipAddress) { - String baseUri = "http://" + ipAddress + "/"; + public DaikinWebTargets(@Nullable HttpClient httpClient, @Nullable String host, @Nullable Boolean secure, + @Nullable String uuid) { + this.httpClient = httpClient; + this.uuid = uuid; + + String baseUri = (secure != null && secure.booleanValue() ? "https://" : "http://") + host + "/"; + getBasicInfoUri = baseUri + "common/basic_info"; setControlInfoUri = baseUri + "aircon/set_control_info"; getControlInfoUri = baseUri + "aircon/get_control_info"; getSensorInfoUri = baseUri + "aircon/get_sensor_info"; + registerUuidUri = baseUri + "common/register_terminal"; + getEnergyInfoYearUri = baseUri + "aircon/get_year_power_ex"; + setSpecialModeUri = baseUri + "aircon/set_special_mode"; - //Daikin Airbase API + // Daikin Airbase API getAirbaseBasicInfoUri = baseUri + "skyfi/common/basic_info"; setAirbaseControlInfoUri = baseUri + "skyfi/aircon/set_control_info"; getAirbaseControlInfoUri = baseUri + "skyfi/aircon/get_control_info"; @@ -69,6 +96,11 @@ public DaikinWebTargets(String ipAddress) { } // Standard Daikin API + public BasicInfo getBasicInfo() throws DaikinCommunicationException { + String response = invoke(getBasicInfoUri); + return BasicInfo.parse(response); + } + public ControlInfo getControlInfo() throws DaikinCommunicationException { String response = invoke(getControlInfoUri); return ControlInfo.parse(response); @@ -84,7 +116,27 @@ public SensorInfo getSensorInfo() throws DaikinCommunicationException { return SensorInfo.parse(response); } - //Daikin Airbase API + public void registerUuid(String key) throws DaikinCommunicationException { + Map params = new HashMap<>(); + params.put("key", key); + String response = invoke(registerUuidUri, params); + logger.debug("registerUuid result: {}", response); + } + + public EnergyInfoYear getEnergyInfoYear() throws DaikinCommunicationException { + String response = invoke(getEnergyInfoYearUri); + return EnergyInfoYear.parse(response); + } + + public boolean setSpecialMode(SpecialModeKind specialModeKind, boolean state) throws DaikinCommunicationException { + Map queryParams = new HashMap<>(); + queryParams.put("spmode_kind", String.valueOf(specialModeKind.getValue())); + queryParams.put("set_spmode", state ? "1" : "0"); + String response = invoke(setSpecialModeUri, queryParams); + return !response.contains("ret=OK"); + } + + // Daikin Airbase API public AirbaseControlInfo getAirbaseControlInfo() throws DaikinCommunicationException { String response = invoke(getAirbaseControlInfoUri); return AirbaseControlInfo.parse(response); @@ -115,17 +167,11 @@ public AirbaseZoneInfo getAirbaseZoneInfo() throws DaikinCommunicationException return AirbaseZoneInfo.parse(response); } - public void setAirbaseZoneInfo(AirbaseZoneInfo zoneinfo, AirbaseModelInfo modelinfo) throws DaikinCommunicationException { - long count = IntStream.range(0, zoneinfo.zone.length).filter(idx -> zoneinfo.zone[idx]).count() + modelinfo.commonzone; - logger.debug("Number of open zones: \"{}\"", count); - + public void setAirbaseZoneInfo(AirbaseZoneInfo zoneinfo) throws DaikinCommunicationException { Map queryParams = zoneinfo.getParamString(); - if (count >= 1) { - invoke(setAirbaseZoneInfoUri, queryParams); - } + invoke(setAirbaseZoneInfoUri, queryParams); } - private String invoke(String uri) throws DaikinCommunicationException { return invoke(uri, new HashMap<>()); } @@ -136,7 +182,15 @@ private String invoke(String uri, Map params) throws DaikinCommu String response; synchronized (this) { try { - response = HttpUtil.executeUrl("GET", uriWithParams, TIMEOUT_MS); + if (httpClient != null) { + response = executeUrl(uriWithParams); + } else { + // a fall back method + logger.debug("Using HttpUtil fall scback"); + response = HttpUtil.executeUrl("GET", uriWithParams, TIMEOUT_MS); + } + } catch (DaikinCommunicationException ex) { + throw ex; } catch (IOException ex) { // Response will also be set to null if parsing in executeUrl fails so we use null here to make the // error check below consistent. @@ -145,13 +199,38 @@ private String invoke(String uri, Map params) throws DaikinCommu } if (response == null) { - throw new DaikinCommunicationException( - String.format("Daikin controller returned error while invoking %s", uriWithParams)); + throw new DaikinCommunicationException("Daikin controller returned error while invoking " + uriWithParams); } return response; } + private String executeUrl(String url) throws DaikinCommunicationException { + try { + Request request = httpClient.newRequest(url).method(HttpMethod.GET).timeout(TIMEOUT_MS, + TimeUnit.MILLISECONDS); + if (uuid != null) { + request.header("X-Daikin-uuid", uuid); + logger.debug("Header: X-Daikin-uuid: {}", uuid); + } + ContentResponse response = request.send(); + + if (response.getStatus() == HttpStatus.FORBIDDEN_403) { + throw new DaikinCommunicationForbiddenException("Daikin controller access denied. Check uuid/key."); + } + + if (response.getStatus() != HttpStatus.OK_200) { + logger.debug("Daikin controller HTTP status: {} - {}", response.getStatus(), response.getReason()); + } + + return response.getContentAsString(); + } catch (DaikinCommunicationException e) { + throw e; + } catch (Exception e) { + throw new DaikinCommunicationException("Daikin HTTP error", e); + } + } + private String paramsToQueryString(Map params) { if (params.isEmpty()) { return ""; diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/BasicInfo.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/BasicInfo.java new file mode 100644 index 0000000000000..fe65ee1de237d --- /dev/null +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/BasicInfo.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.daikin.internal.api; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Holds information from the basic_info call. + * + * @author Jimy Tanagra - Initial contribution + * + */ +@NonNullByDefault +public class BasicInfo { + private static final Logger logger = LoggerFactory.getLogger(BasicInfo.class); + + public String mac = ""; + public String ret = ""; + public String ssid = ""; + + private BasicInfo() { + } + + public static BasicInfo parse(String response) { + logger.debug("Parsing string: \"{}\"", response); + + Map responseMap = InfoParser.parse(response); + + BasicInfo info = new BasicInfo(); + info.mac = Optional.ofNullable(responseMap.get("mac")).orElse(""); + info.ret = Optional.ofNullable(responseMap.get("ret")).orElse(""); + info.ssid = Optional.ofNullable(responseMap.get("ssid")).orElse(""); + return info; + } + + public Map getParamString() { + Map params = new HashMap<>(); + params.put("ssid", ssid); + return params; + } +} diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/ControlInfo.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/ControlInfo.java index 3f2a1cce57ebe..9ead5b570a998 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/ControlInfo.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/ControlInfo.java @@ -12,15 +12,15 @@ */ package org.openhab.binding.daikin.internal.api; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.daikin.internal.api.Enums.FanMovement; import org.openhab.binding.daikin.internal.api.Enums.FanSpeed; import org.openhab.binding.daikin.internal.api.Enums.Mode; +import org.openhab.binding.daikin.internal.api.Enums.SpecialMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,10 +31,11 @@ * @author Paul Smedley - mods for Daikin Airbase * */ +@NonNullByDefault public class ControlInfo { - private static final Logger LOGGER = LoggerFactory.getLogger(ControlInfo.class); + private static final Logger logger = LoggerFactory.getLogger(ControlInfo.class); - public String ret; + public String ret = ""; public boolean power = false; public Mode mode = Mode.AUTO; /** Degrees in Celsius. */ @@ -43,33 +44,30 @@ public class ControlInfo { public FanMovement fanMovement = FanMovement.STOPPED; /* Not supported by all units. Sets the target humidity for dehumidifying. */ public Optional targetHumidity = Optional.empty(); + public SpecialMode specialMode = SpecialMode.UNKNOWN; private ControlInfo() { } public static ControlInfo parse(String response) { - LOGGER.debug("Parsing string: \"{}\"", response); + logger.debug("Parsing string: \"{}\"", response); - Map responseMap = Arrays.asList(response.split(",")).stream().filter(kv -> kv.contains("=")) - .map(kv -> { - String[] keyValue = kv.split("="); - String key = keyValue[0]; - String value = keyValue.length > 1 ? keyValue[1] : ""; - return new String[] { key, value }; - }).collect(Collectors.toMap(x -> x[0], x -> x[1])); + Map responseMap = InfoParser.parse(response); ControlInfo info = new ControlInfo(); - info.ret = responseMap.get("ret"); + info.ret = Optional.ofNullable(responseMap.get("ret")).orElse(""); info.power = "1".equals(responseMap.get("pow")); - info.mode = Optional.ofNullable(responseMap.get("mode")).flatMap(value -> parseInt(value)) + info.mode = Optional.ofNullable(responseMap.get("mode")).flatMap(value -> InfoParser.parseInt(value)) .map(value -> Mode.fromValue(value)).orElse(Mode.AUTO); - info.temp = Optional.ofNullable(responseMap.get("stemp")).flatMap(value -> parseDouble(value)); + info.temp = Optional.ofNullable(responseMap.get("stemp")).flatMap(value -> InfoParser.parseDouble(value)); info.fanSpeed = Optional.ofNullable(responseMap.get("f_rate")).map(value -> FanSpeed.fromValue(value)) .orElse(FanSpeed.AUTO); - info.fanMovement = Optional.ofNullable(responseMap.get("f_dir")).flatMap(value -> parseInt(value)) + info.fanMovement = Optional.ofNullable(responseMap.get("f_dir")).flatMap(value -> InfoParser.parseInt(value)) .map(value -> FanMovement.fromValue(value)).orElse(FanMovement.STOPPED); - info.targetHumidity = Optional.ofNullable(responseMap.get("shum")).flatMap(value -> parseInt(value)); + info.targetHumidity = Optional.ofNullable(responseMap.get("shum")).flatMap(value -> InfoParser.parseInt(value)); + info.specialMode = Optional.ofNullable(responseMap.get("adv")).map(value -> SpecialMode.fromValue(value)) + .orElse(SpecialMode.UNKNOWN); return info; } @@ -84,20 +82,4 @@ public Map getParamString() { return params; } - - private static Optional parseDouble(String value) { - try { - return Optional.of(Double.parseDouble(value)); - } catch (NumberFormatException e) { - return Optional.empty(); - } - } - - private static Optional parseInt(String value) { - try { - return Optional.of(Integer.parseInt(value)); - } catch (Exception e) { - return Optional.empty(); - } - } } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/EnergyInfoYear.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/EnergyInfoYear.java new file mode 100644 index 0000000000000..009e2a1e59180 --- /dev/null +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/EnergyInfoYear.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.daikin.internal.api; + +import java.util.Map; +import java.util.Optional; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Holds information from the get_year_power_ex call. + * + * @author Lukas Agethen - Initial contribution + * + */ +@NonNullByDefault +public class EnergyInfoYear { + private static final Logger logger = LoggerFactory.getLogger(EnergyInfoYear.class); + + public Optional energyHeatingThisYear = Optional.empty(); + + public Optional energyCoolingThisYear = Optional.empty(); + + private EnergyInfoYear() { + } + + public static EnergyInfoYear parse(String response) { + logger.debug("Parsing string: \"{}\"", response); + + Map responseMap = InfoParser.parse(response); + + EnergyInfoYear info = new EnergyInfoYear(); + info.energyHeatingThisYear = Optional.ofNullable(responseMap.get("curr_year_heat")) + .flatMap(value -> InfoParser.parseArrayofInt(value, 12)); + + info.energyCoolingThisYear = Optional.ofNullable(responseMap.get("curr_year_cool")) + .flatMap(value -> InfoParser.parseArrayofInt(value, 12)); + + return info; + } +} diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java index 8224460363f29..a3e36648b78da 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/Enums.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.daikin.internal.api; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,8 +20,10 @@ * Container class for enums related to Daikin A/C systems * * @author Tim Waterhouse - Initial contribution + * @author Lukas Agethen - Add special modes * */ +@NonNullByDefault public class Enums { public enum Mode { UNKNOWN(-1), @@ -119,10 +122,10 @@ public static FanMovement fromValue(int value) { } public enum HomekitMode { - AUTO ("auto"), - COOL ("cool"), - HEAT ("heat"), - OFF ("off"); + AUTO("auto"), + COOL("cool"), + HEAT("heat"), + OFF("off"); private static final Logger LOGGER = LoggerFactory.getLogger(HomekitMode.class); private final String value; @@ -136,4 +139,74 @@ public String getValue() { } } + public enum SpecialMode { + STREAMER("13"), + ECO("12"), + POWERFUL("2"), + POWERFUL_STREAMER("2/13"), + ECO_STREAMER("12/13"), + OFF(""), + UNKNOWN("??"); + + private static final Logger LOGGER = LoggerFactory.getLogger(SpecialMode.class); + private final String value; + + SpecialMode(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public boolean isPowerfulActive() { + return this.equals(POWERFUL) || this.equals(POWERFUL_STREAMER); + } + + public boolean isUndefined() { + return this.equals(UNKNOWN); + } + + public static SpecialMode fromValue(String value) { + for (SpecialMode m : SpecialMode.values()) { + if (m.getValue().equals(value)) { + return m; + } + } + LOGGER.debug("Unexpected SpecialMode value of \"{}\"", value); + + // Default to UNKNOWN + return UNKNOWN; + } + } + + public enum SpecialModeKind { + UNKNOWN(-1), + STREAMER(0), + POWERFUL(1), + ECO(2); + + private static final Logger LOGGER = LoggerFactory.getLogger(SpecialModeKind.class); + private final int value; + + SpecialModeKind(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static SpecialModeKind fromValue(int value) { + for (SpecialModeKind m : SpecialModeKind.values()) { + if (m.getValue() == value) { + return m; + } + } + LOGGER.debug("Unexpected SpecialModeKind value of \"{}\"", value); + + // Default to UNKNOWN + return UNKNOWN; + } + } } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/InfoParser.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/InfoParser.java new file mode 100644 index 0000000000000..65e2d099bfd83 --- /dev/null +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/InfoParser.java @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.daikin.internal.api; + +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Class for parsing the comma separated values and array values returned by the Daikin Controller. + * + * @author Jimmy Tanagra - Initial Contribution + * + */ +@NonNullByDefault +public class InfoParser { + private InfoParser() { + } + + public static Map parse(String response) { + return Stream.of(response.split(",")).filter(kv -> kv.contains("=")).map(kv -> { + String[] keyValue = kv.split("="); + String key = keyValue[0]; + String value = keyValue.length > 1 ? keyValue[1] : ""; + return new String[] { key, value }; + }).collect(Collectors.toMap(x -> x[0], x -> x[1])); + } + + public static Optional parseDouble(String value) { + if ("-".equals(value)) { + return Optional.empty(); + } + try { + return Optional.of(Double.parseDouble(value)); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } + + public static Optional parseInt(String value) { + if ("-".equals(value)) { + return Optional.empty(); + } + try { + return Optional.of(Integer.parseInt(value)); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } + + public static Optional parseArrayofInt(String value) { + if ("-".equals(value)) { + return Optional.empty(); + } + try { + return Optional.of(Stream.of(value.split("/")).map(val -> Integer.parseInt(val)).toArray(Integer[]::new)); + + } catch (NumberFormatException e) { + return Optional.empty(); + } + } + + public static Optional parseArrayofInt(String value, int expectedArraySize) { + Optional result = parseArrayofInt(value); + if (result.isPresent() && result.get().length == expectedArraySize) { + return result; + } + return Optional.empty(); + } +} diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/SensorInfo.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/SensorInfo.java index d4124016565ff..f1969e7c54153 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/SensorInfo.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/SensorInfo.java @@ -12,56 +12,44 @@ */ package org.openhab.binding.daikin.internal.api; +import java.util.Map; import java.util.Optional; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Holds information from the get_sensor_info call. * * @author Tim Waterhouse - Initial contribution * */ +@NonNullByDefault public class SensorInfo { - public Optional indoortemp; - public Optional indoorhumidity; - public Optional outdoortemp; + private static final Logger logger = LoggerFactory.getLogger(SensorInfo.class); + + public Optional indoortemp = Optional.empty(); + public Optional indoorhumidity = Optional.empty(); + public Optional outdoortemp = Optional.empty(); + public Optional compressorfrequency = Optional.empty(); private SensorInfo() { } public static SensorInfo parse(String response) { - SensorInfo info = new SensorInfo(); - info.indoortemp = Optional.empty(); - info.indoorhumidity = Optional.empty(); - info.outdoortemp = Optional.empty(); + logger.debug("Parsing string: \"{}\"", response); - for (String keyValuePair : response.split(",")) { - if (keyValuePair.contains("=")) { - String[] keyValue = keyValuePair.split("="); - String key = keyValue[0]; - String value = keyValue.length > 1 ? keyValue[1] : ""; + Map responseMap = InfoParser.parse(response); - switch (key) { - case "htemp": - // "-" indicates no value - if (!"-".equals(value)) { - info.indoortemp = Optional.of(Double.parseDouble(value)); - } - break; - case "hhum": - // "-" indicates no value - if (!"-".equals(value)) { - info.indoorhumidity = Optional.of(Double.parseDouble(value)); - } - break; - case "otemp": - // "-" indicates no value - if (!"-".equals(value)) { - info.outdoortemp = Optional.of(Double.parseDouble(value)); - } - break; - } - } - } + SensorInfo info = new SensorInfo(); + info.indoortemp = Optional.ofNullable(responseMap.get("htemp")).flatMap(value -> InfoParser.parseDouble(value)); + info.indoorhumidity = Optional.ofNullable(responseMap.get("hhum")) + .flatMap(value -> InfoParser.parseDouble(value)); + info.outdoortemp = Optional.ofNullable(responseMap.get("otemp")) + .flatMap(value -> InfoParser.parseDouble(value)); + info.compressorfrequency = Optional.ofNullable(responseMap.get("cmpfreq")) + .flatMap(value -> InfoParser.parseDouble(value)); return info; } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseBasicInfo.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseBasicInfo.java index 603bbd0b22f47..344bf47e4532a 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseBasicInfo.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseBasicInfo.java @@ -12,10 +12,12 @@ */ package org.openhab.binding.daikin.internal.api.airbase; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.stream.Collectors; +import java.util.Optional; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.daikin.internal.api.InfoParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,34 +27,34 @@ * @author Paul Smedley - Initial contribution * */ +@NonNullByDefault public class AirbaseBasicInfo { - private static final Logger LOGGER = LoggerFactory.getLogger(AirbaseBasicInfo.class); + private static final Logger logger = LoggerFactory.getLogger(AirbaseBasicInfo.class); - public String ssid; + public String mac = ""; + public String ret = ""; + public String ssid = ""; private AirbaseBasicInfo() { } public static AirbaseBasicInfo parse(String response) { - LOGGER.debug("Parsing string: \"{}\"", response); + logger.debug("Parsing string: \"{}\"", response); - Map responseMap = Arrays.asList(response.split(",")).stream().filter(kv -> kv.contains("=")) - .map(kv -> { - String[] keyValue = kv.split("="); - String key = keyValue[0]; - String value = keyValue.length > 1 ? keyValue[1] : ""; - return new String[] { key, value }; - }).collect(Collectors.toMap(x -> x[0], x -> x[1])); + Map responseMap = InfoParser.parse(response); AirbaseBasicInfo info = new AirbaseBasicInfo(); - info.ssid = responseMap.get("ssid"); + info.mac = Optional.ofNullable(responseMap.get("mac")).orElse(""); + info.ret = Optional.ofNullable(responseMap.get("ret")).orElse(""); + info.ssid = Optional.ofNullable(responseMap.get("ssid")).orElse(""); return info; } public Map getParamString() { Map params = new HashMap<>(); - params.put("ssid", ssid); + if (!"".equals(ssid)) { + params.put("ssid", ssid); + } return params; } - } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseControlInfo.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseControlInfo.java index 89707c7accad6..daa7e0b63ed50 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseControlInfo.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseControlInfo.java @@ -12,12 +12,12 @@ */ package org.openhab.binding.daikin.internal.api.airbase; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.daikin.internal.api.InfoParser; import org.openhab.binding.daikin.internal.api.airbase.AirbaseEnums.AirbaseFanMovement; import org.openhab.binding.daikin.internal.api.airbase.AirbaseEnums.AirbaseFanSpeed; import org.openhab.binding.daikin.internal.api.airbase.AirbaseEnums.AirbaseMode; @@ -31,10 +31,11 @@ * @author Paul Smedley - Mods for Daikin Airbase Units * */ +@NonNullByDefault public class AirbaseControlInfo { private static final Logger LOGGER = LoggerFactory.getLogger(AirbaseControlInfo.class); - public String ret; + public String ret = ""; public boolean power = false; public AirbaseMode mode = AirbaseMode.AUTO; /** Degrees in Celsius. */ @@ -50,27 +51,22 @@ private AirbaseControlInfo() { public static AirbaseControlInfo parse(String response) { LOGGER.debug("Parsing string: \"{}\"", response); - Map responseMap = Arrays.asList(response.split(",")).stream().filter(kv -> kv.contains("=")) - .map(kv -> { - String[] keyValue = kv.split("="); - String key = keyValue[0]; - String value = keyValue.length > 1 ? keyValue[1] : ""; - return new String[] { key, value }; - }).collect(Collectors.toMap(x -> x[0], x -> x[1])); + Map responseMap = InfoParser.parse(response); AirbaseControlInfo info = new AirbaseControlInfo(); - info.ret = responseMap.get("ret"); + info.ret = Optional.ofNullable(responseMap.get("ret")).orElse(""); info.power = "1".equals(responseMap.get("pow")); - info.mode = Optional.ofNullable(responseMap.get("mode")).flatMap(value -> parseInt(value)) + info.mode = Optional.ofNullable(responseMap.get("mode")).flatMap(value -> InfoParser.parseInt(value)) .map(value -> AirbaseMode.fromValue(value)).orElse(AirbaseMode.AUTO); - info.temp = Optional.ofNullable(responseMap.get("stemp")).flatMap(value -> parseDouble(value)); - int f_rate = Optional.ofNullable(responseMap.get("f_rate")).flatMap(value -> parseInt(value)).orElse(1); + info.temp = Optional.ofNullable(responseMap.get("stemp")).flatMap(value -> InfoParser.parseDouble(value)); + int f_rate = Optional.ofNullable(responseMap.get("f_rate")).flatMap(value -> InfoParser.parseInt(value)) + .orElse(1); boolean f_auto = "1".equals(responseMap.getOrDefault("f_auto", "0")); boolean f_airside = "1".equals(responseMap.getOrDefault("f_airside", "0")); info.fanSpeed = AirbaseFanSpeed.fromValue(f_rate, f_auto, f_airside); - info.fanMovement = Optional.ofNullable(responseMap.get("f_dir")).flatMap(value -> parseInt(value)) + info.fanMovement = Optional.ofNullable(responseMap.get("f_dir")).flatMap(value -> InfoParser.parseInt(value)) .map(value -> AirbaseFanMovement.fromValue(value)).orElse(AirbaseFanMovement.STOPPED); - info.targetHumidity = Optional.ofNullable(responseMap.get("shum")).flatMap(value -> parseInt(value)); + info.targetHumidity = Optional.ofNullable(responseMap.get("shum")).flatMap(value -> InfoParser.parseInt(value)); return info; } @@ -87,20 +83,4 @@ public Map getParamString() { return params; } - - private static Optional parseDouble(String value) { - try { - return Optional.of(Double.parseDouble(value)); - } catch (NumberFormatException e) { - return Optional.empty(); - } - } - - private static Optional parseInt(String value) { - try { - return Optional.of(Integer.parseInt(value)); - } catch (Exception e) { - return Optional.empty(); - } - } } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseEnums.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseEnums.java index e6ab004b296f5..fe9c9994a0a21 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseEnums.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseEnums.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.daikin.internal.api.airbase; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,13 +23,14 @@ * @author Paul Smedley - Mods for Daikin Airbase Units * */ +@NonNullByDefault public class AirbaseEnums { public enum AirbaseMode { - COLD (2, "Cooling"), - HEAT (1, "Heating"), - FAN (0, "Fan"), - DRY (7, "Dehumidifier"), - AUTO (3, "Auto"); + COLD(2, "Cooling"), + HEAT(1, "Heating"), + FAN(0, "Fan"), + DRY(7, "Dehumidifier"), + AUTO(3, "Auto"); private static final Logger LOGGER = LoggerFactory.getLogger(AirbaseMode.class); private final int value; @@ -42,7 +44,7 @@ public enum AirbaseMode { public int getValue() { return value; } - + public String getLabel() { return label; } @@ -60,18 +62,18 @@ public static AirbaseMode fromValue(int value) { public enum AirbaseFanSpeed { // level,f_auto,f_airside - AUTO (0, false, false), - LEVEL_1 (1, false, false), - LEVEL_2 (2, false, false), - LEVEL_3 (3, false, false), - LEVEL_4 (4, false, false), - LEVEL_5 (5, false, false), - AUTO_LEVEL_1 (1, true, false), - AUTO_LEVEL_2 (2, true, false), - AUTO_LEVEL_3 (3, true, false), - AUTO_LEVEL_4 (4, true, false), - AUTO_LEVEL_5 (5, true, false), - AIRSIDE (1, false, true); + AUTO(0, false, false), + LEVEL_1(1, false, false), + LEVEL_2(2, false, false), + LEVEL_3(3, false, false), + LEVEL_4(4, false, false), + LEVEL_5(5, false, false), + AUTO_LEVEL_1(1, true, false), + AUTO_LEVEL_2(2, true, false), + AUTO_LEVEL_3(3, true, false), + AUTO_LEVEL_4(4, true, false), + AUTO_LEVEL_5(5, true, false), + AIRSIDE(1, false, true); private static final Logger LOGGER = LoggerFactory.getLogger(AirbaseFanSpeed.class); private final int level; @@ -84,7 +86,7 @@ public enum AirbaseFanSpeed { this.airside = airside; } - public int getLevel() { + public int getLevel() { return level; } @@ -110,7 +112,8 @@ public String getLabel() { return label + "Level " + Integer.toString(level); } - public static AirbaseFanSpeed fromValue(int rate, boolean auto, boolean airside) { // convert from f_rate, f_auto, f_airside + public static AirbaseFanSpeed fromValue(int rate, boolean auto, boolean airside) { // convert from f_rate, + // f_auto, f_airside if (airside) { return AIRSIDE; } @@ -122,7 +125,8 @@ public static AirbaseFanSpeed fromValue(int rate, boolean auto, boolean airside) return m; } } - LOGGER.debug("Unexpected FanSpeed value from rate={}, auto={}, airside={}", rate, auto?1:0, airside?1:0); + LOGGER.debug("Unexpected FanSpeed value from rate={}, auto={}, airside={}", rate, auto ? 1 : 0, + airside ? 1 : 0); return LEVEL_1; } } @@ -157,20 +161,20 @@ public static AirbaseFanMovement fromValue(int value) { } public enum AirbaseFeature { - ZONE ("en_zone"), - FILTER_SIGN ("en_filter_sign"), - TEMP_SETTING ("en_temp_setting"), - FRATE ("en_frate"), - DIR ("en_dir"), - RTEMP_A ("en_rtemp_a"), - SPMODE ("en_spmode"), - MOMPOW ("en_mompow"), - PATROL ("en_patrol"), - AIRSIDE ("en_airside"), - QUICK_TIMER ("en_quick_timer"), - AUTO ("en_auto"), - DRY ("en_dry"), - FRATE_AUTO ("en_frate_auto"); + ZONE("en_zone"), + FILTER_SIGN("en_filter_sign"), + TEMP_SETTING("en_temp_setting"), + FRATE("en_frate"), + DIR("en_dir"), + RTEMP_A("en_rtemp_a"), + SPMODE("en_spmode"), + MOMPOW("en_mompow"), + PATROL("en_patrol"), + AIRSIDE("en_airside"), + QUICK_TIMER("en_quick_timer"), + AUTO("en_auto"), + DRY("en_dry"), + FRATE_AUTO("en_frate_auto"); private static final Logger LOGGER = LoggerFactory.getLogger(AirbaseFeature.class); private final String value; diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseModelInfo.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseModelInfo.java index 18b38f37d5dca..fc6f2a297e201 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseModelInfo.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseModelInfo.java @@ -12,29 +12,30 @@ */ package org.openhab.binding.daikin.internal.api.airbase; -import java.util.Arrays; -import java.util.Map; -import java.util.stream.Collectors; import java.util.EnumSet; +import java.util.Map; +import java.util.Optional; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.daikin.internal.api.InfoParser; +import org.openhab.binding.daikin.internal.api.airbase.AirbaseEnums.AirbaseFeature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.openhab.binding.daikin.internal.api.airbase.AirbaseEnums.AirbaseFeature; - /** * Class for holding the set of parameters used by get model info. * * @author Paul Smedley - Initial Contribution * */ +@NonNullByDefault public class AirbaseModelInfo { private static final Logger LOGGER = LoggerFactory.getLogger(AirbaseModelInfo.class); - public String ret; - public Integer zonespresent; - public Integer commonzone; - public Integer frate_steps; // fan rate steps + public String ret = ""; + public int zonespresent; + public int commonzone; + public int frate_steps; // fan rate steps public EnumSet features; private AirbaseModelInfo() { @@ -44,25 +45,21 @@ private AirbaseModelInfo() { public static AirbaseModelInfo parse(String response) { LOGGER.debug("Parsing string: \"{}\"", response); - Map responseMap = Arrays.asList(response.split(",")).stream().filter(kv -> kv.contains("=")) - .map(kv -> { - String[] keyValue = kv.split("="); - String key = keyValue[0]; - String value = keyValue.length > 1 ? keyValue[1] : ""; - return new String[] { key, value }; - }).collect(Collectors.toMap(x -> x[0], x -> x[1])); + Map responseMap = InfoParser.parse(response); AirbaseModelInfo info = new AirbaseModelInfo(); - info.ret = responseMap.get("ret"); - info.zonespresent = Integer.parseInt(responseMap.get("en_zone")); - info.commonzone = Integer.parseInt(responseMap.get("en_common_zone")); - info.frate_steps = Integer.parseInt(responseMap.get("frate_steps")); - for (AirbaseFeature f: AirbaseFeature.values()) { + info.ret = Optional.ofNullable(responseMap.get("ret")).orElse(""); + info.zonespresent = Optional.ofNullable(responseMap.get("en_zone")).flatMap(value -> InfoParser.parseInt(value)) + .orElse(0); + info.commonzone = Optional.ofNullable(responseMap.get("en_common_zone")) + .flatMap(value -> InfoParser.parseInt(value)).orElse(0); + info.frate_steps = Optional.ofNullable(responseMap.get("frate_steps")) + .flatMap(value -> InfoParser.parseInt(value)).orElse(1); + for (AirbaseFeature f : AirbaseFeature.values()) { if ("1".equals(responseMap.get(f.getValue()))) { info.features.add(f); } } return info; } - } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseZoneInfo.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseZoneInfo.java index d3114efc7cf69..037fda7f44c02 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseZoneInfo.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/api/airbase/AirbaseZoneInfo.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.daikin.internal.api.airbase; -import java.util.Arrays; import java.util.LinkedHashMap; -import java.util.stream.IntStream; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.daikin.internal.api.InfoParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,10 +29,11 @@ * @author Paul Smedley - Initial contribution * */ +@NonNullByDefault public class AirbaseZoneInfo { private static final Logger LOGGER = LoggerFactory.getLogger(AirbaseZoneInfo.class); - public String zonenames; + public String zonenames = ""; public boolean zone[] = new boolean[9]; private AirbaseZoneInfo() { @@ -38,32 +42,26 @@ private AirbaseZoneInfo() { public static AirbaseZoneInfo parse(String response) { LOGGER.debug("Parsing string: \"{}\"", response); - Map responseMap = Arrays.asList(response.split(",")).stream().filter(kv -> kv.contains("=")) - .map(kv -> { - String[] keyValue = kv.split("="); - String key = keyValue[0]; - String value = keyValue.length > 1 ? keyValue[1] : ""; - return new String[] { key, value }; - }).collect(Collectors.toMap(x -> x[0], x -> x[1])); + Map responseMap = InfoParser.parse(response); AirbaseZoneInfo info = new AirbaseZoneInfo(); - info.zonenames = responseMap.get("zone_name"); - String zoneinfo = responseMap.get("zone_onoff"); + info.zonenames = Optional.ofNullable(responseMap.get("zone_name")).orElse(""); + String zoneinfo = Optional.ofNullable(responseMap.get("zone_onoff")).orElse(""); String[] Zones = zoneinfo.split("%3b"); for (int i = 1; i < 9; i++) - info.zone[i] = "1".equals(Zones[i-1]); + info.zone[i] = "1".equals(Zones[i - 1]); return info; } public Map getParamString() { Map params = new LinkedHashMap<>(); - String onoffstring = IntStream.range(1, zone.length).mapToObj(idx -> zone[idx] ? "1" : "0").collect(Collectors.joining("%3b")); + String onoffstring = IntStream.range(1, zone.length).mapToObj(idx -> zone[idx] ? "1" : "0") + .collect(Collectors.joining("%3b")); params.put("zone_name", zonenames); params.put("zone_onoff", onoffstring); return params; } - } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/config/DaikinConfiguration.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/config/DaikinConfiguration.java index ccdbc33a759bb..1d820a2d9c450 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/config/DaikinConfiguration.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/config/DaikinConfiguration.java @@ -12,16 +12,26 @@ */ package org.openhab.binding.daikin.internal.config; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * Holds configuration data for a Daikin air conditioning unit. * * @author Tim Waterhouse - Initial contribution + * @author Jimmy Tanagra - Add secure, uuid * */ +@NonNullByDefault public class DaikinConfiguration { public static final String HOST = "host"; + public static final String SECURE = "secure"; + public static final String UUID = "uuid"; + public static final String KEY = "key"; - public String host; - + public @Nullable String host; + public @Nullable Boolean secure; + public @Nullable String uuid; + public @Nullable String key; public long refresh; } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/discovery/DaikinACUnitDiscoveryService.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/discovery/DaikinACUnitDiscoveryService.java index 2076bbdc6ebc8..fe915fed16515 100644 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/discovery/DaikinACUnitDiscoveryService.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/discovery/DaikinACUnitDiscoveryService.java @@ -20,9 +20,15 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; @@ -30,12 +36,13 @@ import org.eclipse.smarthome.core.net.NetUtil; import org.eclipse.smarthome.core.thing.ThingUID; import org.openhab.binding.daikin.internal.DaikinBindingConstants; +import org.openhab.binding.daikin.internal.DaikinCommunicationForbiddenException; +import org.openhab.binding.daikin.internal.DaikinHttpClientFactory; import org.openhab.binding.daikin.internal.DaikinWebTargets; +import org.openhab.binding.daikin.internal.api.InfoParser; import org.openhab.binding.daikin.internal.config.DaikinConfiguration; -import org.openhab.binding.daikin.internal.api.ControlInfo; -import org.openhab.binding.daikin.internal.api.airbase.AirbaseBasicInfo; -import org.openhab.binding.daikin.internal.api.airbase.AirbaseControlInfo; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,14 +54,16 @@ * */ @Component(service = DiscoveryService.class) +@NonNullByDefault public class DaikinACUnitDiscoveryService extends AbstractDiscoveryService { private static final String UDP_PACKET_CONTENTS = "DAIKIN_UDP/common/basic_info"; private static final int REMOTE_UDP_PORT = 30050; private Logger logger = LoggerFactory.getLogger(DaikinACUnitDiscoveryService.class); + private @Nullable HttpClient httpClient; private final Runnable scanner; - private ScheduledFuture backgroundFuture; + private @Nullable ScheduledFuture backgroundFuture; public DaikinACUnitDiscoveryService() { super(Collections.singleton(DaikinBindingConstants.THING_TYPE_AC_UNIT), 600, true); @@ -117,34 +126,55 @@ private Runnable createScanner() { private boolean receivePacketAndDiscover(DatagramSocket socket) { try { - // Use a one byte buffer since we don't really care about the contents. - byte[] buffer = new byte[1]; + byte[] buffer = new byte[512]; DatagramPacket incomingPacket = new DatagramPacket(buffer, buffer.length); socket.setSoTimeout(1000 /* one second */); socket.receive(incomingPacket); String host = incomingPacket.getAddress().toString().substring(1); - logger.debug("Received packet from {}", host); + String data = new String(incomingPacket.getData(), 0, incomingPacket.getLength(), "US-ASCII"); + logger.debug("Received packet from {}: {}", host, data); + + Map parsedData = InfoParser.parse(data); + Boolean secure = "1".equals(parsedData.get("en_secure")); + String thingId = Optional.ofNullable(parsedData.get("ssid")).orElse(host.replace(".", "_")); + String mac = Optional.ofNullable(parsedData.get("mac")).orElse(""); + String uuid = mac.isEmpty() ? UUID.randomUUID().toString() + : UUID.nameUUIDFromBytes(mac.getBytes()).toString(); + + DaikinWebTargets webTargets = new DaikinWebTargets(httpClient, host, secure, null); + boolean found = false; + // look for Daikin controller - ControlInfo controlInfo = new DaikinWebTargets(host).getControlInfo(); - if (controlInfo.ret.equals("OK")) { - ThingUID thingUID = new ThingUID(DaikinBindingConstants.THING_TYPE_AC_UNIT, host.replace('.', '_')); - DiscoveryResult result = DiscoveryResultBuilder.create(thingUID) + try { + found = "OK".equals(webTargets.getBasicInfo().ret); + } catch (DaikinCommunicationForbiddenException e) { + // At this point, we don't have the adapter's key nor a uuid + // so we're getting a Forbidden error + // let's discover it and let the user configure the Key + found = true; + } + if (found) { + ThingUID thingUID = new ThingUID(DaikinBindingConstants.THING_TYPE_AC_UNIT, thingId); + DiscoveryResultBuilder resultBuilder = DiscoveryResultBuilder.create(thingUID) .withProperty(DaikinConfiguration.HOST, host).withLabel("Daikin AC Unit (" + host + ")") - .build(); + .withProperty(DaikinConfiguration.SECURE, secure) + .withRepresentationProperty(DaikinConfiguration.HOST); + if (secure) { + resultBuilder = resultBuilder.withProperty(DaikinConfiguration.UUID, uuid); + } + DiscoveryResult result = resultBuilder.build(); logger.debug("Successfully discovered host {}", host); thingDiscovered(result); return true; } // look for Daikin Airbase controller - AirbaseControlInfo airbaseControlInfo = new DaikinWebTargets(host).getAirbaseControlInfo(); - if (airbaseControlInfo.ret.equals("OK")) { - AirbaseBasicInfo basicInfo = new DaikinWebTargets(host).getAirbaseBasicInfo(); - ThingUID thingUID = new ThingUID(DaikinBindingConstants.THING_TYPE_AIRBASE_AC_UNIT, basicInfo.ssid); + if ("OK".equals(webTargets.getAirbaseBasicInfo().ret)) { + ThingUID thingUID = new ThingUID(DaikinBindingConstants.THING_TYPE_AIRBASE_AC_UNIT, thingId); DiscoveryResult result = DiscoveryResultBuilder.create(thingUID) .withProperty(DaikinConfiguration.HOST, host).withLabel("Daikin Airbase AC Unit (" + host + ")") - .build(); + .withRepresentationProperty(DaikinConfiguration.HOST).build(); logger.debug("Successfully discovered host {}", host); thingDiscovered(result); @@ -154,8 +184,9 @@ private boolean receivePacketAndDiscover(DatagramSocket socket) { } catch (Exception e) { return false; } - // Shouldn't get here unless we don't detect a controller - return false; + // Shouldn't get here unless we don't detect a controller. + // Return true to continue with the next packet, which comes from another adapter + return true; } private List getBroadcastAddresses() { @@ -171,4 +202,9 @@ private List getBroadcastAddresses() { return addresses; } + + @Reference + protected void setDaikinHttpClientFactory(final DaikinHttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getHttpClient(); + } } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java index f6b7885106594..d9b9b2ebc5afd 100755 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAcUnitHandler.java @@ -13,74 +13,121 @@ package org.openhab.binding.daikin.internal.handler; import java.io.IOException; +import java.math.BigDecimal; import java.util.Optional; +import java.util.stream.IntStream; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.daikin.internal.DaikinBindingConstants; import org.openhab.binding.daikin.internal.DaikinCommunicationException; import org.openhab.binding.daikin.internal.DaikinDynamicStateDescriptionProvider; +import org.openhab.binding.daikin.internal.DaikinWebTargets; import org.openhab.binding.daikin.internal.api.ControlInfo; +import org.openhab.binding.daikin.internal.api.EnergyInfoYear; import org.openhab.binding.daikin.internal.api.Enums.FanMovement; import org.openhab.binding.daikin.internal.api.Enums.FanSpeed; import org.openhab.binding.daikin.internal.api.Enums.HomekitMode; import org.openhab.binding.daikin.internal.api.Enums.Mode; +import org.openhab.binding.daikin.internal.api.Enums.SpecialModeKind; import org.openhab.binding.daikin.internal.api.SensorInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Handles communicating with a Daikin air conditioning unit. * * @author Tim Waterhouse - Initial Contribution * @author Paul Smedley - Modifications to support Airbase Controllers - * + * @author Lukas Agethen - Added support for Energy Year reading, compressor frequency and powerful mode */ @NonNullByDefault public class DaikinAcUnitHandler extends DaikinBaseHandler { - public DaikinAcUnitHandler(Thing thing, DaikinDynamicStateDescriptionProvider stateDescriptionProvider) { - super(thing, stateDescriptionProvider); + private final Logger logger = LoggerFactory.getLogger(DaikinAcUnitHandler.class); + + public DaikinAcUnitHandler(Thing thing, DaikinDynamicStateDescriptionProvider stateDescriptionProvider, + @Nullable HttpClient httpClient) { + super(thing, stateDescriptionProvider, httpClient); } @Override protected void pollStatus() throws IOException { + DaikinWebTargets webTargets = this.webTargets; + if (webTargets == null) { + return; + } ControlInfo controlInfo = webTargets.getControlInfo(); updateStatus(ThingStatus.ONLINE); - if (controlInfo != null) { - updateState(DaikinBindingConstants.CHANNEL_AC_POWER, controlInfo.power ? OnOffType.ON : OnOffType.OFF); - updateTemperatureChannel(DaikinBindingConstants.CHANNEL_AC_TEMP, controlInfo.temp); - - updateState(DaikinBindingConstants.CHANNEL_AC_MODE, new StringType(controlInfo.mode.name())); - updateState(DaikinBindingConstants.CHANNEL_AC_FAN_SPEED, new StringType(controlInfo.fanSpeed.name())); - updateState(DaikinBindingConstants.CHANNEL_AC_FAN_DIR, new StringType(controlInfo.fanMovement.name())); - - if (!controlInfo.power) { - updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.OFF.getValue())); - } else if (controlInfo.mode == Mode.COLD) { - updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.COOL.getValue())); - } else if (controlInfo.mode == Mode.HEAT) { - updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.HEAT.getValue())); - } else if (controlInfo.mode == Mode.AUTO) { - updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.AUTO.getValue())); - } + updateState(DaikinBindingConstants.CHANNEL_AC_POWER, controlInfo.power ? OnOffType.ON : OnOffType.OFF); + updateTemperatureChannel(DaikinBindingConstants.CHANNEL_AC_TEMP, controlInfo.temp); + + updateState(DaikinBindingConstants.CHANNEL_AC_MODE, new StringType(controlInfo.mode.name())); + updateState(DaikinBindingConstants.CHANNEL_AC_FAN_SPEED, new StringType(controlInfo.fanSpeed.name())); + updateState(DaikinBindingConstants.CHANNEL_AC_FAN_DIR, new StringType(controlInfo.fanMovement.name())); + + if (!controlInfo.power) { + updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.OFF.getValue())); + } else if (controlInfo.mode == Mode.COLD) { + updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.COOL.getValue())); + } else if (controlInfo.mode == Mode.HEAT) { + updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.HEAT.getValue())); + } else if (controlInfo.mode == Mode.AUTO) { + updateState(DaikinBindingConstants.CHANNEL_AC_HOMEKITMODE, new StringType(HomekitMode.AUTO.getValue())); + } + + updateState(DaikinBindingConstants.CHANNEL_AC_SPECIALMODE, new StringType(controlInfo.specialMode.name())); + + if (controlInfo.specialMode.isUndefined()) { + updateState(DaikinBindingConstants.CHANNEL_AC_SPECIALMODE_POWERFUL, UnDefType.UNDEF); + } else { + updateState(DaikinBindingConstants.CHANNEL_AC_SPECIALMODE_POWERFUL, + controlInfo.specialMode.isPowerfulActive() ? OnOffType.ON : OnOffType.OFF); } SensorInfo sensorInfo = webTargets.getSensorInfo(); - if (sensorInfo != null) { - updateTemperatureChannel(DaikinBindingConstants.CHANNEL_INDOOR_TEMP, sensorInfo.indoortemp); + updateTemperatureChannel(DaikinBindingConstants.CHANNEL_INDOOR_TEMP, sensorInfo.indoortemp); - updateTemperatureChannel(DaikinBindingConstants.CHANNEL_OUTDOOR_TEMP, sensorInfo.outdoortemp); + updateTemperatureChannel(DaikinBindingConstants.CHANNEL_OUTDOOR_TEMP, sensorInfo.outdoortemp); - if (sensorInfo.indoorhumidity.isPresent()) { - updateState(DaikinBindingConstants.CHANNEL_HUMIDITY, new DecimalType(sensorInfo.indoorhumidity.get())); - } else { - updateState(DaikinBindingConstants.CHANNEL_HUMIDITY, UnDefType.UNDEF); + if (sensorInfo.indoorhumidity.isPresent()) { + updateState(DaikinBindingConstants.CHANNEL_HUMIDITY, + new QuantityType<>(sensorInfo.indoorhumidity.get(), SmartHomeUnits.PERCENT)); + } else { + updateState(DaikinBindingConstants.CHANNEL_HUMIDITY, UnDefType.UNDEF); + } + + if (sensorInfo.compressorfrequency.isPresent()) { + updateState(DaikinBindingConstants.CHANNEL_CMP_FREQ, + new QuantityType<>(sensorInfo.compressorfrequency.get(), SmartHomeUnits.PERCENT)); + } else { + updateState(DaikinBindingConstants.CHANNEL_CMP_FREQ, UnDefType.UNDEF); + } + + try { + EnergyInfoYear energyInfoYear = webTargets.getEnergyInfoYear(); + + if (energyInfoYear.energyHeatingThisYear.isPresent()) { + updateEnergyYearChannel(DaikinBindingConstants.CHANNEL_ENERGY_HEATING_CURRENTYEAR_PREFIX, + energyInfoYear.energyHeatingThisYear); + } + if (energyInfoYear.energyCoolingThisYear.isPresent()) { + updateEnergyYearChannel(DaikinBindingConstants.CHANNEL_ENERGY_COOLING_CURRENTYEAR_PREFIX, + energyInfoYear.energyCoolingThisYear); } + } catch (DaikinCommunicationException e) { + // Suppress any error if energy info is not supported. + logger.debug("getEnergyInfoYear() error: {}", e.getMessage()); } } @@ -94,12 +141,22 @@ protected boolean handleCommandInternal(ChannelUID channelUID, Command command) return true; } break; + case DaikinBindingConstants.CHANNEL_AC_SPECIALMODE_POWERFUL: + if (command instanceof OnOffType) { + changeSpecialModePowerful(((OnOffType) command).equals(OnOffType.ON)); + return true; + } + break; } return false; } @Override protected void changePower(boolean power) throws DaikinCommunicationException { + DaikinWebTargets webTargets = this.webTargets; + if (webTargets == null) { + return; + } ControlInfo info = webTargets.getControlInfo(); info.power = power; webTargets.setControlInfo(info); @@ -107,6 +164,10 @@ protected void changePower(boolean power) throws DaikinCommunicationException { @Override protected void changeSetPoint(double newTemperature) throws DaikinCommunicationException { + DaikinWebTargets webTargets = this.webTargets; + if (webTargets == null) { + return; + } ControlInfo info = webTargets.getControlInfo(); info.temp = Optional.of(newTemperature); webTargets.setControlInfo(info); @@ -114,21 +175,101 @@ protected void changeSetPoint(double newTemperature) throws DaikinCommunicationE @Override protected void changeMode(String mode) throws DaikinCommunicationException { + DaikinWebTargets webTargets = this.webTargets; + if (webTargets == null) { + return; + } + Mode newMode; + try { + newMode = Mode.valueOf(mode); + } catch (IllegalArgumentException ex) { + logger.warn("Invalid mode: {}. Valid values: {}", mode, Mode.values()); + return; + } ControlInfo info = webTargets.getControlInfo(); - info.mode = Mode.valueOf(mode); + info.mode = newMode; webTargets.setControlInfo(info); } @Override protected void changeFanSpeed(String fanSpeed) throws DaikinCommunicationException { + DaikinWebTargets webTargets = this.webTargets; + if (webTargets == null) { + return; + } + FanSpeed newSpeed; + try { + newSpeed = FanSpeed.valueOf(fanSpeed); + } catch (IllegalArgumentException ex) { + logger.warn("Invalid fan speed: {}. Valid values: {}", fanSpeed, FanSpeed.values()); + return; + } ControlInfo info = webTargets.getControlInfo(); - info.fanSpeed = FanSpeed.valueOf(fanSpeed); + info.fanSpeed = newSpeed; webTargets.setControlInfo(info); } protected void changeFanDir(String fanDir) throws DaikinCommunicationException { + DaikinWebTargets webTargets = this.webTargets; + if (webTargets == null) { + return; + } + FanMovement newMovement; + try { + newMovement = FanMovement.valueOf(fanDir); + } catch (IllegalArgumentException ex) { + logger.warn("Invalid fan direction: {}. Valid values: {}", fanDir, FanMovement.values()); + return; + } ControlInfo info = webTargets.getControlInfo(); - info.fanMovement = FanMovement.valueOf(fanDir); + info.fanMovement = newMovement; webTargets.setControlInfo(info); } + + /** + * + * @param powerfulMode + * @return Is change successful + * @throws DaikinCommunicationException + */ + protected boolean changeSpecialModePowerful(boolean powerfulMode) throws DaikinCommunicationException { + DaikinWebTargets webTargets = this.webTargets; + if (webTargets == null) { + return false; + } + return webTargets.setSpecialMode(SpecialModeKind.POWERFUL, powerfulMode); + } + + /** + * Updates energy year channels. Values are provided in hundreds of Watt + * + * @param channelPrefix + * @param maybePower + */ + protected void updateEnergyYearChannel(String channelPrefix, Optional maybePower) { + IntStream.range(1, 13) + .forEach(i -> updateState( + String.format(DaikinBindingConstants.CHANNEL_ENERGY_STRING_FORMAT, channelPrefix, i), + maybePower. map(t -> new QuantityType<>(BigDecimal.valueOf(t[i - 1].longValue(), 1), + SmartHomeUnits.KILOWATT_HOUR)).orElse(UnDefType.UNDEF)) + + ); + } + + @Override + protected void registerUuid(@Nullable String key) { + if (key == null) { + return; + } + try { + DaikinWebTargets webTargets = this.webTargets; + if (webTargets == null) { + return; + } + webTargets.registerUuid(key); + } catch (Exception e) { + // suppress exceptions + logger.debug("registerUuid({}) error: {}", key, e.getMessage()); + } + } } diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java index b92927eaf168e..8dc0abde320b1 100755 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinAirbaseUnitHandler.java @@ -19,6 +19,9 @@ import java.util.Optional; import java.util.stream.IntStream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -48,12 +51,14 @@ * @author Jimmy Tanagra - Support Airside and auto fan levels, DynamicStateDescription * */ +@NonNullByDefault public class DaikinAirbaseUnitHandler extends DaikinBaseHandler { private final Logger logger = LoggerFactory.getLogger(DaikinAirbaseUnitHandler.class); - private AirbaseModelInfo airbaseModelInfo; + private @Nullable AirbaseModelInfo airbaseModelInfo; - public DaikinAirbaseUnitHandler(Thing thing, DaikinDynamicStateDescriptionProvider stateDescriptionProvider) { - super(thing, stateDescriptionProvider); + public DaikinAirbaseUnitHandler(Thing thing, DaikinDynamicStateDescriptionProvider stateDescriptionProvider, + @Nullable HttpClient httpClient) { + super(thing, stateDescriptionProvider, httpClient); } @Override @@ -128,12 +133,20 @@ protected void changeSetPoint(double newTemperature) throws DaikinCommunicationE @Override protected void changeMode(String mode) throws DaikinCommunicationException { - AirbaseMode newMode = AirbaseMode.valueOf(mode); - if ((newMode == AirbaseMode.AUTO && !airbaseModelInfo.features.contains(AirbaseFeature.AUTO)) - || (newMode == AirbaseMode.DRY && !airbaseModelInfo.features.contains(AirbaseFeature.DRY))) { - logger.warn("{} mode is not supported by your controller", mode); + AirbaseMode newMode; + try { + newMode = AirbaseMode.valueOf(mode); + } catch (IllegalArgumentException ex) { + logger.warn("Invalid mode: {}. Valid values: {}", mode, AirbaseMode.values()); return; } + if (airbaseModelInfo != null) { + if ((newMode == AirbaseMode.AUTO && !airbaseModelInfo.features.contains(AirbaseFeature.AUTO)) + || (newMode == AirbaseMode.DRY && !airbaseModelInfo.features.contains(AirbaseFeature.DRY))) { + logger.warn("{} mode is not supported by your controller", mode); + return; + } + } AirbaseControlInfo info = webTargets.getAirbaseControlInfo(); info.mode = newMode; webTargets.setAirbaseControlInfo(info); @@ -141,15 +154,23 @@ protected void changeMode(String mode) throws DaikinCommunicationException { @Override protected void changeFanSpeed(String speed) throws DaikinCommunicationException { - AirbaseFanSpeed newFanSpeed = AirbaseFanSpeed.valueOf(speed); - if (EnumSet.range(AirbaseFanSpeed.AUTO_LEVEL_1, AirbaseFanSpeed.AUTO_LEVEL_5).contains(newFanSpeed) - && !airbaseModelInfo.features.contains(AirbaseFeature.FRATE_AUTO)) { - logger.warn("Fan AUTO_LEVEL_X is not supported by your controller"); + AirbaseFanSpeed newFanSpeed; + try { + newFanSpeed = AirbaseFanSpeed.valueOf(speed); + } catch (IllegalArgumentException ex) { + logger.warn("Invalid fan speed: {}. Valid values: {}", speed, AirbaseFanSpeed.values()); return; } - if (newFanSpeed == AirbaseFanSpeed.AIRSIDE && !airbaseModelInfo.features.contains(AirbaseFeature.AIRSIDE)) { - logger.warn("Airside is not supported by your controller"); - return; + if (airbaseModelInfo != null) { + if (EnumSet.range(AirbaseFanSpeed.AUTO_LEVEL_1, AirbaseFanSpeed.AUTO_LEVEL_5).contains(newFanSpeed) + && !airbaseModelInfo.features.contains(AirbaseFeature.FRATE_AUTO)) { + logger.warn("Fan AUTO_LEVEL_X is not supported by your controller"); + return; + } + if (newFanSpeed == AirbaseFanSpeed.AIRSIDE && !airbaseModelInfo.features.contains(AirbaseFeature.AIRSIDE)) { + logger.warn("Airside is not supported by your controller"); + return; + } } AirbaseControlInfo info = webTargets.getAirbaseControlInfo(); info.fanSpeed = newFanSpeed; @@ -162,9 +183,21 @@ protected void changeZone(int zone, boolean command) throws DaikinCommunicationE zone, airbaseModelInfo.zonespresent); return; } - AirbaseZoneInfo info = webTargets.getAirbaseZoneInfo(); - info.zone[zone] = command; - webTargets.setAirbaseZoneInfo(info, airbaseModelInfo); + + AirbaseZoneInfo zoneInfo = webTargets.getAirbaseZoneInfo(); + long count = IntStream.range(0, zoneInfo.zone.length).filter(idx -> zoneInfo.zone[idx]).count() + + airbaseModelInfo.commonzone; + logger.debug("Number of open zones: \"{}\"", count); + + if (count >= 1) { + zoneInfo.zone[zone] = command; + webTargets.setAirbaseZoneInfo(zoneInfo); + } + } + + @Override + protected void registerUuid(@Nullable String key) { + // not implemented. There is currently no known Airbase adapter that requires uuid authentication } protected void updateChannelStateDescriptions() { diff --git a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java index 2139b0b307a75..04bfc6648695d 100755 --- a/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java +++ b/bundles/org.openhab.binding.daikin/src/main/java/org/openhab/binding/daikin/internal/handler/DaikinBaseHandler.java @@ -21,6 +21,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.QuantityType; @@ -37,6 +38,7 @@ import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.daikin.internal.DaikinBindingConstants; import org.openhab.binding.daikin.internal.DaikinCommunicationException; +import org.openhab.binding.daikin.internal.DaikinCommunicationForbiddenException; import org.openhab.binding.daikin.internal.DaikinDynamicStateDescriptionProvider; import org.openhab.binding.daikin.internal.DaikinWebTargets; import org.openhab.binding.daikin.internal.api.Enums.HomekitMode; @@ -56,11 +58,15 @@ public abstract class DaikinBaseHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(DaikinBaseHandler.class); + private final @Nullable HttpClient httpClient; + private long refreshInterval; protected @Nullable DaikinWebTargets webTargets; private @Nullable ScheduledFuture pollFuture; protected final DaikinDynamicStateDescriptionProvider stateDescriptionProvider; + protected @Nullable DaikinConfiguration config; + private boolean uuidRegistrationAttempted = false; // Abstract methods to be overridden by specific Daikin implementation class protected abstract void pollStatus() throws IOException; @@ -77,9 +83,13 @@ public abstract class DaikinBaseHandler extends BaseThingHandler { protected abstract boolean handleCommandInternal(ChannelUID channelUID, Command command) throws DaikinCommunicationException; - public DaikinBaseHandler(Thing thing, DaikinDynamicStateDescriptionProvider stateDescriptionProvider) { + protected abstract void registerUuid(@Nullable String key); + + public DaikinBaseHandler(Thing thing, DaikinDynamicStateDescriptionProvider stateDescriptionProvider, + @Nullable HttpClient httpClient) { super(thing); this.stateDescriptionProvider = stateDescriptionProvider; + this.httpClient = httpClient; } @Override @@ -130,11 +140,14 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void initialize() { logger.debug("Initializing Daikin AC Unit"); - DaikinConfiguration config = getConfigAs(DaikinConfiguration.class); + config = getConfigAs(DaikinConfiguration.class); if (config.host == null) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Host address must be set"); } else { - webTargets = new DaikinWebTargets(config.host); + if (config.uuid != null) { + config.uuid = config.uuid.replaceAll("\\s|-", ""); + } + webTargets = new DaikinWebTargets(httpClient, config.host, config.secure, config.uuid); refreshInterval = config.refresh; schedulePoll(); @@ -172,6 +185,16 @@ private synchronized void poll() { try { logger.debug("Polling for state"); pollStatus(); + } catch (DaikinCommunicationForbiddenException e) { + if (!uuidRegistrationAttempted && config.key != null && config.uuid != null) { + logger.debug("poll: Attempting to register uuid {} with key {}", config.uuid, config.key); + registerUuid(config.key); + uuidRegistrationAttempted = true; + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Access denied. Check uuid/key."); + logger.warn("{} access denied by adapter. Check uuid/key.", thing.getUID()); + } } catch (IOException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } catch (RuntimeException e) { @@ -180,8 +203,8 @@ private synchronized void poll() { } protected void updateTemperatureChannel(String channel, Optional maybeTemperature) { - updateState(channel, maybeTemperature. map(t -> new QuantityType<>(new DecimalType(t), SIUnits.CELSIUS)) - .orElse(UnDefType.UNDEF)); + updateState(channel, + maybeTemperature. map(t -> new QuantityType<>(t, SIUnits.CELSIUS)).orElse(UnDefType.UNDEF)); } /** @@ -218,5 +241,4 @@ private void changeHomekitMode(String homekitmode) throws DaikinCommunicationExc } } } - } diff --git a/bundles/org.openhab.binding.daikin/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.daikin/src/main/resources/ESH-INF/config/config.xml index 239c8ecfead02..c64da2d9bf8f2 100644 --- a/bundles/org.openhab.binding.daikin/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.daikin/src/main/resources/ESH-INF/config/config.xml @@ -1,19 +1,31 @@ - - - - The Host address of the Daikin AC unit. - network_address - - - - The number of seconds between fetches of the AC unit state. - 60 - + + + The Host address of the Daikin AC unit. + network-address + + + + Whether to access using https (default:false). + + + + A unique UUID for authentication if required. + + + + The key obtained from the Daikin adapter. + + + + Time between fetches of the AC unit state. + 60 + - diff --git a/bundles/org.openhab.binding.daikin/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.daikin/src/main/resources/ESH-INF/thing/thing-types.xml index 3b7ef0d07ddb5..d616404007ab4 100644 --- a/bundles/org.openhab.binding.daikin/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.daikin/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -8,18 +9,46 @@ Daikin AC Unit - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + host + @@ -27,25 +56,25 @@ Daikin Airbase AC Unit - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + host + @@ -59,7 +88,7 @@ The set point temperature Temperature - + @@ -67,7 +96,7 @@ The indoor temperature Temperature - + @@ -75,14 +104,14 @@ The outdoor temperature Temperature - + - Number + Number:Dimensionless The indoor humidity as measured by the A/C unit - + @@ -130,7 +159,7 @@ - + String @@ -145,6 +174,172 @@ + + Number:Dimensionless + + Current compressor frequency + + + + String + + Current special mode + + + + Switch + + Powerful mode switch + + + Number:Energy + + The energy usage for heating this year January + + + + Number:Energy + + The energy usage for heating this year February + + + + + Number:Energy + + The energy usage for heating this year March + + + + + Number:Energy + + The energy usage for heating this year April + + + + Number:Energy + + The energy usage for heating this year May + + + + Number:Energy + + The energy usage for heating this year June + + + + Number:Energy + + The energy usage for heating this year July + + + + Number:Energy + + The energy usage for heating this year August + + + + Number:Energy + + The energy usage for heating this year September + + + + Number:Energy + + The energy usage for heating this year October + + + + Number:Energy + + The energy usage for heating this year November + + + + Number:Energy + + The energy usage for heating this year December + + + + Number:Energy + + The energy usage for cooling this year January + + + + Number:Energy + + The energy usage for cooling this year February + + + + + Number:Energy + + The energy usage for cooling this year March + + + + + Number:Energy + + The energy usage for cooling this year April + + + + Number:Energy + + The energy usage for cooling this year May + + + + Number:Energy + + The energy usage for cooling this year June + + + + Number:Energy + + The energy usage for cooling this year July + + + + Number:Energy + + The energy usage for cooling this year August + + + + Number:Energy + + The energy usage for cooling this year September + + + + Number:Energy + + The energy usage for cooling this year October + + + + Number:Energy + + The energy usage for cooling this year November + + + + Number:Energy + + The energy usage for cooling this year December + + + String diff --git a/bundles/org.openhab.binding.danfossairunit/.classpath b/bundles/org.openhab.binding.danfossairunit/.classpath new file mode 100644 index 0000000000000..a5d95095ccaaf --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.danfossairunit/.project b/bundles/org.openhab.binding.danfossairunit/.project new file mode 100644 index 0000000000000..0adde996b05eb --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/.project @@ -0,0 +1,23 @@ + + + org.openhab.binding.danfossairunit + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.danfossairunit/NOTICE b/bundles/org.openhab.binding.danfossairunit/NOTICE new file mode 100644 index 0000000000000..4c20ef446c1e4 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab2-addons diff --git a/bundles/org.openhab.binding.danfossairunit/README.md b/bundles/org.openhab.binding.danfossairunit/README.md new file mode 100644 index 0000000000000..74247576a125c --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/README.md @@ -0,0 +1,82 @@ +# DanfossAirUnit Binding + +This binding supports controlling and monitoring [Danfoss air units](https://www.danfoss.com/en/products/energy-recovery-devices/dhs/heat-recovery-ventilation/air-units/) via Ethernet connection. + +## Supported Things + +This binding has been tested/reported to work with the Danfoss Air w2 / a2 / a3 devices. + +## Discovery + +Air units in the LAN are automatically discovered via broadcast and added to the Inbox. + +## Thing Configuration + +These are the available configuration parameters: + +- `host` Hostname/IP of the air unit (automatically set by discovery service) +- `refreshInterval` Time (in seconds) between monitoring requests to the air unit. Smaller values mean more network load, typically set between a few seconds and a minute. Defaults to 10 seconds. +- `updateUnchangedValuesEveryMillis` Minimum time between state updates sent to the event bus for a particular channel when the state of the channel didn't change. This should avoid spamming the event bus with unnecessary updates. When set to 0, all channel state are updated every time the air unit requests are sent (see refresh interval). When set to a non zero value, unchanged values are only reported after the configured timespan has passed. Changed values are always sent to the event bus. Defaults to 60.000 (one minute), so updates are sent every minute or if the state of the channel changes. + +## Channels + +| channel | channel group | type | readable only (RO) or writable (RW) | description | +|---|---|---|---|---| +| current_time | main | DateTime | RO | Current time reported by the air unit. | +| mode | main | String | RW | Value to control the operation mode of the air unit. One of DEMAND, PROGRAM, MANUAL and OFF | +| manual_fan_speed | main | Dimmer | RW | Value to control the fan speed when in MANUAL mode (10 steps) | +| supply_fan_speed | main | Number | RO | Current rotation of the fan supplying air to the rooms (in rpm) | +| extract_fan_speed | main | Number | RO | Current rotation of the fan extracting air from the rooms (in rpm) | +| supply_fan_step | main | Dimmer | RO | Current 10-step setting of the fan supplying air to the rooms | +| extract_fan_step | main | Dimmer | RO | Current 10-step setting of the fan extracting air from the rooms | +| boost | main | Switch | RW | Enables fan boost | +| night_cooling | main | Switch | RW | Enables night cooling | +| room_temp | temps | Number | RO | Temperature of the air in the room of the Air Dial | +| room_temp_calculated | temps | Number | RO | Calculated Room Temperature | +| outdoor_temp | temps | Number | RO | Temperature of the air outside | +| humidity | humidity | Number | RO | Humidity | +| bypass | recuperator | Switch | RW | Disables the heat exchange. Useful in summer when room temperature is above target and outside temperature is below target. | +| supply_temp | recuperator | Number | RO | Temperature of air which is passed to the rooms | +| extract_temp | recuperator | Number | RO | Temperature of the air as extracted from the rooms | +| exhaust_temp | recuperator | Number | RO | Temperature of the air when pushed outside | +| battery_life | service | Number | RO | Remaining Air Dial Battery Level (percentage) | +| filter_life | service | Number | RO | Remaining life of filter until exchange is necessary (percentage) | + + +## Full Example + +### Things + +Suppose your autodiscovered air unit is identified by the id "danfossairunit:airunit:-1062731769" (see section "Discovery"). +The channel will then be identified by `:#` + +You can also manually configure your air unit in case you don't want to use autodiscovery + (e. g. if you want to have a portable configuration): +Create a new file, e. g. `danfoss.things`, in your _things_ configuration folder: +``` +Thing danfossairunit:airunit:myairunit [host="192.168.0.7", +refreshInterval=5, +updateUnchangedValuesEveryMillis=30000] +``` + +### Items + +``` +Dimmer Lueftung_Drehzahl_Manuell "Drehzahl Lüftung %" (All,Lueftung) {channel = "danfossairunit:airunit:-1062731769:main#manual_fan_speed"} +Number Lueftung_Drehzahl_Supply "Drehzahl Lüftung Zuluft (rpm)" (All,Lueftung) {channel = "danfossairunit:airunit:-1062731769:main#supply_fan_speed"} +Number Lueftung_Drehzahl_Extract "Drehzahl Lüftung Abluft (rpm)" (All,Lueftung) {channel = "danfossairunit:airunit:-1062731769:main#extract_fan_speed"} +String Lueftung_Mode "Betriebsart Lüftung" (All,Lueftung) {channel = "danfossairunit:airunit:-1062731769:main#mode"} +Switch Lueftung_Boost "Stoßlüftung" (All,Lueftung) {channel = "danfossairunit:airunit:-1062731769:main#boost"} +Switch Lueftung_Bypass "Lüftung Bypass" (All,Lueftung) {channel = "danfossairunit:airunit:-1062731769:recuperator#bypass"} +``` + +### Sitemap + +``` +Slider item=Lueftung_Drehzahl_Manuell +Text item=Lueftung_Drehzahl_Supply +Text item=Lueftung_Drehzahl_Extract +Selection item=Lueftung_Mode mappings=[DEMAND="Bedarfslüftung", OFF="Aus", PROGRAM="Programm", MANUAL="manuell"] +Switch item=Lueftung_Boost +Switch item=Lueftung_Bypass +``` \ No newline at end of file diff --git a/bundles/org.openhab.binding.danfossairunit/pom.xml b/bundles/org.openhab.binding.danfossairunit/pom.xml new file mode 100644 index 0000000000000..8b4ad17c9196c --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + + + org.openhab.binding.danfossairunit + + openHAB Add-ons :: Bundles :: DanfossAirUnit Binding + + diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/feature/feature.xml b/bundles/org.openhab.binding.danfossairunit/src/main/feature/feature.xml new file mode 100644 index 0000000000000..47fc4a8178251 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.danfossairunit/${project.version} + + diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Channel.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Channel.java new file mode 100644 index 0000000000000..2359d2a429856 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Channel.java @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * This enum holds the available channels with their properties (name, ...) and read/write accessors to access + * the corresponding values on the air unit. + * + * @author Robert Bach - Initial contribution + */ +@NonNullByDefault +public enum Channel { + + // Main Channels + + CHANNEL_CURRENT_TIME("current_time", ChannelGroup.MAIN, DanfossAirUnit::getCurrentTime), + CHANNEL_MODE("mode", ChannelGroup.MAIN, DanfossAirUnit::getMode, DanfossAirUnit::setMode), + CHANNEL_MANUAL_FAN_SPEED("manual_fan_speed", ChannelGroup.MAIN, DanfossAirUnit::getManualFanSpeed, + DanfossAirUnit::setManualFanSpeed), + CHANNEL_EXTRACT_FAN_SPEED("extract_fan_speed", ChannelGroup.MAIN, DanfossAirUnit::getExtractFanSpeed), + CHANNEL_SUPPLY_FAN_SPEED("supply_fan_speed", ChannelGroup.MAIN, DanfossAirUnit::getSupplyFanSpeed), + CHANNEL_EXTRACT_FAN_STEP("extract_fan_step", ChannelGroup.MAIN, DanfossAirUnit::getExtractFanStep), + CHANNEL_SUPPLY_FAN_STEP("supply_fan_step", ChannelGroup.MAIN, DanfossAirUnit::getSupplyFanStep), + + CHANNEL_BOOST("boost", ChannelGroup.MAIN, DanfossAirUnit::getBoost, DanfossAirUnit::setBoost), + CHANNEL_NIGHT_COOLING("night_cooling", ChannelGroup.MAIN, DanfossAirUnit::getNightCooling, + DanfossAirUnit::setNightCooling), + + // Main Temperature Channels + CHANNEL_ROOM_TEMP("room_temp", ChannelGroup.TEMPS, DanfossAirUnit::getRoomTemperature), + CHANNEL_ROOM_TEMP_CALCULATED("room_temp_calculated", ChannelGroup.TEMPS, + DanfossAirUnit::getRoomTemperatureCalculated), + CHANNEL_OUTDOOR_TEMP("outdoor_temp", ChannelGroup.TEMPS, DanfossAirUnit::getOutdoorTemperature), + + // Humidity Channel + CHANNEL_HUMIDITY("humidity", ChannelGroup.HUMIDITY, DanfossAirUnit::getHumidity), + + // recuperator channels + CHANNEL_BYPASS("bypass", ChannelGroup.RECUPERATOR, DanfossAirUnit::getBypass, DanfossAirUnit::setBypass), + CHANNEL_SUPPLY_TEMP("supply_temp", ChannelGroup.RECUPERATOR, DanfossAirUnit::getSupplyTemperature), + CHANNEL_EXTRACT_TEMP("extract_temp", ChannelGroup.RECUPERATOR, DanfossAirUnit::getExtractTemperature), + CHANNEL_EXHAUST_TEMP("exhaust_temp", ChannelGroup.RECUPERATOR, DanfossAirUnit::getExhaustTemperature), + + // service channels + CHANNEL_BATTERY_LIFE("battery_life", ChannelGroup.SERVICE, DanfossAirUnit::getBatteryLife), + CHANNEL_FILTER_LIFE("filter_life", ChannelGroup.SERVICE, DanfossAirUnit::getFilterLife); + + private final String channelName; + private final ChannelGroup group; + private final DanfossAirUnitReadAccessor readAccessor; + @Nullable + private final DanfossAirUnitWriteAccessor writeAccessor; + + static Channel getByName(String name) { + for (Channel channel : values()) { + if (channel.getChannelName().equals(name)) { + return channel; + } + } + throw new IllegalArgumentException(String.format("Unknown channel name: %s", name)); + } + + Channel(String channelName, ChannelGroup group, DanfossAirUnitReadAccessor readAccessor) { + this(channelName, group, readAccessor, null); + } + + Channel(String channelName, ChannelGroup group, DanfossAirUnitReadAccessor readAccessor, + @Nullable DanfossAirUnitWriteAccessor writeAccessor) { + this.channelName = channelName; + this.group = group; + this.readAccessor = readAccessor; + this.writeAccessor = writeAccessor; + } + + public String getChannelName() { + return channelName; + } + + public ChannelGroup getGroup() { + return group; + } + + public DanfossAirUnitReadAccessor getReadAccessor() { + return readAccessor; + } + + @Nullable + public DanfossAirUnitWriteAccessor getWriteAccessor() { + return writeAccessor; + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/ChannelGroup.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/ChannelGroup.java new file mode 100644 index 0000000000000..fd9afb2c5590b --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/ChannelGroup.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Represents a channel group, channels are divided into. + * + * @author Robert Bach - Initial contribution + */ +@NonNullByDefault +public enum ChannelGroup { + MAIN("main"), + TEMPS("temps"), + HUMIDITY("humidity"), + RECUPERATOR("recuperator"), + SERVICE("service"); + + private final String groupName; + + ChannelGroup(String groupName) { + this.groupName = groupName; + } + + public String getGroupName() { + return groupName; + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Commands.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Commands.java new file mode 100644 index 0000000000000..870ade835ffbb --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Commands.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link Commands} interface holds the commands which can be send to the air unit to read/write values or trigger + * actions. + * + * @author Robert Bach - Initial contribution + */ + +@NonNullByDefault +public class Commands { + + public static byte[] DISCOVER_SEND = { 0x0c, 0x00, 0x30, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13 }; + public static byte[] DISCOVER_RECEIVE = { 0x0d, 0x00, 0x07, 0x00, 0x02, 0x02, 0x00 }; + public static byte[] EMPTY = {}; + public static byte[] GET_HISTORY = { 0x00, 0x30 }; + public static byte[] REGISTER_0_READ = { 0x00, 0x04 }; + public static byte[] REGISTER_1_READ = { 0x01, 0x04 }; + public static byte[] REGISTER_1_WRITE = { 0x01, 0x06 }; + public static byte[] REGISTER_2_READ = { 0x02, 0x04 }; + public static byte[] REGISTER_4_READ = { 0x04, 0x04 }; + public static byte[] REGISTER_6_READ = { 0x06, 0x04 }; + public static byte[] MODE = { 0x14, 0x12 }; + public static byte[] MANUAL_FAN_SPEED_STEP = { 0x15, 0x61 }; + public static byte[] SUPPLY_FAN_SPEED = { 0x14, 0x50 }; + public static byte[] EXTRACT_FAN_SPEED = { 0x14, 0x51 }; + public static byte[] SUPPLY_FAN_STEP = { 0x14, 0x28 }; + public static byte[] EXTRACT_FAN_STEP = { 0x14, 0x29 }; + public static byte[] BASE_IN = { 0x14, 0x40 }; + public static byte[] BASE_OUT = { 0x14, 0x41 }; + public static byte[] BYPASS = { 0x14, 0x60 }; + public static byte[] BYPASS_DEACTIVATION = { 0x14, 0x63 }; + public static byte[] BOOST = { 0x15, 0x30 }; + public static byte[] NIGHT_COOLING = { 0x15, 0x71 }; + public static byte[] AUTOMATIC_BYPASS = { 0x17, 0x06 }; + public static byte[] AUTOMATIC_RUSH_AIRING = { 0x17, 0x02 }; + public static byte[] HUMIDITY = { 0x14, 0x70 }; + public static byte[] ROOM_TEMPERATURE = { 0x03, 0x00 }; + public static byte[] ROOM_TEMPERATURE_CALCULATED = { 0x14, (byte) 0x96 }; + public static byte[] OUTDOOR_TEMPERATURE = { 0x03, 0x34 }; + public static byte[] SUPPLY_TEMPERATURE = { 0x14, 0x73 }; + public static byte[] EXTRACT_TEMPERATURE = { 0x14, 0x74 }; + public static byte[] EXHAUST_TEMPERATURE = { 0x14, 0x75 }; + public static byte[] BATTERY_LIFE = { 0x03, 0x0f }; + public static byte[] FILTER_LIFE = { 0x14, 0x6a }; + public static byte[] CURRENT_TIME = { 0x15, (byte) 0xe0 }; + public static byte[] AWAY_TO = { 0x15, 0x20 }; + public static byte[] AWAY_FROM = { 0x15, 0x21 }; + public static byte[] UNIT_SERIAL = { 0x00, 0x25 }; // endpoint 4 + public static byte[] UNIT_NAME = { 0x15, (byte) 0xe5 }; // endpoint 1 + public static byte[] CCM_SERIAL = { 0x14, 0x6a }; // endpoint 0 +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnit.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnit.java new file mode 100644 index 0000000000000..848e7e47d318f --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnit.java @@ -0,0 +1,286 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import static org.openhab.binding.danfossairunit.internal.Commands.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.net.InetAddress; +import java.nio.charset.StandardCharsets; +import java.time.DateTimeException; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import javax.measure.quantity.Temperature; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.DateTimeType; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.library.unit.SIUnits; +import org.eclipse.smarthome.core.types.Command; + +/** + * The {@link DanfossAirUnit} class represents the air unit device and build the commands to be sent by + * {@link DanfossAirUnitCommunicationController} + * + * @author Ralf Duckstein - Initial contribution + * @author Robert Bach - heavy refactorings + */ + +@SuppressWarnings("SameParameterValue") +@NonNullByDefault +public class DanfossAirUnit { + + private final DanfossAirUnitCommunicationController communicationController; + + public DanfossAirUnit(InetAddress inetAddr, int port) { + this.communicationController = new DanfossAirUnitCommunicationController(inetAddr, port); + } + + public void cleanUp() { + this.communicationController.disconnect(); + } + + private boolean getBoolean(byte[] operation, byte[] register) throws IOException { + return communicationController.sendRobustRequest(operation, register)[0] != 0; + } + + private void setSetting(byte[] register, boolean value) throws IOException { + setSetting(register, value ? (byte) 1 : (byte) 0); + } + + private short getWord(byte[] operation, byte[] register) throws IOException { + byte[] resultBytes = communicationController.sendRobustRequest(operation, register); + return (short) ((resultBytes[0] << 8) | (resultBytes[1] & 0xFF)); + } + + private byte getByte(byte[] operation, byte[] register) throws IOException { + return communicationController.sendRobustRequest(operation, register)[0]; + } + + private String getString(byte[] operation, byte[] register) throws IOException { + // length of the string is stored in the first byte + byte[] result = communicationController.sendRobustRequest(operation, register); + return new String(result, 1, result[0], StandardCharsets.US_ASCII); + } + + private void set(byte[] operation, byte[] register, byte value) throws IOException { + byte[] valueArray = { value }; + communicationController.sendRobustRequest(operation, register, valueArray); + } + + private void set(byte[] operation, byte[] register, short value) throws IOException { + communicationController.sendRobustRequest(operation, register, shortToBytes(value)); + } + + private byte[] shortToBytes(short s) { + return new byte[] { (byte) ((s & 0xFF00) >> 8), (byte) (s & 0x00FF) }; + } + + private short getShort(byte[] operation, byte[] register) throws IOException { + byte[] result = communicationController.sendRobustRequest(operation, register); + return (short) ((result[0] << 8) + (result[1] & 0xff)); + } + + private float getTemperature(byte[] operation, byte[] register) + throws IOException, UnexpectedResponseValueException { + short shortTemp = getShort(operation, register); + float temp = ((float) shortTemp) / 100; + if (temp <= -274 || temp > 100) { + throw new UnexpectedResponseValueException(String.format("Invalid temperature: %s", temp)); + } + return temp; + } + + private ZonedDateTime getTimestamp(byte[] operation, byte[] register) + throws IOException, UnexpectedResponseValueException { + byte[] result = communicationController.sendRobustRequest(operation, register); + return asZonedDateTime(result); + } + + private ZonedDateTime asZonedDateTime(byte[] data) throws UnexpectedResponseValueException { + int second = data[0]; + int minute = data[1]; + int hour = data[2] & 0x1f; + int day = data[3] & 0x1f; + int month = data[4]; + int year = data[5] + 2000; + try { + return ZonedDateTime.of(year, month, day, hour, minute, second, 0, ZoneId.systemDefault()); + } catch (DateTimeException e) { + String msg = String.format("Ignoring invalid timestamp %s.%s.%s %s:%s:%s", day, month, year, hour, minute, + second); + throw new UnexpectedResponseValueException(msg, e); + } + } + + private static int asUnsignedByte(byte b) { + return b & 0xFF; + } + + private static float asPercentByte(byte b) { + float f = asUnsignedByte(b); + return f * 100 / 255; + } + + private void setSetting(byte[] register, short value) throws IOException { + byte[] valueArray = new byte[2]; + valueArray[0] = (byte) (value >> 8); + valueArray[1] = (byte) value; + + communicationController.sendRobustRequest(REGISTER_1_WRITE, register, valueArray); + } + + public String getUnitName() throws IOException { + return getString(REGISTER_1_READ, UNIT_NAME); + } + + public String getUnitSerialNumber() throws IOException { + return String.valueOf(getShort(REGISTER_4_READ, UNIT_SERIAL)); + } + + public StringType getMode() throws IOException { + return new StringType(Mode.values()[getByte(REGISTER_1_READ, MODE)].name()); + } + + public PercentType getManualFanSpeed() throws IOException { + return new PercentType(BigDecimal.valueOf(getByte(REGISTER_1_READ, MANUAL_FAN_SPEED_STEP) * 10)); + } + + public DecimalType getSupplyFanSpeed() throws IOException { + return new DecimalType(BigDecimal.valueOf(getWord(REGISTER_4_READ, SUPPLY_FAN_SPEED))); + } + + public DecimalType getExtractFanSpeed() throws IOException { + return new DecimalType(BigDecimal.valueOf(getWord(REGISTER_4_READ, EXTRACT_FAN_SPEED))); + } + + public PercentType getSupplyFanStep() throws IOException { + return new PercentType(BigDecimal.valueOf(getByte(REGISTER_4_READ, SUPPLY_FAN_STEP))); + } + + public PercentType getExtractFanStep() throws IOException { + return new PercentType(BigDecimal.valueOf(getByte(REGISTER_4_READ, EXTRACT_FAN_STEP))); + } + + public OnOffType getBoost() throws IOException { + return getBoolean(REGISTER_1_READ, BOOST) ? OnOffType.ON : OnOffType.OFF; + } + + public OnOffType getNightCooling() throws IOException { + return getBoolean(REGISTER_1_READ, NIGHT_COOLING) ? OnOffType.ON : OnOffType.OFF; + } + + public OnOffType getBypass() throws IOException { + return getBoolean(REGISTER_1_READ, BYPASS) ? OnOffType.ON : OnOffType.OFF; + } + + public DecimalType getHumidity() throws IOException { + BigDecimal value = BigDecimal.valueOf(asPercentByte(getByte(REGISTER_1_READ, HUMIDITY))); + return new DecimalType(value.setScale(1, RoundingMode.HALF_UP)); + } + + public QuantityType getRoomTemperature() throws IOException, UnexpectedResponseValueException { + return getTemperatureAsDecimalType(REGISTER_1_READ, ROOM_TEMPERATURE); + } + + public QuantityType getRoomTemperatureCalculated() + throws IOException, UnexpectedResponseValueException { + return getTemperatureAsDecimalType(REGISTER_0_READ, ROOM_TEMPERATURE_CALCULATED); + } + + public QuantityType getOutdoorTemperature() throws IOException, UnexpectedResponseValueException { + return getTemperatureAsDecimalType(REGISTER_1_READ, OUTDOOR_TEMPERATURE); + } + + public QuantityType getSupplyTemperature() throws IOException, UnexpectedResponseValueException { + return getTemperatureAsDecimalType(REGISTER_4_READ, SUPPLY_TEMPERATURE); + } + + public QuantityType getExtractTemperature() throws IOException, UnexpectedResponseValueException { + return getTemperatureAsDecimalType(REGISTER_4_READ, EXTRACT_TEMPERATURE); + } + + public QuantityType getExhaustTemperature() throws IOException, UnexpectedResponseValueException { + return getTemperatureAsDecimalType(REGISTER_4_READ, EXHAUST_TEMPERATURE); + } + + private QuantityType getTemperatureAsDecimalType(byte[] operation, byte[] register) + throws IOException, UnexpectedResponseValueException { + BigDecimal value = BigDecimal.valueOf(getTemperature(operation, register)); + return new QuantityType<>(value.setScale(1, RoundingMode.HALF_UP), SIUnits.CELSIUS); + } + + public DecimalType getBatteryLife() throws IOException { + return new DecimalType(BigDecimal.valueOf(asUnsignedByte(getByte(REGISTER_1_READ, BATTERY_LIFE)))); + } + + public DecimalType getFilterLife() throws IOException { + return new DecimalType(BigDecimal.valueOf(asPercentByte(getByte(REGISTER_1_READ, FILTER_LIFE)))); + } + + public DateTimeType getCurrentTime() throws IOException, UnexpectedResponseValueException { + ZonedDateTime timestamp = getTimestamp(REGISTER_1_READ, CURRENT_TIME); + return new DateTimeType(timestamp); + } + + public PercentType setManualFanSpeed(Command cmd) throws IOException { + return setPercentTypeRegister(cmd, MANUAL_FAN_SPEED_STEP); + } + + private PercentType setPercentTypeRegister(Command cmd, byte[] register) throws IOException { + if (cmd instanceof PercentType) { + byte value = (byte) ((((PercentType) cmd).intValue() + 5) / 10); + set(REGISTER_1_WRITE, register, value); + } + return new PercentType(BigDecimal.valueOf(getByte(REGISTER_1_READ, register) * 10)); + } + + private OnOffType setOnOffTypeRegister(Command cmd, byte[] register) throws IOException { + if (cmd instanceof OnOffType) { + set(REGISTER_1_WRITE, register, OnOffType.ON.equals(cmd) ? (byte) 1 : (byte) 0); + } + return getBoolean(REGISTER_1_READ, register) ? OnOffType.ON : OnOffType.OFF; + } + + private StringType setStringTypeRegister(Command cmd, byte[] register) throws IOException { + if (cmd instanceof StringType) { + byte value = (byte) (Mode.valueOf(cmd.toString()).ordinal()); + set(REGISTER_1_WRITE, register, value); + } + + return new StringType(Mode.values()[getByte(REGISTER_1_READ, register)].name()); + } + + public StringType setMode(Command cmd) throws IOException { + return setStringTypeRegister(cmd, MODE); + } + + public OnOffType setBoost(Command cmd) throws IOException { + return setOnOffTypeRegister(cmd, BOOST); + } + + public OnOffType setNightCooling(Command cmd) throws IOException { + return setOnOffTypeRegister(cmd, NIGHT_COOLING); + } + + public OnOffType setBypass(Command cmd) throws IOException { + return setOnOffTypeRegister(cmd, BYPASS); + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitBindingConstants.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitBindingConstants.java new file mode 100644 index 0000000000000..4619464b6d996 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitBindingConstants.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link DanfossAirUnitBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Ralf Duckstein - Initial contribution + * @author Robert Bach - heavy refactorings + */ +@NonNullByDefault +public class DanfossAirUnitBindingConstants { + + public static String BINDING_ID = "danfossairunit"; + + // List of all Thing Type UIDs + public static ThingTypeUID THING_TYPE_SAMPLE = new ThingTypeUID(BINDING_ID, "sample"); + + // List of all Channel ids + public static String CHANNEL_1 = "channel1"; + + // The only thing type UIDs + public static ThingTypeUID THING_TYPE_AIRUNIT = new ThingTypeUID(BINDING_ID, "airunit"); + + // The thing type as a set + public static Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_AIRUNIT); + + // Properties + public static String PROPERTY_UNIT_NAME = "Unit Name"; + public static String PROPERTY_SERIAL = "Serial Number"; +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitCommunicationController.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitCommunicationController.java new file mode 100644 index 0000000000000..3b7e2787cd19f --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitCommunicationController.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import static org.openhab.binding.danfossairunit.internal.Commands.EMPTY; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.Socket; +import java.util.Arrays; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link DanfossAirUnitCommunicationController} class does the actual network communication with the air unit. + * + * @author Robert Bach - initial contribution + */ + +@NonNullByDefault +public class DanfossAirUnitCommunicationController { + + private final Logger logger = LoggerFactory.getLogger(DanfossAirUnitCommunicationController.class); + + private final InetAddress inetAddr; + private final int port; + private boolean connected = false; + private @Nullable Socket socket; + private @Nullable OutputStream oStream; + private @Nullable InputStream iStream; + + public DanfossAirUnitCommunicationController(InetAddress inetAddr, int port) { + this.inetAddr = inetAddr; + this.port = port; + } + + public synchronized void connect() throws IOException { + if (connected) { + return; + } + socket = new Socket(inetAddr, port); + oStream = socket.getOutputStream(); + iStream = socket.getInputStream(); + connected = true; + } + + public synchronized void disconnect() { + if (!connected) { + return; + } + try { + if (socket != null) { + socket.close(); + } + } catch (IOException ioe) { + logger.debug("Connection to air unit could not be closed gracefully. {}", ioe.getMessage()); + } finally { + socket = null; + iStream = null; + oStream = null; + } + connected = false; + } + + public byte[] sendRobustRequest(byte[] operation, byte[] register) throws IOException { + return sendRobustRequest(operation, register, EMPTY); + } + + public synchronized byte[] sendRobustRequest(byte[] operation, byte[] register, byte[] value) throws IOException { + connect(); + byte[] request = new byte[4 + value.length]; + System.arraycopy(operation, 0, request, 0, 2); + System.arraycopy(register, 0, request, 2, 2); + System.arraycopy(value, 0, request, 4, value.length); + try { + return sendRequestInternal(request); + } catch (IOException ioe) { + // retry once if there was connection problem + disconnect(); + connect(); + return sendRequestInternal(request); + } + } + + private synchronized byte[] sendRequestInternal(byte[] request) throws IOException { + + if (oStream == null) { + throw new IOException( + String.format("Output stream is null while sending request: %s", Arrays.toString(request))); + } + oStream.write(request); + oStream.flush(); + + byte[] result = new byte[63]; + if (iStream == null) { + throw new IOException( + String.format("Input stream is null while sending request: %s", Arrays.toString(request))); + } + // noinspection ResultOfMethodCallIgnored + iStream.read(result, 0, 63); + + return result; + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitConfiguration.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitConfiguration.java new file mode 100644 index 0000000000000..1fc109b91c9af --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitConfiguration.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link DanfossAirUnitConfiguration} class contains configuration parameters for the air unit. + * + * @author Ralf Duckstein - Initial contribution + * @author Robert Bach - heavy refactorings + */ +@NonNullByDefault +public class DanfossAirUnitConfiguration { + + public @Nullable String host; + + public int refreshInterval = 10; + + public long updateUnchangedValuesEveryMillis = 60000; +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitHandler.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitHandler.java new file mode 100644 index 0000000000000..a36913f36f750 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitHandler.java @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import static org.openhab.binding.danfossairunit.internal.DanfossAirUnitBindingConstants.PROPERTY_SERIAL; +import static org.openhab.binding.danfossairunit.internal.DanfossAirUnitBindingConstants.PROPERTY_UNIT_NAME; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Objects; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link DanfossAirUnitHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Ralf Duckstein - Initial contribution + * @author Robert Bach - heavy refactorings + */ +@NonNullByDefault +public class DanfossAirUnitHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(DanfossAirUnitHandler.class); + private @Nullable DanfossAirUnitConfiguration config; + private @Nullable ValueCache valueCache; + private @Nullable ScheduledFuture pollingJob; + private @Nullable DanfossAirUnit hrv; + + public DanfossAirUnitHandler(Thing thing) { + super(thing); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + updateAllChannels(); + } else { + try { + if (hrv == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.NONE, + "Air unit connection not initialized."); + return; + } + Channel channel = Channel.getByName(channelUID.getIdWithoutGroup()); + if (channel.getWriteAccessor() != null) { + updateState(channelUID, channel.getWriteAccessor().access(Objects.requireNonNull(hrv), command)); + } + } catch (IllegalArgumentException e) { + logger.debug("Ignoring unknown channel id: {}", channelUID.getIdWithoutGroup(), e); + } catch (IOException ioe) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, ioe.getMessage()); + } + } + } + + @Override + public void initialize() { + updateStatus(ThingStatus.UNKNOWN); + config = getConfigAs(DanfossAirUnitConfiguration.class); + valueCache = new ValueCache(config.updateUnchangedValuesEveryMillis); + try { + hrv = new DanfossAirUnit(InetAddress.getByName(config.host), 30046); + } catch (UnknownHostException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Unknown host: " + config.host); + return; + } + + scheduler.execute(() -> { + try { + thing.setProperty(PROPERTY_UNIT_NAME, hrv.getUnitName()); + thing.setProperty(PROPERTY_SERIAL, hrv.getUnitSerialNumber()); + pollingJob = scheduler.scheduleWithFixedDelay(this::updateAllChannels, 5, config.refreshInterval, + TimeUnit.SECONDS); + updateStatus(ThingStatus.ONLINE); + + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage()); + } + }); + } + + private void updateAllChannels() { + if (hrv == null) { + return; + } + DanfossAirUnit danfossAirUnit = hrv; + logger.debug("Updating DanfossHRV data '{}'", getThing().getUID()); + + for (Channel channel : Channel.values()) { + if (Thread.interrupted()) { + logger.debug("Polling thread interrupted..."); + return; + } + try { + updateState(channel.getGroup().getGroupName(), channel.getChannelName(), + channel.getReadAccessor().access(danfossAirUnit)); + } catch (UnexpectedResponseValueException e) { + updateState(channel.getGroup().getGroupName(), channel.getChannelName(), UnDefType.UNDEF); + logger.debug( + "Cannot update channel {}: an unexpected or invalid response has been received from the air unit: {}", + channel.getChannelName(), e.getMessage()); + } catch (IOException e) { + updateState(channel.getGroup().getGroupName(), channel.getChannelName(), UnDefType.UNDEF); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage()); + logger.debug("Cannot update channel {}: an error occurred retrieving the value: {}", + channel.getChannelName(), e.getMessage()); + } + } + + if (getThing().getStatus() == ThingStatus.OFFLINE) { + updateStatus(ThingStatus.ONLINE); + } + } + + @Override + public void dispose() { + logger.debug("Disposing Danfoss HRV handler '{}'", getThing().getUID()); + + if (pollingJob != null) { + pollingJob.cancel(true); + pollingJob = null; + } + + if (hrv != null) { + hrv.cleanUp(); + hrv = null; + } + } + + private void updateState(String groupId, String channelId, State state) { + if (valueCache.updateValue(channelId, state)) { + updateState(new ChannelUID(thing.getUID(), groupId, channelId), state); + } + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitHandlerFactory.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitHandlerFactory.java new file mode 100644 index 0000000000000..4e3f2d7b987b7 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitHandlerFactory.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import static org.openhab.binding.danfossairunit.internal.DanfossAirUnitBindingConstants.THING_TYPE_AIRUNIT; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link DanfossAirUnitHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Ralf Duckstein - Initial contribution + * @author Robert Bach - heavy refactorings + */ +@NonNullByDefault +@Component(configurationPid = "binding.danfossairunit", service = ThingHandlerFactory.class) +public class DanfossAirUnitHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_AIRUNIT); + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(THING_TYPE_AIRUNIT)) { + return new DanfossAirUnitHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitReadAccessor.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitReadAccessor.java new file mode 100644 index 0000000000000..848875f13eeb6 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitReadAccessor.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.types.State; + +/** + * The {@link DanfossAirUnitReadAccessor} encapsulates access to an air unit value to be read. + * + * @author Robert Bach - Initial contribution + */ +@FunctionalInterface +@NonNullByDefault +public interface DanfossAirUnitReadAccessor { + State access(DanfossAirUnit hrv) throws IOException, UnexpectedResponseValueException; +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitWriteAccessor.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitWriteAccessor.java new file mode 100644 index 0000000000000..ce16369a5661f --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/DanfossAirUnitWriteAccessor.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.State; + +/** + * The {@link DanfossAirUnitWriteAccessor} encapsulates access to an air unit value to be written. + * + * @author Robert Bach - Initial contribution + */ +@FunctionalInterface +@NonNullByDefault +public interface DanfossAirUnitWriteAccessor { + State access(DanfossAirUnit hrv, Command command) throws IOException; +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Mode.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Mode.java new file mode 100644 index 0000000000000..3f7e1c03b5809 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/Mode.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link Mode} enum represents an air unit operation mode. + * + * @author Robert Bach - Initial contribution + */ +@NonNullByDefault +public enum Mode { + DEMAND, + PROGRAM, + MANUAL, + OFF +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/UnexpectedResponseValueException.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/UnexpectedResponseValueException.java new file mode 100644 index 0000000000000..136b6a5970ee8 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/UnexpectedResponseValueException.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * An exception representing an unexpected value received from the air unit. + * + * @author Robert Bach - Initial contribution + */ +@NonNullByDefault +public class UnexpectedResponseValueException extends Exception { + + private static final long serialVersionUID = -5727747058755880978L; + + public UnexpectedResponseValueException(String message) { + super(message); + } + + public UnexpectedResponseValueException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/ValueCache.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/ValueCache.java new file mode 100644 index 0000000000000..836d53b4cf4d1 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/ValueCache.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.types.State; + +/** + * The {@link ValueCache} is responsible for holding the last value of the channels for a + * certain amount of time {@link ValueCache#durationMs} to prevent unnecessary event bus updates if the value didn't + * change. + * + * @author Robert Bach - Initial contribution + */ +@NonNullByDefault +public class ValueCache { + + private Map stateByValue = new HashMap<>(); + + private final long durationMs; + + public ValueCache(long durationMs) { + this.durationMs = durationMs; + } + + /** + * Updates or inserts the given value into the value cache. Returns true if there was no value in the cache + * for the given channelId or if the value has updated to a different value or if the value is older than + * the cache duration + */ + public boolean updateValue(String channelId, State newState) { + long currentTimeMs = Calendar.getInstance().getTimeInMillis(); + StateWithTimestamp oldState = stateByValue.get(channelId); + boolean writeToCache; + if (oldState == null) { + writeToCache = true; + } else { + writeToCache = !oldState.state.equals(newState) || oldState.timestamp < (currentTimeMs - durationMs); + } + if (writeToCache) { + stateByValue.put(channelId, new StateWithTimestamp(newState, currentTimeMs)); + } + return writeToCache; + } + + @NonNullByDefault + private static class StateWithTimestamp { + State state; + long timestamp; + + public StateWithTimestamp(State state, long timestamp) { + this.state = state; + this.timestamp = timestamp; + } + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/discovery/DanfossAirUnitDiscoveryService.java b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/discovery/DanfossAirUnitDiscoveryService.java new file mode 100644 index 0000000000000..92c70bbc15822 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/java/org/openhab/binding/danfossairunit/internal/discovery/DanfossAirUnitDiscoveryService.java @@ -0,0 +1,139 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal.discovery; + +import static org.openhab.binding.danfossairunit.internal.DanfossAirUnitBindingConstants.*; + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketTimeoutException; +import java.util.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Discovery service implementation to scan for available air units in the network via broadcast. + * + * @author Ralf Duckstein - Initial contribution + * @author Robert Bach - heavy refactorings + */ +@Component(service = DiscoveryService.class, immediate = true) +@NonNullByDefault +public class DanfossAirUnitDiscoveryService extends AbstractDiscoveryService { + + private static final int BROADCAST_PORT = 30045; + private static final byte[] DISCOVER_SEND = { 0x0c, 0x00, 0x30, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13 }; + private static final byte[] DISCOVER_RECEIVE = { 0x0d, 0x00, 0x07, 0x00, 0x02, 0x02, 0x00 }; + + private final Logger logger = LoggerFactory.getLogger(DanfossAirUnitDiscoveryService.class); + + public DanfossAirUnitDiscoveryService() { + super(SUPPORTED_THING_TYPES_UIDS, 15, true); + } + + @Override + public Set getSupportedThingTypes() { + return SUPPORTED_THING_TYPES_UIDS; + } + + @Override + protected void startBackgroundDiscovery() { + logger.debug("Start Danfoss Air CCM background discovery"); + scheduler.execute(this::discover); + } + + @Override + public void startScan() { + logger.debug("Start Danfoss Air CCM scan"); + discover(); + } + + private synchronized void discover() { + logger.debug("Try to discover all Danfoss Air CCM devices"); + + try (DatagramSocket socket = new DatagramSocket()) { + + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface networkInterface = interfaces.nextElement(); + if (networkInterface.isLoopback() || !networkInterface.isUp()) { + continue; + } + for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) { + if (interfaceAddress.getBroadcast() == null) { + continue; + } + logger.debug("Sending broadcast on interface {} to discover Danfoss Air CCM device...", + interfaceAddress.getAddress()); + sendBroadcastToDiscoverThing(socket, interfaceAddress.getBroadcast()); + } + } + + } catch (IOException e) { + logger.debug("No Danfoss Air CCM device found. Diagnostic: {}", e.getMessage()); + } + } + + private void sendBroadcastToDiscoverThing(DatagramSocket socket, InetAddress broadcastAddress) throws IOException { + socket.setBroadcast(true); + socket.setSoTimeout(500); + // send discover + byte[] sendBuffer = DISCOVER_SEND; + DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, broadcastAddress, BROADCAST_PORT); + socket.send(sendPacket); + logger.debug("Discover message sent"); + + // wait for responses + while (true) { + byte[] receiveBuffer = new byte[7]; + DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); + try { + socket.receive(receivePacket); + } catch (SocketTimeoutException e) { + break; // leave the endless loop + } + + byte[] data = receivePacket.getData(); + if (Arrays.equals(data, DISCOVER_RECEIVE)) { + logger.debug("Discover received correct response"); + + String host = receivePacket.getAddress().getHostName(); + Map properties = new HashMap<>(); + properties.put("host", host); + + logger.debug("Adding a new Danfoss Air Unit CCM '{}' to inbox", host); + + ThingUID uid = new ThingUID(THING_TYPE_AIRUNIT, String.valueOf(receivePacket.getAddress().hashCode())); + + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withRepresentationProperty("host") + .withProperties(properties).withLabel("Danfoss HRV").build(); + thingDiscovered(result); + + logger.debug("Thing discovered '{}'", result); + } + } + } +} diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.danfossairunit/src/main/resources/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..0c6673125fd81 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/resources/ESH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + DanfossAirUnit Binding + This is the binding for DanfossAirUnit. + Ralf Duckstein, Robert Bach + + diff --git a/bundles/org.openhab.binding.danfossairunit/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.danfossairunit/src/main/resources/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..86be859847101 --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/main/resources/ESH-INF/thing/thing-types.xml @@ -0,0 +1,199 @@ + + + + + + + The Danfoss Air Unit Heat Exchanger, CCM and Air Dial + + + + + + + + + + unknown + unknown + + + + + network-address + Host name or IP address of the Danfoss Air CCM + + + 10 + + Seconds + + + + 60000 + ms + Interval to update unchanged values (to the event bus) in milliseconds. A value of 0 means that every + value (received via polling from the air unit) is updated to the event bus, unchanged or not. + true + + + + + + + + + + + + + + + + + + + Enables fan boost + + + + Enables night cooling + + + + + + Temperature + + + + Temperature of the air in the room of the Air Dial + + + + Calculated Room Temperature + + + + Temperature of the air outside + + + + + + + + + + + + Heat exchaning device in the Air Unit + + + + Disables the heat exchange. Useful in summer when room temperature is above target and outside + temperature is below target. + + + + Temperature of air which is passed to the rooms + + + + Temperature of the air as extracted from the rooms + + + + Temperature of the air when pushed outside + + + + + + + + + Remaining Air Dial Battery Level + + + + Remaining life of filter until exchange is necessary + + + + + + + DateTime + + + + + String + + Off, Demand, Manual, Program + + + + + + + + + + + Dimmer + + + + + Number + + + + + Number + + + + + Dimmer + + + + + Dimmer + + + + + Number + + Read only percentage + + + + Number + + Humidity + + CurrentHumidity + + + + + + Switch + + + + Number:Temperature + + Current temperature + + + + diff --git a/bundles/org.openhab.binding.danfossairunit/src/test/java/org/openhab/binding/danfossairunit/internal/ValueCacheTest.java b/bundles/org.openhab.binding.danfossairunit/src/test/java/org/openhab/binding/danfossairunit/internal/ValueCacheTest.java new file mode 100644 index 0000000000000..842d4cc8c818d --- /dev/null +++ b/bundles/org.openhab.binding.danfossairunit/src/test/java/org/openhab/binding/danfossairunit/internal/ValueCacheTest.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.danfossairunit.internal; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.junit.Test; + +/** + * @author Robert Bach - Initial contribution + */ +@NonNullByDefault +public class ValueCacheTest { + + @Test + public void updateValueNotInCache() { + ValueCache valueCache = new ValueCache(10000); + assertTrue(valueCache.updateValue("channel", OnOffType.ON)); + } + + @Test + public void updateValueInCacheUnchangedWithinCacheDuration() { + ValueCache valueCache = new ValueCache(10000); + assertTrue(valueCache.updateValue("channel", OnOffType.ON)); + assertFalse(valueCache.updateValue("channel", OnOffType.ON)); + } + + @Test + public void updateValueInCacheChangedWithinCacheDuration() { + ValueCache valueCache = new ValueCache(10000); + assertTrue(valueCache.updateValue("channel", OnOffType.ON)); + assertTrue(valueCache.updateValue("channel", OnOffType.OFF)); + } + + @Test + public void updateValueInCacheUnchangedButCacheDurationExpired() throws InterruptedException { + ValueCache valueCache = new ValueCache(1); + assertTrue(valueCache.updateValue("channel", OnOffType.ON)); + Thread.sleep(2); + assertTrue(valueCache.updateValue("channel", OnOffType.ON)); + } + + @Test + public void updateValueMultipleCacheUpdatesButNotReportedAsToUpdate() throws InterruptedException { + ValueCache valueCache = new ValueCache(60); + assertTrue(valueCache.updateValue("channel", OnOffType.ON)); + Thread.sleep(30); + assertFalse(valueCache.updateValue("channel", OnOffType.ON)); + Thread.sleep(35); + assertTrue(valueCache.updateValue("channel", OnOffType.ON)); + } +} diff --git a/bundles/org.openhab.binding.darksky/pom.xml b/bundles/org.openhab.binding.darksky/pom.xml index b64d0f323d521..41653f63d7833 100644 --- a/bundles/org.openhab.binding.darksky/pom.xml +++ b/bundles/org.openhab.binding.darksky/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.darksky diff --git a/bundles/org.openhab.binding.darksky/src/main/feature/feature.xml b/bundles/org.openhab.binding.darksky/src/main/feature/feature.xml index 665164779eb5c..60a56c35b03a5 100644 --- a/bundles/org.openhab.binding.darksky/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.darksky/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.darksky/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.darksky/${project.version} + diff --git a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/config/DarkSkyChannelConfiguration.java b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/config/DarkSkyChannelConfiguration.java index 3a71c4e95c336..8d1ea63377c5f 100644 --- a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/config/DarkSkyChannelConfiguration.java +++ b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/config/DarkSkyChannelConfiguration.java @@ -15,7 +15,6 @@ import java.time.Duration; import java.util.regex.Pattern; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.slf4j.Logger; @@ -79,8 +78,8 @@ public String toString() { * Parses a hh:mm string and returns the minutes. */ private long getMinutesFromTime(@Nullable String configTime) { - String time = StringUtils.trimToNull(configTime); - if (time != null) { + String time = configTime; + if (time != null && !(time = time.trim()).isEmpty()) { try { if (!HHMM_PATTERN.matcher(time).matches()) { throw new NumberFormatException(); diff --git a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/connection/DarkSkyConnection.java b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/connection/DarkSkyConnection.java index 029b08010fa77..58d9158589641 100644 --- a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/connection/DarkSkyConnection.java +++ b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/connection/DarkSkyConnection.java @@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; @@ -99,9 +98,13 @@ public DarkSkyConnection(DarkSkyAPIHandler handler, HttpClient httpClient) { } DarkSkyAPIConfiguration config = handler.getDarkSkyAPIConfig(); + String apikey = config.apikey; + if (apikey == null || (apikey = apikey.trim()).isEmpty()) { + throw new DarkSkyConfigurationException("@text/offline.conf-error-missing-apikey"); + } - String url = String.format(Locale.ROOT, WEATHER_URL, StringUtils.trimToEmpty(config.apikey), - location.getLatitude().doubleValue(), location.getLongitude().doubleValue()); + String url = String.format(Locale.ROOT, WEATHER_URL, apikey, location.getLatitude().doubleValue(), + location.getLongitude().doubleValue()); return gson.fromJson(getResponseFromCache(buildURL(url, getRequestParams(config))), DarkSkyJsonWeatherData.class); @@ -114,7 +117,7 @@ public DarkSkyConnection(DarkSkyAPIHandler handler, HttpClient httpClient) { * @return the weather icon as {@link RawType} */ public static @Nullable RawType getWeatherIcon(String iconId) { - if (StringUtils.isEmpty(iconId)) { + if (iconId.isEmpty()) { throw new IllegalArgumentException("Cannot download weather icon as icon id is null."); } @@ -146,8 +149,8 @@ private Map getRequestParams(DarkSkyAPIConfiguration config) { params.put(PARAM_UNITS, "si"); - String language = StringUtils.trimToEmpty(config.language); - if (!language.isEmpty()) { + String language = config.language; + if (language != null && !(language = language.trim()).isEmpty()) { params.put(PARAM_LANG, language.toLowerCase()); } return params; @@ -155,7 +158,7 @@ private Map getRequestParams(DarkSkyAPIConfiguration config) { private String buildURL(String url, Map requestParams) { return requestParams.keySet().stream().map(key -> key + "=" + encodeParam(requestParams.get(key))) - .collect(joining("&", url + "?", StringUtils.EMPTY)); + .collect(joining("&", url + "?", "")); } private String encodeParam(String value) { @@ -163,7 +166,7 @@ private String encodeParam(String value) { return URLEncoder.encode(value, StandardCharsets.UTF_8.name()); } catch (UnsupportedEncodingException e) { logger.debug("UnsupportedEncodingException occurred during execution: {}", e.getLocalizedMessage(), e); - return StringUtils.EMPTY; + return ""; } } diff --git a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/handler/DarkSkyAPIHandler.java b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/handler/DarkSkyAPIHandler.java index 2606364388908..56f45ea4fe9d2 100644 --- a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/handler/DarkSkyAPIHandler.java +++ b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/handler/DarkSkyAPIHandler.java @@ -19,7 +19,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; @@ -75,7 +74,7 @@ public void initialize() { config = getConfigAs(DarkSkyAPIConfiguration.class); boolean configValid = true; - if (StringUtils.trimToNull(config.apikey) == null) { + if (config.apikey == null || config.apikey.trim().isEmpty()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-missing-apikey"); configValid = false; @@ -87,8 +86,7 @@ public void initialize() { configValid = false; } String language = config.language; - if (language != null) { - language = StringUtils.trimToEmpty(language); + if (language != null && !(language = language.trim()).isEmpty()) { if (!DarkSkyAPIConfiguration.SUPPORTED_LANGUAGES.contains(language.toLowerCase())) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-not-supported-language"); diff --git a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/handler/DarkSkyWeatherAndForecastHandler.java b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/handler/DarkSkyWeatherAndForecastHandler.java index 90684df03d886..daf1320e61cc7 100644 --- a/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/handler/DarkSkyWeatherAndForecastHandler.java +++ b/bundles/org.openhab.binding.darksky/src/main/java/org/openhab/binding/darksky/internal/handler/DarkSkyWeatherAndForecastHandler.java @@ -35,7 +35,6 @@ import javax.measure.Unit; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DateTimeType; @@ -128,7 +127,7 @@ public void initialize() { DarkSkyWeatherAndForecastConfiguration config = getConfigAs(DarkSkyWeatherAndForecastConfiguration.class); boolean configValid = true; - if (StringUtils.trimToNull(config.location) == null) { + if (config.location == null || config.location.trim().isEmpty()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-missing-location"); configValid = false; diff --git a/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/bridge-types.xml b/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/bridge-types.xml index 24ea9a6fe9733..70ed527db80d7 100644 --- a/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/bridge-types.xml +++ b/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/bridge-types.xml @@ -11,7 +11,7 @@ apikey - + diff --git a/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/channel-types.xml index 34117f3c7284d..2a96c4d61acdd 100644 --- a/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/channel-types.xml @@ -9,30 +9,30 @@ This is the current weather. - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -40,26 +40,26 @@ This is the 5 day / 3 hour weather forecast. - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + @@ -67,30 +67,30 @@ This is the 16 day / daily weather forecast. - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + @@ -98,12 +98,12 @@ Weather warnings issued for the requested location. - - - - - - + + + + + + @@ -113,7 +113,7 @@ Time of data observation. Time - + @@ -121,7 +121,7 @@ Time of data forecasted. Time - + @@ -129,7 +129,7 @@ Date of data forecasted. Time - + @@ -137,7 +137,7 @@ Current weather condition. Sun_Clouds - + @@ -145,21 +145,21 @@ Forecasted weather condition. Sun_Clouds - + Image Icon representing the weather condition. - + String Id of the icon to create the URL. - + @@ -167,7 +167,7 @@ Forecasted outdoor temperature. Temperature - + @@ -175,7 +175,7 @@ Minimum forecasted outdoor temperature. Temperature - + @@ -183,7 +183,7 @@ Maximum forecasted outdoor temperature. Temperature - + @@ -191,7 +191,7 @@ Current apparent temperature. Temperature - + @@ -199,7 +199,7 @@ Forecasted apparent temperature. Temperature - + @@ -207,7 +207,7 @@ Minimum forecasted apparent temperature. Temperature - + @@ -215,7 +215,7 @@ Maximum forecasted apparent temperature. Temperature - + @@ -223,7 +223,7 @@ Forecasted barometric pressure. Pressure - + @@ -231,7 +231,7 @@ Forecasted atmospheric relative humidity. Humidity - + @@ -239,7 +239,7 @@ Forecasted wind speed. Wind - + @@ -247,7 +247,7 @@ Forecasted wind direction expressed as an angle. Wind - + @@ -255,7 +255,7 @@ Current gust speed. Wind - + @@ -263,7 +263,7 @@ Forecasted gust speed. Wind - + @@ -271,7 +271,7 @@ Current cloudiness. Clouds - + @@ -279,21 +279,21 @@ Forecasted cloudiness. Clouds - + Number:Length Current visibility. - + Number:Length Forecasted visibility. - + @@ -301,7 +301,7 @@ Current rain intensity. Rain - + @@ -309,7 +309,7 @@ Forecasted rain intensity. Rain - + @@ -317,7 +317,7 @@ Current snow intensity. Snow - + @@ -325,35 +325,35 @@ Forecasted snow intensity. Snow - + Number:Speed Current precipitation intensity. - + Number:Speed Forecasted precipitation intensity. - + Number:Dimensionless Current precipitation probability. - + Number:Dimensionless Forecasted precipitation probability. - + @@ -386,28 +386,28 @@ Number Current UV index. - + Number Forecasted UV index. - + Number:ArealDensity Current ozone. - + Number:ArealDensity Forecasted ozone. - + @@ -415,7 +415,7 @@ Sunrise of the current day. Sun - + @@ -423,7 +423,7 @@ Forecasted sunrise of the day. Sun - + @@ -436,7 +436,7 @@ - + @@ -444,7 +444,7 @@ Sunset of the current day. Sun - + @@ -452,7 +452,7 @@ Forecasted sunset of the day. Sun - + @@ -465,49 +465,49 @@ - + String A brief description of the alert. - + String A detailed description of the alert. - + String The severity of the alert. - + DateTime The time at which the alert was issued. - + DateTime The time at which the alert will expire. - + String An external URI that one may refer to for detailed information about the alert. - + diff --git a/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/thing-types.xml index 0e8abcb5929e7..7a1ba61239c40 100644 --- a/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.darksky/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,14 +7,14 @@ - + Provides current weather and forecast data from the Dark Sky API. - + This is the weather forecast for the next hour. @@ -147,7 +147,7 @@ location - + diff --git a/bundles/org.openhab.binding.deconz/pom.xml b/bundles/org.openhab.binding.deconz/pom.xml index 1a53e4d8a90a2..92038b962ebf6 100644 --- a/bundles/org.openhab.binding.deconz/pom.xml +++ b/bundles/org.openhab.binding.deconz/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.deconz diff --git a/bundles/org.openhab.binding.deconz/src/main/feature/feature.xml b/bundles/org.openhab.binding.deconz/src/main/feature/feature.xml index dff0a3b336b82..b77377e2b7d60 100644 --- a/bundles/org.openhab.binding.deconz/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.deconz/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.deconz/${project.version} - + + openhab-runtime-base + openhab-transport-http + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.deconz/${project.version} + diff --git a/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/binding/binding.xml index 89bc397ecf352..45ddd6e22a3ef 100644 --- a/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/binding/binding.xml @@ -5,7 +5,9 @@ Dresden Elektronik deCONZ Binding Allows to use the real-time channel of the deCONZ software for Zigbee sensors and switches. - deCONZ is the accompanying software for the Raspbee and Conbee Zigbee dongles from Dresden Elektronik. - Is meant to be used together with the HUE binding which makes the lights and plugs available. + deCONZ is the + accompanying software for the Raspbee and Conbee Zigbee dongles from Dresden Elektronik. + Is meant to be used together + with the HUE binding which makes the lights and plugs available. David Graeff diff --git a/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/config/config.xml index 7a455b32502fc..230cfedb9c70a 100644 --- a/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/config/config.xml @@ -23,7 +23,8 @@ password - If no API Key is provided, a new one will be requested. You need to authorize the access on the deCONZ web interface. + If no API Key is provided, a new one will be requested. You need to authorize the access on the deCONZ + web interface. diff --git a/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/thing/thing-types.xml index a0f2ab559cffc..caa015752b045 100644 --- a/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.deconz/src/main/resources/ESH-INF/thing/thing-types.xml @@ -8,23 +8,23 @@ A running deCONZ software instance - + - + A Presence sensor - - + + uid - + @@ -39,23 +39,23 @@ The date and time when the sensor was last updated. Time - + - + A power sensor - - + + uid - + @@ -71,7 +71,7 @@ Current voltage Energy - + @@ -79,12 +79,12 @@ Current current Energy - + - + A consumption sensor @@ -95,7 +95,7 @@ uid - + @@ -107,19 +107,19 @@ - + A switch or button - - - + + + uid - + @@ -165,21 +165,21 @@ - + A light sensor - - - - - + + + + + uid - + @@ -193,37 +193,37 @@ Number Current light level. - + Switch Light level is below the darkness threshold. - + Switch Light level is above the daylight threshold. - + - + A temperature sensor - - + + uid - + @@ -235,18 +235,18 @@ - + A humidity sensor - - + + uid - + @@ -258,7 +258,7 @@ - + A pressure senor @@ -269,7 +269,7 @@ uid - + @@ -281,7 +281,7 @@ - + A daylight sensor @@ -292,7 +292,7 @@ uid - + @@ -317,18 +317,18 @@ - + A open/close sensor - - + + uid - + @@ -340,101 +340,101 @@ - + A water leakage sensor - - + + uid - + Switch Water leakage detected - + - + A fire sensor - - + + uid - + Switch A fire was detected. - + - + An alarm sensor - - + + uid - + Switch Alarm was triggered. - + Switch A zone is being tampered. - + - + A vibration sensor - - + + uid - + Switch Vibration was detected. - + diff --git a/bundles/org.openhab.binding.denonmarantz/pom.xml b/bundles/org.openhab.binding.denonmarantz/pom.xml index 23872b49333af..e51e6ac402830 100644 --- a/bundles/org.openhab.binding.denonmarantz/pom.xml +++ b/bundles/org.openhab.binding.denonmarantz/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.denonmarantz diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/feature/feature.xml b/bundles/org.openhab.binding.denonmarantz/src/main/feature/feature.xml index ddc816aaaf4f0..66dd063f4d886 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.denonmarantz/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - openhab.tp-jaxb - mvn:org.openhab.addons.bundles/org.openhab.binding.denonmarantz/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + openhab.tp-jaxb + mvn:org.openhab.addons.bundles/org.openhab.binding.denonmarantz/${project.version} + diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/DenonMarantzState.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/DenonMarantzState.java index cddf496975915..b5b641cb3c59b 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/DenonMarantzState.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/DenonMarantzState.java @@ -261,7 +261,6 @@ public void setZone3Volume(BigDecimal volume) { .valueOf(volume.subtract(DenonMarantzBindingConstants.DB_OFFSET).toString()); handler.stateChanged(DenonMarantzBindingConstants.CHANNEL_ZONE3_VOLUME_DB, this.zone3VolumeDB); } - } public void setZone3Mute(boolean mute) { @@ -298,7 +297,6 @@ public void setZone4Volume(BigDecimal volume) { .valueOf(volume.subtract(DenonMarantzBindingConstants.DB_OFFSET).toString()); handler.stateChanged(DenonMarantzBindingConstants.CHANNEL_ZONE4_VOLUME_DB, this.zone4VolumeDB); } - } public void setZone4Mute(boolean mute) { diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/DenonMarantzStateChangedListener.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/DenonMarantzStateChangedListener.java index 96307e224623b..6d4e6cd698c24 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/DenonMarantzStateChangedListener.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/DenonMarantzStateChangedListener.java @@ -26,7 +26,7 @@ public interface DenonMarantzStateChangedListener { * Update was received. * * @param channelID the channel for which its state changed - * @param state the new state of the channel + * @param state the new state of the channel */ void stateChanged(String channelID, State state); diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/UnsupportedCommandTypeException.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/UnsupportedCommandTypeException.java index 0cf72b4625f56..601103aa96199 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/UnsupportedCommandTypeException.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/UnsupportedCommandTypeException.java @@ -29,5 +29,4 @@ public UnsupportedCommandTypeException() { public UnsupportedCommandTypeException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/config/DenonMarantzConfiguration.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/config/DenonMarantzConfiguration.java index a307a57c2a831..8792b800f6942 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/config/DenonMarantzConfiguration.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/config/DenonMarantzConfiguration.java @@ -117,5 +117,4 @@ public void setZoneCount(Integer count) { Integer zoneCount = count; this.zoneCount = zoneCount; } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/DenonMarantzConnectorFactory.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/DenonMarantzConnectorFactory.java index 5c4ef4b9e2911..50bab9745cba1 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/DenonMarantzConnectorFactory.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/DenonMarantzConnectorFactory.java @@ -36,5 +36,4 @@ public DenonMarantzConnector getConnector(DenonMarantzConfiguration config, Deno return new DenonMarantzHttpConnector(config, state, scheduler, httpClient); } } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java index a0fd9afd2f9d5..250276c9f0ef5 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/http/DenonMarantzHttpConnector.java @@ -370,5 +370,4 @@ public String getLocalName() { return Introspector.decapitalize(super.getLocalName()); } } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/telnet/DenonMarantzTelnetClient.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/telnet/DenonMarantzTelnetClient.java index 496c523931eb0..425977ae2859a 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/telnet/DenonMarantzTelnetClient.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/telnet/DenonMarantzTelnetClient.java @@ -172,5 +172,4 @@ private void disconnect() { } } } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/telnet/DenonMarantzTelnetListener.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/telnet/DenonMarantzTelnetListener.java index 1bf3bb3d486ce..59af5dd004248 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/telnet/DenonMarantzTelnetListener.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/connector/telnet/DenonMarantzTelnetListener.java @@ -34,5 +34,4 @@ public interface DenonMarantzTelnetListener { * @param connected whether or not the connection was successful */ void telnetClientConnected(boolean connected); - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/Main.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/Main.java index b4943aff107a2..232ad2aac21cd 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/Main.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/Main.java @@ -36,5 +36,4 @@ public OnOffType getPower() { public void setPower(OnOffType power) { this.power = power; } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/ZoneStatus.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/ZoneStatus.java index ae2fe3dec63b9..63f838f602385 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/ZoneStatus.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/ZoneStatus.java @@ -100,5 +100,4 @@ public void setMute(OnOffType mute) { public List getInputFuncList() { return this.inputFunctions; } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/ZoneStatusLite.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/ZoneStatusLite.java index e017d92c924b0..e1dc67538bf6d 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/ZoneStatusLite.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/ZoneStatusLite.java @@ -78,5 +78,4 @@ public OnOffType getMute() { public void setMute(OnOffType mute) { this.mute = mute; } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/OnOffType.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/OnOffType.java index 90826605784dc..265051a6cc3f8 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/OnOffType.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/OnOffType.java @@ -36,5 +36,4 @@ public Boolean getValue() { public void setValue(Boolean value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/StringType.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/StringType.java index c1adc93b4ed05..fe7464ef2d4dc 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/StringType.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/StringType.java @@ -36,5 +36,4 @@ public String getValue() { public void setValue(String value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/VolumeType.java b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/VolumeType.java index fa4082cdfe1c3..f17d54df349b0 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/VolumeType.java +++ b/bundles/org.openhab.binding.denonmarantz/src/main/java/org/openhab/binding/denonmarantz/internal/xml/entities/types/VolumeType.java @@ -38,5 +38,4 @@ public BigDecimal getValue() { public void setValue(BigDecimal value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.denonmarantz/src/main/resources/ESH-INF/binding/binding.xml index 298dc38680d90..69b0e11b0f587 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.denonmarantz/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - DenonMarantz Binding diff --git a/bundles/org.openhab.binding.denonmarantz/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.denonmarantz/src/main/resources/ESH-INF/thing/thing-types.xml index 58fe92816abfe..51bf60a87e0f5 100644 --- a/bundles/org.openhab.binding.denonmarantz/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.denonmarantz/src/main/resources/ESH-INF/thing/thing-types.xml @@ -10,7 +10,7 @@ Control a Denon/Marantz AVR. - + Channels for the main zone of this AVR. @@ -55,8 +55,7 @@ 2 - + network-address Hostname or IP address of the AVR to control. @@ -64,7 +63,9 @@ - By using telnet the AVR updates are received immediately. Also, some devices only support telnet. However, the AVR only allows 1 simultaneous connection. Uncheck if you are using dedicated apps to control the AVR. Then HTTP polling is used instead. + By using telnet the AVR updates are received immediately. Also, some devices only support telnet. + However, the AVR only allows 1 simultaneous connection. Uncheck if you are using dedicated apps to control the AVR. + Then HTTP polling is used instead. @@ -81,8 +82,7 @@ true - + Refresh interval of the HTTP API in seconds (minimal 5) 5 @@ -95,12 +95,12 @@ General channels for this AVR. - - - - - - + + + + + + @@ -108,11 +108,11 @@ Channels for a zone of this AVR. - - - - - + + + + + @@ -140,7 +140,7 @@ Set the volume level (dB). Same as [mainVolume - 80]. SoundVolume - + @@ -203,28 +203,28 @@ String Select the surround program of the AVR - + String Displays the artist of the now playing song. - + String Displays the album of the now playing song. - + String Displays the title of the now playing track. - + diff --git a/bundles/org.openhab.binding.digiplex/pom.xml b/bundles/org.openhab.binding.digiplex/pom.xml index 6c9248db8ae32..de84e49fa0b83 100644 --- a/bundles/org.openhab.binding.digiplex/pom.xml +++ b/bundles/org.openhab.binding.digiplex/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.digiplex diff --git a/bundles/org.openhab.binding.digiplex/src/main/feature/feature.xml b/bundles/org.openhab.binding.digiplex/src/main/feature/feature.xml index f927556337fe0..6f1e372860785 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.digiplex/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.digiplex/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.digiplex/${project.version} + diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/DigiplexBindingConstants.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/DigiplexBindingConstants.java index bcbe6ea64ad02..94a4722a5b149 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/DigiplexBindingConstants.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/DigiplexBindingConstants.java @@ -86,5 +86,4 @@ public class DigiplexBindingConstants { public static final StringType COMMAND_FAIL = new StringType("Fail"); public static final int GLOBAL_AREA_NO = 0; - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/DigiplexHandlerFactory.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/DigiplexHandlerFactory.java index 9732fa2a0a32c..6e6d7129f298b 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/DigiplexHandlerFactory.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/DigiplexHandlerFactory.java @@ -22,10 +22,13 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.digiplex.internal.handler.DigiplexAreaHandler; import org.openhab.binding.digiplex.internal.handler.DigiplexBridgeHandler; import org.openhab.binding.digiplex.internal.handler.DigiplexZoneHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link DigiplexHandlerFactory} is responsible for creating things and thing @@ -37,6 +40,13 @@ @NonNullByDefault public class DigiplexHandlerFactory extends BaseThingHandlerFactory { + private final SerialPortManager serialPortManager; + + @Activate + public DigiplexHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); @@ -51,9 +61,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } else if (thingTypeUID.equals(THING_TYPE_AREA)) { return new DigiplexAreaHandler(thing); } else if (thingTypeUID.equals(THING_TYPE_BRIDGE)) { - return new DigiplexBridgeHandler((Bridge) thing); + return new DigiplexBridgeHandler((Bridge) thing, serialPortManager); } return null; } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaArmDisarmResponse.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaArmDisarmResponse.java index cdb82a85a30ce..c28be2f2877c2 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaArmDisarmResponse.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaArmDisarmResponse.java @@ -48,7 +48,5 @@ public static AreaArmDisarmResponse success(int areaNo, ArmDisarmType type) { @Override public void accept(DigiplexMessageHandler visitor) { visitor.handleArmDisarmAreaResponse(this); - } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaLabelRequest.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaLabelRequest.java index d59766c2bb68b..710620961fba4 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaLabelRequest.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaLabelRequest.java @@ -32,5 +32,4 @@ public AreaLabelRequest(int areaNo) { public String getSerialMessage() { return String.format("AL%03d\r", areaNo); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatus.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatus.java index 7da08ff102dae..85ae848ece273 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatus.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatus.java @@ -51,5 +51,4 @@ public static AreaStatus fromMessage(char indicator) { public StringType toStringType() { return new StringType(this.toString()); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatusRequest.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatusRequest.java index f3d8750b0cfa2..141ed30c3d5f4 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatusRequest.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatusRequest.java @@ -32,5 +32,4 @@ public AreaStatusRequest(int areaNo) { public String getSerialMessage() { return String.format("RA%03d\r", areaNo); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatusResponse.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatusResponse.java index ea8d8b06252c4..174320123ac5a 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatusResponse.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/AreaStatusResponse.java @@ -75,5 +75,4 @@ public static AreaStatusResponse success(int areaNo, AreaStatus status, boolean public void accept(DigiplexMessageHandler visitor) { visitor.handleAreaStatusResponse(this); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ArmDisarmType.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ArmDisarmType.java index 0555def21e004..c7f5c2448ecb9 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ArmDisarmType.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ArmDisarmType.java @@ -40,5 +40,4 @@ public static ArmDisarmType fromMessage(String indicator) { return Arrays.stream(ArmDisarmType.values()).filter(type -> type.indicator.equals(indicator)).findFirst() .orElse(UNKNOWN); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/CommunicationStatus.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/CommunicationStatus.java index 82f6b3f9f188b..3dd73ce55444c 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/CommunicationStatus.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/CommunicationStatus.java @@ -34,5 +34,4 @@ private CommunicationStatus(boolean success) { public void accept(DigiplexMessageHandler visitor) { visitor.handleCommunicationStatus(this); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexMessageHandler.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexMessageHandler.java index 801153122e52a..22ec985cb0633 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexMessageHandler.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexMessageHandler.java @@ -70,5 +70,4 @@ default void handleGenericEvent(GenericEvent event) { default void handleTroubleEvent(TroubleEvent troubleEvent) { } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexRequest.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexRequest.java index 0fbe4dc7c4b4d..9e65035b2034c 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexRequest.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexRequest.java @@ -24,5 +24,4 @@ public interface DigiplexRequest extends DigiplexMessage { String getSerialMessage(); - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexResponse.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexResponse.java index acae22659dc61..d84268bb9a537 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexResponse.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexResponse.java @@ -24,5 +24,4 @@ public interface DigiplexResponse extends DigiplexMessage { void accept(DigiplexMessageHandler visitor); - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexResponseResolver.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexResponseResolver.java index 091382cb4f28e..9200af7ceb78d 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexResponseResolver.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/DigiplexResponseResolver.java @@ -214,5 +214,4 @@ private static DigiplexResponse resolveSystemEvent(String message) { } return new GenericEvent(eventGroup, eventNumber, areaNumber); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/UnknownResponse.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/UnknownResponse.java index 10437c59a9524..17a37a679f32f 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/UnknownResponse.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/UnknownResponse.java @@ -33,5 +33,4 @@ public UnknownResponse(String message) { public void accept(DigiplexMessageHandler visitor) { visitor.handleUnknownResponse(this); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneLabelRequest.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneLabelRequest.java index 7f4559a48395f..9bb9b440ac463 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneLabelRequest.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneLabelRequest.java @@ -32,5 +32,4 @@ public ZoneLabelRequest(int zoneNo) { public String getSerialMessage() { return String.format("ZL%03d\r", zoneNo); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneStatus.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneStatus.java index f1b1226bd5575..a3fa234cc685e 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneStatus.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneStatus.java @@ -45,5 +45,4 @@ public static ZoneStatus fromMessage(char indicator) { return Arrays.stream(ZoneStatus.values()).filter(type -> type.indicator == indicator).findFirst() .orElse(UNKNOWN); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneStatusRequest.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneStatusRequest.java index 13dbcf6eeab79..2b1180a0f176b 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneStatusRequest.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/ZoneStatusRequest.java @@ -32,5 +32,4 @@ public ZoneStatusRequest(int zoneNo) { public String getSerialMessage() { return String.format("RZ%03d\r", zoneNo); } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/AbstractEvent.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/AbstractEvent.java index 4623612291dbf..141d9a08e77e2 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/AbstractEvent.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/AbstractEvent.java @@ -46,5 +46,4 @@ public boolean isForArea(int areaNo) { } return false; } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/TroubleType.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/TroubleType.java index 013e871ec0a55..93217b9ba9b26 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/TroubleType.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/TroubleType.java @@ -46,5 +46,4 @@ public String getBridgeChannel() { public static TroubleType fromEventNumber(int eventNumber) { return TroubleType.values()[eventNumber]; } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/ZoneStatusEvent.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/ZoneStatusEvent.java index d897382574a2b..1277bb74b496b 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/ZoneStatusEvent.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/communication/events/ZoneStatusEvent.java @@ -46,6 +46,5 @@ public ZoneStatus getStatus() { @Override public void accept(DigiplexMessageHandler visitor) { visitor.handleZoneStatusEvent(this); - } } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/DigiplexAreaHandler.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/DigiplexAreaHandler.java index 8028b13be1f5c..ae48f8d9686d0 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/DigiplexAreaHandler.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/DigiplexAreaHandler.java @@ -149,7 +149,6 @@ private void processControlCommand(String command) { bridgeHandler.sendRequest(new AreaDisarmRequest(areaNo, command.substring(1))); break; } - } @SuppressWarnings("null") diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/DigiplexBridgeHandler.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/DigiplexBridgeHandler.java index 0bd40c743669f..627c1b4280f4f 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/DigiplexBridgeHandler.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/DigiplexBridgeHandler.java @@ -29,7 +29,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -import org.apache.commons.io.IOUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DecimalType; @@ -43,6 +42,13 @@ import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.digiplex.internal.DigiplexBridgeConfiguration; import org.openhab.binding.digiplex.internal.communication.CommunicationStatus; import org.openhab.binding.digiplex.internal.communication.DigiplexMessageHandler; @@ -56,15 +62,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.RXTXPort; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * The {@link DigiplexBridgeHandler} is responsible for handling communication with PRT3 module * @@ -81,11 +78,12 @@ public class DigiplexBridgeHandler extends BaseBridgeHandler implements SerialPo private final Logger logger = LoggerFactory.getLogger(DigiplexBridgeHandler.class); private @Nullable DigiplexBridgeConfiguration config; - private @Nullable RXTXPort serialPort; + private @Nullable SerialPort serialPort; private @Nullable DigiplexReceiverThread receiverThread; private @Nullable DigiplexSenderThread senderThread; - private BlockingQueue sendQueue = new LinkedBlockingQueue<>(); - private Set handlers = ConcurrentHashMap.newKeySet(); + private final BlockingQueue sendQueue = new LinkedBlockingQueue<>(); + private final SerialPortManager serialPortManager; + private final Set handlers = ConcurrentHashMap.newKeySet(); @Nullable private ScheduledFuture reinitializeTask; @@ -94,8 +92,9 @@ public class DigiplexBridgeHandler extends BaseBridgeHandler implements SerialPo private AtomicLong responsesReceived = new AtomicLong(0); private AtomicLong eventsReceived = new AtomicLong(0); - public DigiplexBridgeHandler(Bridge bridge) { + public DigiplexBridgeHandler(Bridge bridge, SerialPortManager serialPortManager) { super(bridge); + this.serialPortManager = serialPortManager; } @SuppressWarnings("null") @@ -107,8 +106,27 @@ public void initialize() { return; } + SerialPortIdentifier portId = serialPortManager.getIdentifier(config.port); + if (portId == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + "No such port: " + config.port); + return; + } + try { - serialPort = initializeSerialPort(config.port); + serialPort = initializeSerialPort(portId); + + InputStream inputStream = serialPort.getInputStream(); + OutputStream outputStream = serialPort.getOutputStream(); + + if (inputStream == null || outputStream == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Input/Output stream null"); + return; + } + + receiverThread = new DigiplexReceiverThread(inputStream); + senderThread = new DigiplexSenderThread(outputStream); registerMessageHandler(new BridgeMessageHandler()); @@ -116,30 +134,26 @@ public void initialize() { responsesReceived.set(0); eventsReceived.set(0); - receiverThread = new DigiplexReceiverThread(serialPort.getInputStream()); - senderThread = new DigiplexSenderThread(serialPort.getOutputStream()); - receiverThread.start(); senderThread.start(); updateStatus(ThingStatus.ONLINE); } catch (PortInUseException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "Port is in use!"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Port in use: " + config.port); } catch (Exception e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "Communication error!"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Communication error: " + e.getMessage()); } - } @SuppressWarnings("null") - private @Nullable RXTXPort initializeSerialPort(String port) throws PortInUseException, NoSuchPortException, - TooManyListenersException, UnsupportedCommOperationException { - CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(port); - - RXTXPort serialPort = portId.open(getThing().getUID().toString(), 2000); + private @Nullable SerialPort initializeSerialPort(SerialPortIdentifier portId) + throws PortInUseException, TooManyListenersException, UnsupportedCommOperationException { + SerialPort serialPort = portId.open(getThing().getUID().toString(), 2000); serialPort.setSerialPortParams(config.baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); - serialPort.disableReceiveThreshold(); + serialPort.enableReceiveThreshold(0); serialPort.enableReceiveTimeout(1000); // RXTX serial port library causes high CPU load @@ -200,8 +214,24 @@ public void dispose() { senderThread = null; receiverThread = null; if (serialPort != null) { - IOUtils.closeQuietly(serialPort.getInputStream()); - IOUtils.closeQuietly(serialPort.getOutputStream()); + try { + InputStream inputStream = serialPort.getInputStream(); + if (inputStream != null) { + inputStream.close(); + } + } catch (IOException e) { + logger.debug("Error closing input stream", e); + } + + try { + OutputStream outputStream = serialPort.getOutputStream(); + if (outputStream != null) { + outputStream.close(); + } + } catch (IOException e) { + logger.debug("Error closing output stream", e); + } + serialPort.close(); serialPort = null; } diff --git a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/TypeUtils.java b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/TypeUtils.java index 4e0203eb17192..550ef617a8ffe 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/TypeUtils.java +++ b/bundles/org.openhab.binding.digiplex/src/main/java/org/openhab/binding/digiplex/internal/handler/TypeUtils.java @@ -27,5 +27,4 @@ public class TypeUtils { public static OpenClosedType openClosedFromBoolean(boolean value) { return value ? OpenClosedType.OPEN : OpenClosedType.CLOSED; } - } diff --git a/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/area.xml b/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/area.xml index bc0e7ea788425..be90d00b23ffc 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/area.xml +++ b/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/area.xml @@ -6,20 +6,20 @@ - + Area - - - - - - - - - + + + + + + + + + @@ -130,7 +130,8 @@ String - Used to control area status. By reading its state one can check result of the last command sent to the alarm system. + Used to control area status. By reading its state one can check result of the last command sent to the + alarm system. diff --git a/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/bridge.xml index e92563e7d3d0a..4403ca5354540 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/bridge.xml @@ -8,8 +8,8 @@ Digiplex PRT3 module with Serial Interface - - + + @@ -23,6 +23,7 @@ serial-port + false Set the serial port used to access PRT3 device @@ -47,9 +48,9 @@ Statistics of PRT3 communication - - - + + + @@ -57,14 +58,14 @@ Problems reported by the alarm system - - - - - - - - + + + + + + + + diff --git a/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/zone.xml b/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/zone.xml index 69e11cff68c3c..e104ff0116cf2 100644 --- a/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/zone.xml +++ b/bundles/org.openhab.binding.digiplex/src/main/resources/ESH-INF/thing/zone.xml @@ -6,18 +6,18 @@ - + Zone - - - - - - - + + + + + + + @@ -99,7 +99,7 @@ DateTime Indicates when the zone has been triggered for the last time - + diff --git a/bundles/org.openhab.binding.digitalstrom/pom.xml b/bundles/org.openhab.binding.digitalstrom/pom.xml index 584d66b6b18ab..560769df84afe 100644 --- a/bundles/org.openhab.binding.digitalstrom/pom.xml +++ b/bundles/org.openhab.binding.digitalstrom/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.digitalstrom diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/feature/feature.xml b/bundles/org.openhab.binding.digitalstrom/src/main/feature/feature.xml index 7d06aa273d5df..fc7077185674f 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - mvn:org.openhab.addons.bundles/org.openhab.binding.digitalstrom/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + mvn:org.openhab.addons.bundles/org.openhab.binding.digitalstrom/${project.version} + diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/DigitalSTROMBindingConstants.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/DigitalSTROMBindingConstants.java index f91ddddd3bcfe..d4b9fd12c1142 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/DigitalSTROMBindingConstants.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/DigitalSTROMBindingConstants.java @@ -106,5 +106,4 @@ public class DigitalSTROMBindingConstants { public static final String API_VERSION = "apiVersion"; public static final String DSP_SW_VERSION = "armSwVersion"; public static final String ARM_SW_VERSION = "dspSwVersion"; - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/discovery/DiscoveryServiceManager.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/discovery/DiscoveryServiceManager.java index 6ab6142bd2ef3..318144be652bd 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/discovery/DiscoveryServiceManager.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/discovery/DiscoveryServiceManager.java @@ -250,12 +250,10 @@ public Integer getTemperationControlStatusListenrID() { @Override public void onTargetTemperatureChanged(Float newValue) { // nothing to do - } @Override public void onControlValueChanged(Integer newValue) { // nothing to do - } } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/CircuitHandler.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/CircuitHandler.java index aa546efe28354..fa65b948a2034 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/CircuitHandler.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/CircuitHandler.java @@ -180,7 +180,6 @@ public void onDeviceStateChanged(DeviceStateUpdate deviceStateUpdate) { } } } - } @Override @@ -309,5 +308,4 @@ public void onSceneConfigAdded(short sceneID) { public String getDeviceStatusListenerID() { return this.dSID; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/DeviceHandler.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/DeviceHandler.java index 26acb664207db..94bf072ff8a74 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/DeviceHandler.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/DeviceHandler.java @@ -768,7 +768,6 @@ private void loadOutputChannel(ChannelTypeUID channelTypeUID, String acceptedIte updateThing(thingBuilder.build()); logger.debug("load channel: {} with item: {}", channelTypeUID.getAsString(), acceptedItemType); } - } private ChannelUID getSensorChannelUID(SensorEnum sensorType) { @@ -935,7 +934,6 @@ public synchronized void onSceneConfigAdded(short sceneId) { // super.updateThing(editThing().build()); } } - } @Override diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/SceneHandler.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/SceneHandler.java index be199d9853b11..9e22775e173b8 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/SceneHandler.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/SceneHandler.java @@ -304,7 +304,6 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else { logger.warn("Command sent to an unknown channel id: {}", channelUID); } - } private synchronized BridgeHandler getBridgeHandler() { diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/ZoneTemperatureControlHandler.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/ZoneTemperatureControlHandler.java index bc52eaa28a895..0f8e634faafcc 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/ZoneTemperatureControlHandler.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/ZoneTemperatureControlHandler.java @@ -231,7 +231,6 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else { logger.debug("Command sent to an unknown channel id: {}", channelUID); } - } private boolean isTemperature() { @@ -356,5 +355,4 @@ public void registerTemperatureSensorTransmitter( public Integer getTemperationControlStatusListenrID() { return zoneID; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/datatypes/CachedSensorValue.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/datatypes/CachedSensorValue.java index e8ff19e5cc264..63366f85243e9 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/datatypes/CachedSensorValue.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/datatypes/CachedSensorValue.java @@ -153,5 +153,4 @@ public boolean equals(Object obj) { } return true; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/BaseTemperatureControl.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/BaseTemperatureControl.java index 004012a074b3e..5f5025ea8ed01 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/BaseTemperatureControl.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/BaseTemperatureControl.java @@ -91,5 +91,4 @@ public Short getControlMode() { public Boolean isNotSetOff() { return !ControlModes.OFF.getID().equals(controlMode); } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/AssignedSensors.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/AssignedSensors.java index 398bcff565d3d..08bd1e404d4d7 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/AssignedSensors.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/AssignedSensors.java @@ -153,5 +153,4 @@ public boolean existsAssignedSensors() { public String toString() { return "AssignedSensors [sensors=" + sensors + "]"; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/SensorValues.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/SensorValues.java index df9beddd06255..038f3e5e1446c 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/SensorValues.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/SensorValues.java @@ -96,5 +96,4 @@ public Integer getZoneID() { public String getZoneName() { return zoneName; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/TemperatureControlConfig.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/TemperatureControlConfig.java index 71dfe5be732bc..551ea3123582e 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/TemperatureControlConfig.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/TemperatureControlConfig.java @@ -116,7 +116,6 @@ private void init(JsonObject jObject) { } } } - } /** diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/TemperatureControlInternals.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/TemperatureControlInternals.java index bf62c3f1ebb6c..d2b83cc4ce9c4 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/TemperatureControlInternals.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/climate/jsonresponsecontainer/impl/TemperatureControlInternals.java @@ -200,5 +200,4 @@ public String toString() { + ctrlTErrorPrev + ", ctrlIntegral=" + ctrlIntegral + ", ctrlYp=" + ctrlYp + ", ctrlYi=" + ctrlYi + ", ctrlYd=" + ctrlYd + ", ctrlY=" + ctrlY + ", ctrlAntiWindUp=" + ctrlAntiWindUp + "]"; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/event/EventListener.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/event/EventListener.java index 8e113d2c09954..a09ffb1845abe 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/event/EventListener.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/event/EventListener.java @@ -358,7 +358,6 @@ public void run() { } subscriptionScheduler.cancel(true); } - }, 0, SUBSCRIBE_DELAY, TimeUnit.MILLISECONDS); } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/event/constants/EventNames.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/event/constants/EventNames.java index 28d69fc624e44..9e00fb4134113 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/event/constants/EventNames.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/event/constants/EventNames.java @@ -27,5 +27,4 @@ public class EventNames { public static final String UNDO_SCENE = "undoScene"; public static final String DEVICE_SENSOR_VALUE = "deviceSensorValue"; public static final String DEVICE_BINARY_INPUT_EVENT = "deviceBinaryInputEvent"; - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/DeviceStatusManagerImpl.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/DeviceStatusManagerImpl.java index f28cf9ec5a8ed..f5e70bf70554e 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/DeviceStatusManagerImpl.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/DeviceStatusManagerImpl.java @@ -473,7 +473,6 @@ && checkAngleIsMinMax(device) == 0)) { } } } - } private void removeSensorJob(Device eshDevice, DeviceStateUpdate deviceStateUpdate) { @@ -1206,7 +1205,6 @@ private void getMeterData() { if (totalPowerConsumptionListener != null) { totalPowerConsumptionListener.onEnergyMeterValueChanged(val); } - } @Override diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/StructureManagerImpl.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/StructureManagerImpl.java index 549fb25efc2c4..f2f07b9dacd69 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/StructureManagerImpl.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/StructureManagerImpl.java @@ -109,7 +109,6 @@ public StructureManagerImpl(List referenceDeviceList, List refe * Creates a new {@link StructureManagerImpl} without {@link Device}s. */ public StructureManagerImpl() { - } @Override diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/sensorjobexecutor/SceneReadingJobExecutor.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/sensorjobexecutor/SceneReadingJobExecutor.java index 2681d5d63e755..114bf127dc041 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/sensorjobexecutor/SceneReadingJobExecutor.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/sensorjobexecutor/SceneReadingJobExecutor.java @@ -57,7 +57,6 @@ public void addHighPriorityJob(SensorJob sensorJob) { addSensorJobToCircuitScheduler(sensorJob); logger.debug("Add SceneReadingJob from device with dSID {} and high-priority to SceneReadingSobExecutor", sensorJob.getDSID()); - } @Override diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/sensorjobexecutor/sensorjob/impl/DeviceOutputValueSensorJob.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/sensorjobexecutor/sensorjob/impl/DeviceOutputValueSensorJob.java index 262da686fb6e8..eb465661564d9 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/sensorjobexecutor/sensorjob/impl/DeviceOutputValueSensorJob.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/sensorjobexecutor/sensorjob/impl/DeviceOutputValueSensorJob.java @@ -138,5 +138,4 @@ public String getID() { public static String getID(Device device) { return DeviceOutputValueSensorJob.class.getSimpleName() + "-" + device.getDSID().getValue(); } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/DsAPI.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/DsAPI.java index 56bfcadf6fd64..5cd74cba59706 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/DsAPI.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/DsAPI.java @@ -1107,5 +1107,4 @@ boolean pushZoneSensorValue(String sessionToken, Integer zoneID, String zoneName * @return true, if successful */ Boolean propertyTreeRemove(String sessionToken, String path); - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/constants/JSONApiResponseKeysEnum.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/constants/JSONApiResponseKeysEnum.java index 02e295fb97a23..67f045b83724b 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/constants/JSONApiResponseKeysEnum.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/constants/JSONApiResponseKeysEnum.java @@ -233,5 +233,4 @@ private JSONApiResponseKeysEnum(String key) { public String getKey() { return key; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/DsAPIImpl.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/DsAPIImpl.java index ba9d423f45ead..93ec6135a0ace 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/DsAPIImpl.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/DsAPIImpl.java @@ -567,7 +567,6 @@ public boolean setDeviceValue(String token, DSID dSID, String dSUID, String name return JSONResponseHandler.checkResponse(JSONResponseHandler.toJsonObject(response)); } return false; - } @Override diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java index 5003012f7d157..6953eb8a76ffc 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/HttpTransportImpl.java @@ -581,12 +581,10 @@ public java.security.cert.X509Certificate[] getAcceptedIssuers() { @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { - } @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { - } } }; diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/JSONResponseHandler.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/JSONResponseHandler.java index da0d4d2b2550d..54eff09cf9f7e 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/JSONResponseHandler.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/impl/JSONResponseHandler.java @@ -83,5 +83,4 @@ public static JsonObject getResultJsonObject(JsonObject jsonObject) { } return null; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/simpledsrequestbuilder/SimpleRequestBuilder.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/simpledsrequestbuilder/SimpleRequestBuilder.java index 6dd65757f1e77..6a550dd18ce8e 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/simpledsrequestbuilder/SimpleRequestBuilder.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/simpledsrequestbuilder/SimpleRequestBuilder.java @@ -52,7 +52,6 @@ public class SimpleRequestBuilder { private static final Lock LOCK = new ReentrantLock(); private SimpleRequestBuilder() { - } /** diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/simpledsrequestbuilder/constants/ClassKeys.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/simpledsrequestbuilder/constants/ClassKeys.java index e6b68ac8c4aaf..2bb18f9b04ed2 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/simpledsrequestbuilder/constants/ClassKeys.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/simpledsrequestbuilder/constants/ClassKeys.java @@ -29,5 +29,4 @@ public class ClassKeys { public static final String METERING = "metering"; public static final String SYSTEM = "system"; public static final String PROPERTY_TREE = "property"; - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/Circuit.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/Circuit.java index 7c95f42f1e6e8..15aa098339f58 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/Circuit.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/Circuit.java @@ -290,5 +290,4 @@ public interface Circuit extends GeneralDeviceInformation { * @return list of all {@link CachedMeteringValue} */ List getAllCachedMeteringValues(); - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/DeviceConstants.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/DeviceConstants.java index 5ef7bc86482fa..72603c9d085d3 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/DeviceConstants.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/DeviceConstants.java @@ -62,5 +62,4 @@ public interface DeviceConstants { /** this index is needed to get the angle of the slats (if device is a blind/jalousie) */ static final short DEVICE_SENSOR_SLAT_ANGLE_OUTPUT = 4; - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FunctionalColorGroupEnum.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FunctionalColorGroupEnum.java index d6640cfe5b9c7..88218ebe900b1 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FunctionalColorGroupEnum.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FunctionalColorGroupEnum.java @@ -99,5 +99,4 @@ private FunctionalColorGroupEnum(List functionalColorGroupID) { public List getFunctionalColorGroup() { return colorGroup; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/SensorEnum.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/SensorEnum.java index f6c581329bcba..658110a02c883 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/SensorEnum.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/SensorEnum.java @@ -246,5 +246,4 @@ public Float getMax() { public Float getResolution() { return resolution; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/impl/DeviceBinaryInput.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/impl/DeviceBinaryInput.java index 0294647dce774..f3b7423bc1d8f 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/impl/DeviceBinaryInput.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/impl/DeviceBinaryInput.java @@ -175,5 +175,4 @@ public String toString() { return "DeviceBinaryInput [targetGroupType=" + targetGroupType + ", targetGroup=" + targetGroup + ", inputType=" + inputType + ", inputId=" + inputId + ", state=" + stateValue + "]"; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/impl/DeviceSensorValue.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/impl/DeviceSensorValue.java index cec6210d342e5..26f4fdeb4f300 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/impl/DeviceSensorValue.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/impl/DeviceSensorValue.java @@ -280,5 +280,4 @@ public boolean equals(Object obj) { } return true; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImpl.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImpl.java index 8f89c85407e96..3b35644eaf7bf 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImpl.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImpl.java @@ -1801,7 +1801,6 @@ public void saveConfigSceneSpecificationIntoDevice(String propertries) { } } } - } @Override diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/scene/InternalScene.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/scene/InternalScene.java index 19ebbdae401e5..05fcc3fde827d 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/scene/InternalScene.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/scene/InternalScene.java @@ -230,7 +230,6 @@ public void checkDeviceSceneConfig() { */ public List getDeviceList() { return this.devices; - } /** @@ -329,7 +328,6 @@ public synchronized void registerSceneListener(SceneStatusListener listener) { this.listener = listener; this.listener.onSceneAdded(this); checkDeviceSceneConfig(); - } /** diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/providers/DsDeviceThingTypeProvider.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/providers/DsDeviceThingTypeProvider.java index 11f7c3f0a2975..c3acb11bc4e4d 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/providers/DsDeviceThingTypeProvider.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/providers/DsDeviceThingTypeProvider.java @@ -172,5 +172,4 @@ public ThingType getThingType(ThingTypeUID thingTypeUID, Locale locale) { } return null; } - } diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/binding/binding.xml index cdeaf3ad9f542..309ea92557447 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/binding/binding.xml @@ -1,7 +1,7 @@ - + @text/binding_name @text/binding_desc diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/config/bridgeConfig.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/config/bridgeConfig.xml index 49993b0697430..8d6101b051203 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/config/bridgeConfig.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/config/bridgeConfig.xml @@ -1,9 +1,9 @@ - + https://openhab.org/schemas/config-description-1.0.0.xsd"> diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/config/deviceConfig.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/config/deviceConfig.xml index 78ba7f53158dc..da12533fbfeaa 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/config/deviceConfig.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/config/deviceConfig.xml @@ -1,9 +1,9 @@ - + https://openhab.org/schemas/config-description-1.0.0.xsd"> diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/AppartmentScene.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/AppartmentScene.xml index d38bc7c98cf9b..9712bf3b55050 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/AppartmentScene.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/AppartmentScene.xml @@ -1,17 +1,17 @@ - + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + @text/app_scene_desc - + diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/GroupScene.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/GroupScene.xml index 88c45e5941f7f..b597c64008968 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/GroupScene.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/GroupScene.xml @@ -1,18 +1,18 @@ - + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + @text/group_scene_desc - + diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/NamedScene.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/NamedScene.xml index f6f38488ad2f4..8edcfeac41096 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/NamedScene.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/NamedScene.xml @@ -1,18 +1,18 @@ - + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + @text/named_scene_desc - + diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/ZoneScene.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/ZoneScene.xml index 900509fb9fb49..e2dc0471bdc8a 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/ZoneScene.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/ZoneScene.xml @@ -1,18 +1,18 @@ - + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + @text/zone_scene_desc - + diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/ZoneTemperatureControl.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/ZoneTemperatureControl.xml index f6479c134f2b4..32346f11ece82 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/ZoneTemperatureControl.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/ZoneTemperatureControl.xml @@ -1,11 +1,11 @@ - + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/dssBridge.xml b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/dssBridge.xml index bcf799df514e3..9918f663a2ea1 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/dssBridge.xml +++ b/bundles/org.openhab.binding.digitalstrom/src/main/resources/ESH-INF/thing/dssBridge.xml @@ -1,22 +1,22 @@ - + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @text/dSS_desc - - - + + + - + diff --git a/bundles/org.openhab.binding.dlinksmarthome/pom.xml b/bundles/org.openhab.binding.dlinksmarthome/pom.xml index 027d6ae00246d..905e8daa1fe63 100644 --- a/bundles/org.openhab.binding.dlinksmarthome/pom.xml +++ b/bundles/org.openhab.binding.dlinksmarthome/pom.xml @@ -1,17 +1,19 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.dlinksmarthome openHAB Add-ons :: Bundles :: D-Link Smart Home Binding - + !javax.xml.soap, com.sun.xml.messaging.saaj.soap diff --git a/bundles/org.openhab.binding.dlinksmarthome/src/main/feature/feature.xml b/bundles/org.openhab.binding.dlinksmarthome/src/main/feature/feature.xml index 89ec4f621cdd8..e519a92c61cc6 100644 --- a/bundles/org.openhab.binding.dlinksmarthome/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.dlinksmarthome/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - openhab.tp-jaxws - mvn:org.openhab.addons.bundles/org.openhab.binding.dlinksmarthome/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + openhab.tp-jaxws + mvn:org.openhab.addons.bundles/org.openhab.binding.dlinksmarthome/${project.version} + diff --git a/bundles/org.openhab.binding.dlinksmarthome/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.dlinksmarthome/src/main/resources/ESH-INF/binding/binding.xml index 884a36143dbc6..05322996fa563 100644 --- a/bundles/org.openhab.binding.dlinksmarthome/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.dlinksmarthome/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + D-Link Smart Home Binding This is the binding for D-Link Smart Home devices diff --git a/bundles/org.openhab.binding.dlinksmarthome/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.dlinksmarthome/src/main/resources/ESH-INF/thing/thing-types.xml index 6545241d5f926..f3948ffb08dd8 100644 --- a/bundles/org.openhab.binding.dlinksmarthome/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.dlinksmarthome/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> diff --git a/bundles/org.openhab.binding.dmx/pom.xml b/bundles/org.openhab.binding.dmx/pom.xml index 8284abf21bf7a..e84933fe3d8eb 100644 --- a/bundles/org.openhab.binding.dmx/pom.xml +++ b/bundles/org.openhab.binding.dmx/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.dmx diff --git a/bundles/org.openhab.binding.dmx/src/main/feature/feature.xml b/bundles/org.openhab.binding.dmx/src/main/feature/feature.xml index 44ef74cf2fc1a..731b03d7bd462 100644 --- a/bundles/org.openhab.binding.dmx/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.dmx/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.dmx/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.dmx/${project.version} + diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/action/BaseAction.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/action/BaseAction.java index 6bf1137517462..95f1bd3428731 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/action/BaseAction.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/action/BaseAction.java @@ -48,5 +48,4 @@ public void reset() { startTime = 0; state = ActionState.WAITING; } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/action/ResumeAction.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/action/ResumeAction.java index 71defc48f77ca..9fc1f9aadbbcf 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/action/ResumeAction.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/action/ResumeAction.java @@ -28,5 +28,4 @@ public int getNewValue(DmxChannel channel, long currentTime) { channel.resumeAction(); return channel.getNewHiResValue(currentTime); } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/ArtnetPacket.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/ArtnetPacket.java index 6e13bb9a57911..e0a5b37166d32 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/ArtnetPacket.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/ArtnetPacket.java @@ -107,5 +107,4 @@ public void setPayload(byte[] payload, int payloadSize) { public int getPacketLength() { return (18 + this.payloadSize); } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/DmxOverEthernetHandler.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/DmxOverEthernetHandler.java index 45b7fe64ed7ad..c0c668d00d793 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/DmxOverEthernetHandler.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/DmxOverEthernetHandler.java @@ -129,5 +129,4 @@ protected void sendDmxData() { public DmxOverEthernetHandler(Bridge sacnBridge) { super(sacnBridge); } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/DmxOverEthernetPacket.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/DmxOverEthernetPacket.java index d2b88598b7360..c89b872795540 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/DmxOverEthernetPacket.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/DmxOverEthernetPacket.java @@ -94,5 +94,4 @@ public int getUniverse() { public int getPayloadSize() { return this.payloadSize; } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/SacnPacket.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/SacnPacket.java index 58957ffe9a5a4..6a0597eeb9612 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/SacnPacket.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/dmxoverethernet/SacnPacket.java @@ -181,5 +181,4 @@ public void setPayload(byte[] payload, int payloadSize) { public int getPacketLength() { return (126 + this.payloadSize); } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/ChaserThingHandler.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/ChaserThingHandler.java index 83bf8f8bda48e..f9ab2be4b925f 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/ChaserThingHandler.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/ChaserThingHandler.java @@ -213,5 +213,4 @@ public void updateSwitchState(ChannelUID channelUID, State state) { logger.debug("unknown state received: {} in channel {} thing {}", state, channelUID, this.thing.getUID()); } } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/Lib485BridgeHandler.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/Lib485BridgeHandler.java index f086422a8dddd..4d1aa2298a0e3 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/Lib485BridgeHandler.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/Lib485BridgeHandler.java @@ -157,5 +157,4 @@ public void initialize() { updateConfiguration(); } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/TunableWhiteThingHandler.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/TunableWhiteThingHandler.java index b25b279002141..5c984efc2d621 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/TunableWhiteThingHandler.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/handler/TunableWhiteThingHandler.java @@ -319,5 +319,4 @@ private void updateCurrentBrightnessAndTemperature() { 100 * currentValues.get(1) / (currentValues.get(0) + currentValues.get(1))); } } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/multiverse/DmxChannel.java b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/multiverse/DmxChannel.java index dbf1b799ca117..bd094e21fcf17 100644 --- a/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/multiverse/DmxChannel.java +++ b/bundles/org.openhab.binding.dmx/src/main/java/org/openhab/binding/dmx/internal/multiverse/DmxChannel.java @@ -356,5 +356,4 @@ public void removeListener(ChannelUID thingChannel) { logger.trace("listener {} not found in DMX channel {}", thingChannel, this); } } - } diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/binding/binding.xml index c0b423b86640c..e0016d429157e 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,7 @@ - + DMX Binding This is the binding for DMX. Jan N. Klug diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/artnet-bridge.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/artnet-bridge.xml index e74d37cbe7116..ce5b2db5bfc84 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/artnet-bridge.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/artnet-bridge.xml @@ -1,5 +1,7 @@ - + @@ -10,7 +12,8 @@ - Network addresses of ArtNet receivers, format: address[:port][, address[:port], ...]. Default port is 6454. + Network addresses of ArtNet receivers, format: address[:port][, address[:port], ...]. Default port is + 6454. true @@ -38,7 +41,7 @@ List of channels that should use LED dim curve. Format is channel[,channel, ...] or channel[/width]. true - + DMX refresh rate in Hz (0=disable output) 30 true diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/channels.xml index 77955368c244a..bae3f02d3b26a 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/channels.xml @@ -1,10 +1,13 @@ - + Dimmer - Allows to send a brightness value to the thing. If the thing is associated with more than one DMX channel, the values is used for ALL DMX channels. + Allows to send a brightness value to the thing. If the thing is associated with more than one DMX + channel, the values is used for ALL DMX channels. DimmableLight Lighting @@ -24,7 +27,8 @@ Color - Allows to send a color value to the thing. If the thing is associated with more than one DMX channel, color will be re-use in 3-channel groups. + Allows to send a color value to the thing. If the thing is associated with more than one DMX channel, + color will be re-use in 3-channel groups. ColorLight Lighting diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/chaser-thing.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/chaser-thing.xml index 7daa425457294..a7ad88b25feba 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/chaser-thing.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/chaser-thing.xml @@ -1,5 +1,7 @@ - + @@ -10,8 +12,8 @@ A single/multi-channel chaser - - + + diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/color-thing.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/color-thing.xml index 47043bbbd7b79..b2ba8c8a86098 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/color-thing.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/color-thing.xml @@ -1,19 +1,21 @@ - + - - - + + + A RGB capable dimmer - - - - + + + + @@ -33,13 +35,15 @@ - Format is "value[, value, ...]", has to be a multiple of three. If less values than channels are defined, they are reused from the beginning. + Format is "value[, value, ...]", has to be a multiple of three. If less values than channels are + defined, they are reused from the beginning. false true - Format is "value[, value, ...]", has to be a multiple of three. If less values than channels are defined, they are reused from the beginning. + Format is "value[, value, ...]", has to be a multiple of three. If less values than channels are + defined, they are reused from the beginning. true diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/dimmer-thing.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/dimmer-thing.xml index a7ebf222281e9..7e107d9b01ccd 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/dimmer-thing.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/dimmer-thing.xml @@ -5,15 +5,15 @@ - - - + + + A single/multi-channel dimmer - - + + @@ -33,13 +33,17 @@ - Format is "value[, value, ...]". If less values than channels are defined, they are reused from the beginning. + Format is "value[, value, ...]". If less values than channels are defined, they are reused from the + beginning. + false true - Format is "value[, value, ...]". If less values than channels are defined, they are reused from the beginning. + Format is "value[, value, ...]". If less values than channels are defined, they are reused from the + beginning. + true diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/lib485-bridge.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/lib485-bridge.xml index dfd672becbadb..70fe9f7175395 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/lib485-bridge.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/lib485-bridge.xml @@ -1,5 +1,7 @@ - + @@ -19,7 +21,7 @@ List of channels that should use LED dim curve. Format is channel[,channel, ...] or channel[/width]. true - + DMX refresh rate in Hz (0=disable output) 30 true diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/sacn-bridge.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/sacn-bridge.xml index 634133cf29cf8..c594138c59f35 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/sacn-bridge.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/sacn-bridge.xml @@ -1,5 +1,7 @@ - + @@ -21,7 +23,8 @@ - Network addresses of sACN/E1.31 receivers, format: address[:port][, address[:port], ...]. Default port is 5568. + Network addresses of sACN/E1.31 receivers, format: address[:port][, address[:port], ...]. Default port + is 5568. false @@ -53,7 +56,7 @@ false true - + DMX refresh rate in Hz false 30 diff --git a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/tunablewhite-thing.xml b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/tunablewhite-thing.xml index d676c1cbe0d31..52076d7ecf8be 100644 --- a/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/tunablewhite-thing.xml +++ b/bundles/org.openhab.binding.dmx/src/main/resources/ESH-INF/thing/tunablewhite-thing.xml @@ -1,19 +1,21 @@ - + - - - + + + A tunable white capable dimmer - - - - + + + + @@ -33,13 +35,17 @@ - Format is "value[, value, ...]", has to be a multiple of two. If less values than channels are defined, they are reused from the beginning. + Format is "value[, value, ...]", has to be a multiple of two. If less values than channels are defined, + they are reused from the beginning. + false true - Format is "value[, value, ...]", has to be a multiple of two. If less values than channels are defined, they are reused from the beginning. + Format is "value[, value, ...]", has to be a multiple of two. If less values than channels are defined, + they are reused from the beginning. + true diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/UtilTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/UtilTest.java index 5de9678c250e9..992096da8ca3d 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/UtilTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/UtilTest.java @@ -17,7 +17,6 @@ import org.eclipse.smarthome.core.library.types.PercentType; import org.junit.Test; -import org.openhab.binding.dmx.internal.Util; import org.openhab.binding.dmx.internal.multiverse.DmxChannel; /** @@ -60,7 +59,6 @@ public void conversionFromPercentType() { // middle value = Util.toDmxValue(new PercentType(50)); assertThat(value, is(127)); - } @Test @@ -91,5 +89,4 @@ public void fadeTimeFraction() { value = Util.fadeTimeFraction(100, 155, 2550); assertThat(value, is(550)); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ArtnetBridgeHandlerTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ArtnetBridgeHandlerTest.java index 403347b1eac2a..e51b4d06ca106 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ArtnetBridgeHandlerTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ArtnetBridgeHandlerTest.java @@ -34,10 +34,9 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.openhab.binding.dmx.internal.handler.ArtnetBridgeHandler; /** - * Tests cases for {@link ArtnetBridgeHandler}. + * Tests cases for {@link org.openhab.binding.dmx.internal.handler.ArtnetBridgeHandler}. * * @author Jan N. Klug - Initial contribution */ @@ -102,5 +101,4 @@ public void renamingOfUniverses() { bridgeHandler.handleConfigurationUpdate(bridgeProperties); waitForAssert(() -> assertThat(bridgeHandler.getUniverseId(), is(TEST_UNIVERSE))); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ChaserThingHandlerTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ChaserThingHandlerTest.java index fc935469d057b..0b2485c2ae3bc 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ChaserThingHandlerTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ChaserThingHandlerTest.java @@ -36,12 +36,11 @@ import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; import org.junit.Before; import org.junit.Test; -import org.openhab.binding.dmx.internal.handler.ChaserThingHandler; import org.openhab.binding.dmx.test.AbstractDmxThingTestParent; import org.openhab.binding.dmx.test.TestBridgeHandler; /** - * Tests cases for {@link ChaserThingHandler}. + * Tests cases for {@link org.openhab.binding.dmx.internal.handler.ChaserThingHandler}. * * @author Jan N. Klug - Initial contribution */ @@ -183,7 +182,6 @@ private void initialize() { } }; initializeHandler(chaserThingHandler); - } private void initializeTestBridge() { diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ColorThingHandlerTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ColorThingHandlerTest.java index 022a52491684a..e98d636da3f7b 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ColorThingHandlerTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/ColorThingHandlerTest.java @@ -34,11 +34,10 @@ import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; import org.junit.Before; import org.junit.Test; -import org.openhab.binding.dmx.internal.handler.ColorThingHandler; import org.openhab.binding.dmx.test.AbstractDmxThingTestParent; /** - * Tests cases for {@link ColorThingHandler} in RGB mode. + * Tests cases for {@link org.openhab.binding.dmx.internal.handler.ColorThingHandler} in RGB mode. * * @author Jan N. Klug - Initial contribution */ @@ -216,5 +215,4 @@ public void testColorCommand() { state -> assertThat(((PercentType) state).doubleValue(), is(closeTo(29.8, 0.5)))); }); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/DimmerThingHandlerTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/DimmerThingHandlerTest.java index 1d9df89c78d12..ca6997ac106c6 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/DimmerThingHandlerTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/DimmerThingHandlerTest.java @@ -32,11 +32,11 @@ import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; import org.junit.Before; import org.junit.Test; -import org.openhab.binding.dmx.internal.handler.DimmerThingHandler; import org.openhab.binding.dmx.test.AbstractDmxThingTestParent; /** - * Tests cases for {@link DimmerThingHandler} in normal mode. + * Tests cases for {@link org.openhab.binding.dmx.internal.handler.DimmerThingHandler} in normal + * mode. * * @author Jan N. Klug - Initial contribution */ @@ -152,5 +152,4 @@ public void testDynamicTurnOnValue() { public void testPercentTypeCommand() { assertPercentTypeCommands(dimmerThingHandler, CHANNEL_UID_BRIGHTNESS, TEST_FADE_TIME); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/DmxBridgeHandlerTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/DmxBridgeHandlerTest.java index 307ac25127bfd..48bcef4b3be79 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/DmxBridgeHandlerTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/DmxBridgeHandlerTest.java @@ -79,7 +79,6 @@ public void initialize() { super.updateConfiguration(); updateStatus(ThingStatus.ONLINE); } - } private static final int TEST_UNIVERSE = 1; diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/Lib485BridgeHandlerTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/Lib485BridgeHandlerTest.java index 9adf10eafd556..3600c7f3651dc 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/Lib485BridgeHandlerTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/Lib485BridgeHandlerTest.java @@ -33,10 +33,9 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.openhab.binding.dmx.internal.handler.Lib485BridgeHandler; /** - * Tests cases for {@link Lib485BridgeHandler}. + * Tests cases for {@link org.openhab.binding.dmx.internal.handler.Lib485BridgeHandler}. * * @author Jan N. Klug - Initial contribution */ @@ -86,5 +85,4 @@ public void tearDown() { public void assertBridgeStatus() { waitForAssert(() -> assertEquals(ThingStatus.OFFLINE, bridge.getStatusInfo().getStatus())); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/SacnBridgeHandlerTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/SacnBridgeHandlerTest.java index 8d5c1bb0428ef..bfab88eb041d5 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/SacnBridgeHandlerTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/SacnBridgeHandlerTest.java @@ -34,10 +34,9 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.openhab.binding.dmx.internal.handler.SacnBridgeHandler; /** - * Tests cases for {@link SacnBridgeHandler}. + * Tests cases for {@link org.openhab.binding.dmx.internal.handler.SacnBridgeHandler}. * * @author Jan N. Klug - Initial contribution */ @@ -102,5 +101,4 @@ public void renamingOfUniverses() { bridgeHandler.handleConfigurationUpdate(bridgeProperties); waitForAssert(() -> assertThat(bridgeHandler.getUniverseId(), is(TEST_UNIVERSE))); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/TunableWhiteThingHandlerTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/TunableWhiteThingHandlerTest.java index 315c857caabda..4a36039be2a21 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/TunableWhiteThingHandlerTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/handler/TunableWhiteThingHandlerTest.java @@ -32,11 +32,10 @@ import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; import org.junit.Before; import org.junit.Test; -import org.openhab.binding.dmx.internal.handler.TunableWhiteThingHandler; import org.openhab.binding.dmx.test.AbstractDmxThingTestParent; /** - * Tests cases for {@link TunableWhiteThingHandler}. + * Tests cases for {@link org.openhab.binding.dmx.internal.handler.TunableWhiteThingHandler}. * * @author Jan N. Klug - Initial contribution */ @@ -227,5 +226,4 @@ public void testColorTemperature() { state -> assertThat(((PercentType) state).doubleValue(), is(closeTo(75.0, 0.5)))); }); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/multiverse/BaseChannelTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/multiverse/BaseChannelTest.java index f1e1e507374cf..6b0e022a776ca 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/multiverse/BaseChannelTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/multiverse/BaseChannelTest.java @@ -107,5 +107,4 @@ public void stringConversion() { assertThat(channelList.get(3).toString(), is(equalTo("2:102"))); assertThat(channelList.get(4).toString(), is(equalTo("2:426"))); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/multiverse/DmxChannelTest.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/multiverse/DmxChannelTest.java index 7d642e6420272..0f9e876ac3f74 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/multiverse/DmxChannelTest.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/internal/multiverse/DmxChannelTest.java @@ -23,7 +23,6 @@ import org.openhab.binding.dmx.internal.action.FadeAction; import org.openhab.binding.dmx.internal.action.ResumeAction; import org.openhab.binding.dmx.internal.handler.DimmerThingHandler; -import org.openhab.binding.dmx.internal.multiverse.DmxChannel; /** * Tests cases for Channel @@ -143,5 +142,4 @@ public void checkFadeActionWithResume() { assertThat(dmxChannel.hasRunningActions(), is(false)); Mockito.verify(dimmerThingHandler).updateChannelValue(valueChannelUID, 127); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/test/AbstractDmxThingTestParent.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/test/AbstractDmxThingTestParent.java index a46274a72cff6..4365078c2a7a7 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/test/AbstractDmxThingTestParent.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/test/AbstractDmxThingTestParent.java @@ -142,5 +142,4 @@ protected void assertChannelStateUpdate(ChannelUID channelUID, Consumer s State value = captor.getValue(); stateAssertion.accept(value); } - } diff --git a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/test/TestBridgeHandler.java b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/test/TestBridgeHandler.java index 8f1551bd0a4f0..3cdaea7901282 100644 --- a/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/test/TestBridgeHandler.java +++ b/bundles/org.openhab.binding.dmx/src/test/java/org/openhab/binding/dmx/test/TestBridgeHandler.java @@ -47,17 +47,14 @@ public TestBridgeHandler(Bridge testBridge) { @Override protected void openConnection() { - } @Override protected void closeConnection() { - } @Override protected void sendDmxData() { - } @Override diff --git a/bundles/org.openhab.binding.doorbird/pom.xml b/bundles/org.openhab.binding.doorbird/pom.xml index 9dac96ee4e1ef..a54e49ebf914a 100644 --- a/bundles/org.openhab.binding.doorbird/pom.xml +++ b/bundles/org.openhab.binding.doorbird/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.doorbird diff --git a/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/binding/binding.xml index 50c9a9d2f3520..b84a9227ecef6 100644 --- a/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Doorbird Binding This is the binding for Doorbird video doorbells. diff --git a/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/config/config.xml index 7de9aba283413..6e3fb64f708a3 100644 --- a/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/thing/thing-types.xml index 48818a1f8cf84..b5be96be05967 100644 --- a/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.doorbird/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -11,25 +12,25 @@ Trigger for doorbell press - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + @@ -40,37 +41,37 @@ Trigger for doorbell press - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + Doorbird model A1081 Controller - - - + + + - + diff --git a/bundles/org.openhab.binding.dscalarm/README.md b/bundles/org.openhab.binding.dscalarm/README.md index 45200886870ff..8cbc1eb69d036 100644 --- a/bundles/org.openhab.binding.dscalarm/README.md +++ b/bundles/org.openhab.binding.dscalarm/README.md @@ -27,11 +27,10 @@ Most settings are through thing configuration parameters. ## Discovery -The DSC Alarm binding incorporates several discovery modes in order to find DSC Alarm systems. -First, there is the Envisalink bridge discovery mode which performs a network query for any Envisalink adapters and adds them to the discovery inbox. -Second, there is The IT-100 bridge discovery mode which will search serial ports for any IT-100 adapters and add them to the discovery inbox. -The bridge discovery modes are started manually through Paper UI. -Third, after a bridge is discovered and available to openHAB, the binding will attempt to discover DSC Alarm things and add them to the discovery inbox. +The DSC Alarm binding incorporates a discovery modes in order to find DSC Alarm systems. +There is the Envisalink bridge discovery mode which performs a network query for any Envisalink adapters and adds them to the discovery inbox. +This bridge discovery mode is started manually through Paper UI. +After a bridge is discovered and available to openHAB, the binding will attempt to discover DSC Alarm things and add them to the discovery inbox. The TCP Server bridge does not implement bridge discovery but will utilize thing discovery once it is online. Note: diff --git a/bundles/org.openhab.binding.dscalarm/pom.xml b/bundles/org.openhab.binding.dscalarm/pom.xml index 116cec54b6702..6ac7ebd7e2ab0 100644 --- a/bundles/org.openhab.binding.dscalarm/pom.xml +++ b/bundles/org.openhab.binding.dscalarm/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.dscalarm diff --git a/bundles/org.openhab.binding.dscalarm/src/main/feature/feature.xml b/bundles/org.openhab.binding.dscalarm/src/main/feature/feature.xml index 9cc7883e0784a..f6ef496fe7b7f 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.dscalarm/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.dscalarm/${project.version} + diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/DSCAlarmBindingConstants.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/DSCAlarmBindingConstants.java index 6dcaf1c397c18..c61b134ac18e3 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/DSCAlarmBindingConstants.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/DSCAlarmBindingConstants.java @@ -119,5 +119,4 @@ public class DSCAlarmBindingConstants { public static final Set SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections .unmodifiableSet(Stream.of(ENVISALINKBRIDGE_THING_TYPE, IT100BRIDGE_THING_TYPE, TCPSERVERBRIDGE_THING_TYPE) .collect(Collectors.toSet())); - } diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/DSCAlarmEvent.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/DSCAlarmEvent.java index 0c52a8404bd38..de0838047092e 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/DSCAlarmEvent.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/DSCAlarmEvent.java @@ -50,5 +50,4 @@ public void dscAlarmEventMessage(DSCAlarmMessage dscAlarmMessage) { public DSCAlarmMessage getDSCAlarmMessage() { return dscAlarmMessage; } - } diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/config/TCPServerBridgeConfiguration.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/config/TCPServerBridgeConfiguration.java index d31264410077a..281c7365fe186 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/config/TCPServerBridgeConfiguration.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/config/TCPServerBridgeConfiguration.java @@ -52,5 +52,4 @@ public class TCPServerBridgeConfiguration { * The Protocol Type - 1 for IT-100 API or 2 for Envisalink TPI. */ public Integer protocol; - } diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/DSCAlarmBridgeDiscovery.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/DSCAlarmBridgeDiscovery.java index d0923b7d6feaf..24b2911cfa6db 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/DSCAlarmBridgeDiscovery.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/DSCAlarmBridgeDiscovery.java @@ -21,7 +21,6 @@ import org.eclipse.smarthome.core.thing.ThingUID; import org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants; import org.openhab.binding.dscalarm.internal.config.EnvisalinkBridgeConfiguration; -import org.openhab.binding.dscalarm.internal.config.IT100BridgeConfiguration; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,11 +36,7 @@ public class DSCAlarmBridgeDiscovery extends AbstractDiscoveryService { private final Logger logger = LoggerFactory.getLogger(DSCAlarmBridgeDiscovery.class); private EnvisalinkBridgeDiscovery envisalinkBridgeDiscovery = new EnvisalinkBridgeDiscovery(this); - private IT100BridgeDiscovery it100BridgeDiscovery = new IT100BridgeDiscovery(this); - /** - * Constructor. - */ public DSCAlarmBridgeDiscovery() { super(DSCAlarmBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS, 15, true); } @@ -50,17 +45,12 @@ public DSCAlarmBridgeDiscovery() { protected void startScan() { logger.trace("Start DSC Alarm Bridge discovery."); scheduler.execute(envisalinkBridgeDiscoveryRunnable); - scheduler.execute(it100BridgeDiscoveryRunnable); } private Runnable envisalinkBridgeDiscoveryRunnable = () -> { envisalinkBridgeDiscovery.discoverBridge(); }; - private Runnable it100BridgeDiscoveryRunnable = () -> { - it100BridgeDiscovery.discoverBridge(); - }; - /** * Method to add an Envisalink Bridge to the Smarthome Inbox. * @@ -84,40 +74,4 @@ public void addEnvisalinkBridge(String ipAddress) { logger.error("addBridge(): Error", e); } } - - /** - * Method to add an IT-100 Bridge to the Smarthome Inbox. - * - * @param port - */ - public void addIT100Bridge(String port) { - logger.trace("addBridge(): Adding new IT-100 Bridge on {} to Smarthome inbox", port); - - String bridgeID = ""; - boolean containsChar = port.contains("/"); - - if (containsChar) { - String[] parts = port.split("/"); - String id = parts[parts.length - 1].toUpperCase(); - bridgeID = id.replaceAll("\\W", "_"); - - } else { - String id = port.toUpperCase(); - bridgeID = id.replaceAll("\\W", "_"); - } - - Map properties = new HashMap<>(0); - properties.put(IT100BridgeConfiguration.SERIAL_PORT, port); - - try { - ThingUID thingUID = new ThingUID(DSCAlarmBindingConstants.IT100BRIDGE_THING_TYPE, bridgeID); - - thingDiscovered(DiscoveryResultBuilder.create(thingUID).withProperties(properties) - .withLabel("DSC IT-100 Bridge - " + port).build()); - - logger.trace("addBridge(): '{}' was added to Smarthome inbox.", thingUID); - } catch (Exception e) { - logger.error("addBridge(): Error", e); - } - } } diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/DSCAlarmDiscoveryService.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/DSCAlarmDiscoveryService.java index 7fc80005f90f9..77a1bf674a5fd 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/DSCAlarmDiscoveryService.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/DSCAlarmDiscoveryService.java @@ -136,7 +136,6 @@ public void addThing(Bridge bridge, DSCAlarmThingType dscAlarmThingType, DSCAlar } else { logger.debug("addThing(): Unable to Add DSC Alarm Thing to Inbox!"); } - } @Override diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/IT100BridgeDiscovery.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/IT100BridgeDiscovery.java deleted file mode 100644 index 93aea7aa3d360..0000000000000 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/discovery/IT100BridgeDiscovery.java +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dscalarm.internal.discovery; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.util.Enumeration; - -import org.apache.commons.io.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import gnu.io.CommPort; -import gnu.io.CommPortIdentifier; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.UnsupportedCommOperationException; - -/** - * This class is responsible for discovering the DSC IT100 RS232 Serial interface. - * - * @author Russell Stephens - Initial Contribution - * - */ -public class IT100BridgeDiscovery { - private final Logger logger = LoggerFactory.getLogger(IT100BridgeDiscovery.class); - - static final int BAUD_RATE = 9600; - static final int RECEIVE_TIMEOUT = 15000; - static final String IT100_SEND_STRING = "00090\r\n"; - static final String IT100_DISCOVERY_RESPONSE = "500"; - - private DSCAlarmBridgeDiscovery dscAlarmBridgeDiscovery = null; - - /** - * Constructor. - */ - public IT100BridgeDiscovery(DSCAlarmBridgeDiscovery dscAlarmBridgeDiscovery) { - this.dscAlarmBridgeDiscovery = dscAlarmBridgeDiscovery; - } - - /** - * Method for Bridge Discovery. - */ - public synchronized void discoverBridge() { - logger.debug("Starting IT-100 Bridge Discovery."); - - Enumeration ports = CommPortIdentifier.getPortIdentifiers(); - - while (ports.hasMoreElements()) { - CommPortIdentifier portIdentifier = (CommPortIdentifier) ports.nextElement(); - - if (portIdentifier.getPortType() == CommPortIdentifier.PORT_SERIAL) { - SerialPort serialPort = null; - OutputStreamWriter serialOutput = null; - BufferedReader serialInput = null; - - try { - CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000); - serialPort = (SerialPort) commPort; - serialPort.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, - SerialPort.PARITY_NONE); - serialPort.enableReceiveThreshold(1); - - serialOutput = new OutputStreamWriter(serialPort.getOutputStream(), "US-ASCII"); - serialInput = new BufferedReader(new InputStreamReader(serialPort.getInputStream())); - - serialPort.enableReceiveTimeout(RECEIVE_TIMEOUT); - String message = ""; - - serialOutput.write(IT100_SEND_STRING); - serialOutput.flush(); - - try { - message = serialInput.readLine(); - } catch (IOException e) { - logger.debug("discoverBridge(): No Message Read from Serial Port '{}'", - portIdentifier.getName()); - continue; - } - - if (message.substring(0, 3).equals(IT100_DISCOVERY_RESPONSE)) { - logger.debug("discoverBridge(): Serial Port '{}' Found!", portIdentifier.getName()); - dscAlarmBridgeDiscovery.addIT100Bridge(portIdentifier.getName()); - } else { - logger.debug("discoverBridge(): Incorrect Response from Serial Port! '{}' - {}", - portIdentifier.getName(), message); - } - - } catch (UnsupportedCommOperationException e) { - logger.debug("discoverBridge(): Unsupported Comm Operation Exception - '{}': {}", - portIdentifier.getName(), e.getMessage()); - } catch (PortInUseException e) { - logger.debug("discoverBridge(): Port in Use Exception - '{}': {}", portIdentifier.getName(), - e.getMessage()); - } catch (UnsupportedEncodingException e) { - logger.debug("discoverBridge(): Unsupported Encoding Exception - '{}': {}", - portIdentifier.getName(), e.getMessage()); - } catch (IOException e) { - logger.debug("discoverBridge(): IO Exception - '{}': {}", portIdentifier.getName(), e.getMessage()); - } finally { - if (serialInput != null) { - IOUtils.closeQuietly(serialInput); - serialInput = null; - } - - if (serialOutput != null) { - IOUtils.closeQuietly(serialOutput); - serialOutput = null; - } - - if (serialPort != null) { - serialPort.close(); - serialPort = null; - } - } - } - } - } -} diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/factory/DSCAlarmHandlerFactory.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/factory/DSCAlarmHandlerFactory.java index a998fa242da04..48a0caa84d623 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/factory/DSCAlarmHandlerFactory.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/factory/DSCAlarmHandlerFactory.java @@ -27,6 +27,7 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.dscalarm.internal.DSCAlarmBindingConstants; import org.openhab.binding.dscalarm.internal.config.DSCAlarmPartitionConfiguration; import org.openhab.binding.dscalarm.internal.config.DSCAlarmZoneConfiguration; @@ -43,7 +44,9 @@ import org.openhab.binding.dscalarm.internal.handler.TCPServerBridgeHandler; import org.openhab.binding.dscalarm.internal.handler.ZoneThingHandler; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,6 +61,13 @@ public class DSCAlarmHandlerFactory extends BaseThingHandlerFactory { private final Logger logger = LoggerFactory.getLogger(DSCAlarmHandlerFactory.class); private final Map> discoveryServiceRegistrations = new HashMap<>(); + private final SerialPortManager serialPortManager; + + @Activate + public DSCAlarmHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID, ThingUID bridgeUID) { @@ -261,7 +271,7 @@ protected ThingHandler createHandler(Thing thing) { logger.debug("createHandler(): ENVISALINKBRIDGE_THING: ThingHandler created for {}", thingTypeUID); return handler; } else if (thingTypeUID.equals(DSCAlarmBindingConstants.IT100BRIDGE_THING_TYPE)) { - IT100BridgeHandler handler = new IT100BridgeHandler((Bridge) thing); + IT100BridgeHandler handler = new IT100BridgeHandler((Bridge) thing, serialPortManager); registerDSCAlarmDiscoveryService(handler); logger.debug("createHandler(): IT100BRIDGE_THING: ThingHandler created for {}", thingTypeUID); return handler; @@ -304,5 +314,4 @@ protected void removeHandler(ThingHandler thingHandler) { super.removeHandler(thingHandler); } - } diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmBaseBridgeHandler.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmBaseBridgeHandler.java index 86595de1db84d..de4f6e87a8c86 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmBaseBridgeHandler.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmBaseBridgeHandler.java @@ -371,7 +371,6 @@ public void checkThings() { logger.error("checkThings(): Thing handler not found!"); } } - } /** diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmBaseThingHandler.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmBaseThingHandler.java index ec1523d27bdfe..6e061188cbb1b 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmBaseThingHandler.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmBaseThingHandler.java @@ -379,5 +379,4 @@ && getSuppressAcknowledgementMsgs()) { logger.debug("setPanelMessage(): Panel Message Set to - {}", message); } } - } diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmThingType.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmThingType.java index 67721a25669a4..c4351df926536 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmThingType.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/DSCAlarmThingType.java @@ -73,5 +73,4 @@ public static DSCAlarmThingType getDSCAlarmThingType(String label) { } return labelToDSCAlarmThingType.get(label); } - } diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/EnvisalinkBridgeHandler.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/EnvisalinkBridgeHandler.java index 0b9cba93fa169..e51dc13c8b6ee 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/EnvisalinkBridgeHandler.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/EnvisalinkBridgeHandler.java @@ -165,18 +165,9 @@ public void closeConnection() { logger.debug("closeConnection(): Closing Socket!"); tcpSocket.close(); tcpSocket = null; - } - if (tcpInput != null) { - logger.debug("closeConnection(): Closing Output Writer!"); - tcpInput.close(); tcpInput = null; - } - if (tcpOutput != null) { - logger.debug("closeConnection(): Closing Input Reader!"); - tcpOutput.close(); tcpOutput = null; } - setConnected(false); logger.debug("closeConnection(): Closed TCP Connection!"); } catch (IOException ioException) { diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/IT100BridgeHandler.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/IT100BridgeHandler.java index a0142f483cc24..d8d6ff04c74fe 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/IT100BridgeHandler.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/IT100BridgeHandler.java @@ -19,22 +19,19 @@ import java.io.UnsupportedEncodingException; import java.util.TooManyListenersException; -import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.dscalarm.internal.config.IT100BridgeConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPort; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * The bridge handler for the DSC IT100 RS232 Serial interface. * @@ -44,15 +41,7 @@ public class IT100BridgeHandler extends DSCAlarmBaseBridgeHandler implements SerialPortEventListener { private final Logger logger = LoggerFactory.getLogger(IT100BridgeHandler.class); - - /** - * Constructor. - * - * @param bridge - */ - public IT100BridgeHandler(Bridge bridge) { - super(bridge, DSCAlarmBridgeType.IT100, DSCAlarmProtocol.IT100_API); - } + private final SerialPortManager serialPortManager; private String serialPortName = ""; private int baudRate; @@ -60,6 +49,11 @@ public IT100BridgeHandler(Bridge bridge) { private OutputStreamWriter serialOutput = null; private BufferedReader serialInput = null; + public IT100BridgeHandler(Bridge bridge, SerialPortManager serialPortManager) { + super(bridge, DSCAlarmBridgeType.IT100, DSCAlarmProtocol.IT100_API); + this.serialPortManager = serialPortManager; + } + @Override public void initialize() { logger.debug("Initializing the DSC IT100 Bridge handler."); @@ -98,13 +92,19 @@ public void dispose() { @Override public void openConnection() { - try { - logger.debug("openConnection(): Connecting to IT-100 "); + logger.debug("openConnection(): Connecting to IT-100"); - CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName); - CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000); + SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(serialPortName); + if (portIdentifier == null) { + logger.error("openConnection(): No Such Port: {}", serialPort); + setConnected(false); + return; + } + + try { + SerialPort commPort = portIdentifier.open(this.getClass().getName(), 2000); - serialPort = (SerialPort) commPort; + serialPort = commPort; serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); serialPort.enableReceiveThreshold(1); @@ -116,10 +116,6 @@ public void openConnection() { setSerialEventHandler(this); setConnected(true); - - } catch (NoSuchPortException noSuchPortException) { - logger.error("openConnection(): No Such Port Exception: {}", noSuchPortException.getMessage()); - setConnected(false); } catch (PortInUseException portInUseException) { logger.error("openConnection(): Port in Use Exception: {}", portInUseException.getMessage()); setConnected(false); @@ -168,7 +164,6 @@ public String read() { } return message; - } /** @@ -193,12 +188,20 @@ public void closeConnection() { serialPort.removeEventListener(); if (serialInput != null) { - IOUtils.closeQuietly(serialInput); + try { + serialInput.close(); + } catch (IOException e) { + logger.debug("Error while closing the input stream: {}", e.getMessage()); + } serialInput = null; } if (serialOutput != null) { - IOUtils.closeQuietly(serialOutput); + try { + serialOutput.close(); + } catch (IOException e) { + logger.debug("Error while closing the output stream: {}", e.getMessage()); + } serialOutput = null; } diff --git a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/TCPServerBridgeHandler.java b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/TCPServerBridgeHandler.java index f84a6a09ba48a..a6d71e6f441ed 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/TCPServerBridgeHandler.java +++ b/bundles/org.openhab.binding.dscalarm/src/main/java/org/openhab/binding/dscalarm/internal/handler/TCPServerBridgeHandler.java @@ -172,16 +172,9 @@ public void closeConnection() { if (tcpSocket != null) { tcpSocket.close(); tcpSocket = null; - } - if (tcpInput != null) { - tcpInput.close(); tcpInput = null; - } - if (tcpOutput != null) { - tcpOutput.close(); tcpOutput = null; } - setConnected(false); logger.debug("closeConnection(): Closed TCP Connection!"); } catch (IOException ioException) { diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/binding/binding.xml index 4c41eec4300d3..a188fe1f50efe 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/binding/binding.xml @@ -1,10 +1,11 @@ - DSCAlarm Binding - The DSCAlarm binding interfaces with a DSC PowerSeries Alarm System through the EyezOn Envisalink 3/2DS interface or the DSC IT-100 RS-232 interface. + The DSCAlarm binding interfaces with a DSC PowerSeries Alarm System through the EyezOn Envisalink 3/2DS + interface or the DSC IT-100 RS-232 interface. Russell Stephens diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/channels.xml index 21aa1b35f81d7..bfe9da7112a70 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/channels.xml @@ -1,6 +1,8 @@ - + diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/envisalinkbridge.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/envisalinkbridge.xml index d592210b09d3e..909bef60c3aa9 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/envisalinkbridge.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/envisalinkbridge.xml @@ -1,6 +1,8 @@ - + diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/it100bridge.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/it100bridge.xml index d2c150383ea57..2d2513c1e3fcc 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/it100bridge.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/it100bridge.xml @@ -1,6 +1,8 @@ - + @@ -20,6 +22,7 @@ serial-port + false The serial port name for the DSC IT-100. Valid values are e.g. COM1 for Windows and /dev/ttyS0 or diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/keypad.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/keypad.xml index 2b7b72268c8fc..2f9f4a78a90c5 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/keypad.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/keypad.xml @@ -1,13 +1,14 @@ - - - - + + + diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/panel.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/panel.xml index d383971ca0ee7..0a5a12ec38b48 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/panel.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/panel.xml @@ -1,13 +1,14 @@ - - - - + + + diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/partition.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/partition.xml index 482b6cc2a0bdc..9ea265dc22881 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/partition.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/partition.xml @@ -1,13 +1,14 @@ - - - - + + + @@ -40,7 +41,8 @@ - Partition Opening/Closing Mode ("User Closing", "Special Closing", "Partial Closing", "User Opening", "Special Opening") + Partition Opening/Closing Mode ("User Closing", "Special Closing", "Partial Closing", "User Opening", + "Special Opening") diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/tcpserverbridge.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/tcpserverbridge.xml index 78c13d939a4f7..1dd5a75876ec2 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/tcpserverbridge.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/tcpserverbridge.xml @@ -1,6 +1,8 @@ - + diff --git a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/zone.xml b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/zone.xml index b12fa49bb099e..21814b2227d91 100644 --- a/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/zone.xml +++ b/bundles/org.openhab.binding.dscalarm/src/main/resources/ESH-INF/thing/zone.xml @@ -1,13 +1,14 @@ - - - - + + + diff --git a/bundles/org.openhab.binding.dsmr/pom.xml b/bundles/org.openhab.binding.dsmr/pom.xml index 8535991afc049..0c398076eaa8f 100644 --- a/bundles/org.openhab.binding.dsmr/pom.xml +++ b/bundles/org.openhab.binding.dsmr/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.dsmr diff --git a/bundles/org.openhab.binding.dsmr/src/main/feature/feature.xml b/bundles/org.openhab.binding.dsmr/src/main/feature/feature.xml index f848335f9d1ec..87ea8207b734f 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.dsmr/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.dsmr/${project.version} + diff --git a/bundles/org.openhab.binding.dsmr/src/main/java/org/openhab/binding/dsmr/internal/device/DSMRSerialAutoDevice.java b/bundles/org.openhab.binding.dsmr/src/main/java/org/openhab/binding/dsmr/internal/device/DSMRSerialAutoDevice.java index e8b4b4811a1a8..d0537833762cc 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/java/org/openhab/binding/dsmr/internal/device/DSMRSerialAutoDevice.java +++ b/bundles/org.openhab.binding.dsmr/src/main/java/org/openhab/binding/dsmr/internal/device/DSMRSerialAutoDevice.java @@ -279,5 +279,4 @@ private void restartHalfTimer() { } halfTimeTimer = scheduler.schedule(this::switchBaudrate, baudrateSwitchTimeoutSeconds, TimeUnit.SECONDS); } - } diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/config/configuration_parameters.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/config/configuration_parameters.xml index 87a6b1cc9aee4..8b07743197eb5 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/config/configuration_parameters.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/config/configuration_parameters.xml @@ -7,8 +7,10 @@ serial-port + false - The serial port where the P1 port of the Smart Meter is connected (e.g. Linux: /dev/ttyUSB0, Windows: COM1) + The serial port where the P1 port of the Smart Meter is connected (e.g. Linux: /dev/ttyUSB0, Windows: + COM1) 30 @@ -64,12 +66,15 @@ serial-port + false - The serial port where the P1 port of the Smart Meter is connected (e.g. Linux: /dev/ttyUSB0, Windows: COM1) + The serial port where the P1 port of the Smart Meter is connected (e.g. Linux: /dev/ttyUSB0, Windows: + COM1) - The Luxembourgian Smart meter decryption key. Ask for your energy grid operator for your Smart meter P1 key. + The Luxembourgian Smart meter decryption key. Ask for your energy grid operator for your Smart meter P1 + key. 30 @@ -87,7 +92,7 @@ true - diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/channeltypes_electricity.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/channeltypes_electricity.xml index 4d5fa02c0647e..bd34f7f647f2d 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/channeltypes_electricity.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/channeltypes_electricity.xml @@ -7,350 +7,352 @@ Number:Energy The total amount of electricity used. - + Number:Energy The total amount of electricity used for tariff 0. - + Number:Energy The total amount of electricity used for tariff 1. - + Number:Energy The total amount of electricity used for tariff 2. - + Number:Energy The total amount of electricity used for tariff 1. - + Number:Energy The total amount of electricity used for tariff 2. - + Number:Energy The total amount of electricity used for tariff 0 (anti fraud). - + Number The total amount of electricity used for tariff 1 (anti fraud). - + Number:Energy The total amount of electricity used for tariff 2 (anti fraud). - + Number:Energy The total amount of electricity produced for tariff 0. - + Number:Energy The total amount of electricity produced for tariff 1. - + Number:Energy The total amount of electricity produced for tariff 2. - + Number:Energy The total amount of electricity produced for tariff 1. - + Number:Energy The total amount of electricity produced for tariff 2. - + Number:Energy The Total imported energy register (P+). - + Number:Energy The Total exported energy register (P-). - + Number:Energy The Total imported energy register (Q+). - + Number:Energy The Total exported energy register (Q-). - + String The current tariff indicator. - + Number:Power The aggregate active import power. - + Number:Power The current power delivery. - + Number:Power The current power production. - + Number The current reactive power delivery. - + Number The current reactive power production. - + Number:ElectricCurrent The actual threshold. - + Number:ElectricCurrent The actual fuse threshold. - + Number:Power The actual threshold. - + Number Active threshold (SMAX). - + Number The switch position. - + Number The number of power failures. - + Number The number of long power failures. - + Number Number of log entries. - + DateTime Timestamp when the power failure ended. There can be multiple log entries. - Each entry has its own channel (emeter_power_failure_log_timestamp*x*, *x* = 0 - 9) - + Each entry has its own channel + (emeter_power_failure_log_timestamp*x*, *x* = 0 - 9) + Number:Time Duration of the power failure. - Each entry has its own channel (emeter_power_failure_log_duration*x*, *x* = 0 - 9) - + Each entry has its own channel (emeter_power_failure_log_duration*x*, *x* = + 0 - 9) + Number The number of voltage sags L1. - + Number The number of voltage sags L2. - + Number The number of voltage sags L3. - + Number The number of voltage swells L1. - + Number The number of voltage swells L2. - + Number The number of voltage swells L3. - + Number:ElectricCurrent The instant current L1. - + Number:ElectricCurrent The instant current L2. - + Number:ElectricCurrent The instant current L3. - + Number:Power The instant power delivery L1. - + Number:Power The instant power delivery L2. - + Number The instant power delivery L3. - + Number:Power The instant power production L1. - + Number:Power The instant power production L2. - + Number:Power The instant power production L3. - + Number:Power The instant reactive power delivery L1. - + Number:Power The instant reactive power delivery L2. - + Number:Power The instant reactive power delivery L3. - + Number:Power The instant reactive power production L1. - + Number:Power The instant reactive power production L2. - + Number:Power The instant reactive power production L3. - + Number:ElectricPotential The instant voltage L1. - + Number:ElectricPotential The instant voltage L2. - + Number:ElectricPotential The instant voltage L3. - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/dsmr_device.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/dsmr_device.xml index 1c93d46e5eb5e..6c3311432be4e 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/dsmr_device.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/dsmr_device.xml @@ -8,7 +8,7 @@ The Dutch/Belgium Smart Meter (DSMR/e-MUCS) - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_cooling_ace4000.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_cooling_ace4000.xml index bb765a748a847..22058bbed9c79 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_cooling_ace4000.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_cooling_ace4000.xml @@ -6,14 +6,14 @@ - + This is a cooling meter that complies to the ACE4000 GTMM Mk3 specification. - + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_cooling_v2_2.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_cooling_v2_2.xml index 194cff6e9b940..867c13e403e05 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_cooling_v2_2.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_cooling_v2_2.xml @@ -6,17 +6,17 @@ - + This is a cooling meter that complies to the DSMR V2.2 specification. - - - + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v2_v3.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v2_v3.xml index d3b3059545700..d2ba3b2c83619 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v2_v3.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v2_v3.xml @@ -6,16 +6,16 @@ - + This is the device meter that complies to the DSMR V2.x or V3 specification. - - + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v4.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v4.xml index 1e951864d4937..83767a9183ee9 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v4.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v4.xml @@ -6,18 +6,18 @@ - - + + This is the device meter that complies to the DSMR V4 specification. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v5.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v5.xml index e519d51c8fde9..582dd6d8f4fd5 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v5.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_dsmr_v5.xml @@ -6,18 +6,18 @@ - - + + This is the device meter that complies to the DSMR V5 specification. - - - + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_emucs_v1_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_emucs_v1_0.xml index b90cb7187dbac..513479e788c2a 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_emucs_v1_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_device_emucs_v1_0.xml @@ -6,17 +6,17 @@ - + This is the device meter that complies to the e-MUCS 1.0 specification. - - - + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_ace4000.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_ace4000.xml index fd622d40a390e..dfac6e95a46c6 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_ace4000.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_ace4000.xml @@ -6,28 +6,28 @@ - + This is an electricity meter that complies to the ACE4000 GTMM Mk3 specification. - - - - - - - - - - - - - - + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v2_1.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v2_1.xml index 4f4eb0909526e..9eaec9dbe4404 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v2_1.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v2_1.xml @@ -6,23 +6,23 @@ - + This is an electricity meter that complies to the DSMR V2.1 specification. - - - - - - - - - + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v2_2.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v2_2.xml index 705c73e50b399..39685dafac5ff 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v2_2.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v2_2.xml @@ -6,23 +6,23 @@ - + This is an electricity meter that complies to the DSMR V2.2 specification. - - - - - - - - - + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v3.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v3.xml index c9c7aad24153e..9a41be73449d3 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v3.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v3.xml @@ -6,24 +6,24 @@ - + This is an electricity meter that complies to the DSMR V3 specification. - - - - - - - - - - + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4.xml index e4b8c6bf46e8d..a5b60f804b923 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4.xml @@ -6,53 +6,53 @@ - + This is an electricity meter that complies to the DSMR V4.0 specification. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4_0_4.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4_0_4.xml index 33c59678f9dd5..a66b2d1f2a01c 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4_0_4.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4_0_4.xml @@ -6,63 +6,63 @@ - + This is an electricity meter that complies to the DSMR V4.0.4 specification. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4_2.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4_2.xml index 0867538debf40..0307c7603c5e9 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4_2.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v4_2.xml @@ -6,61 +6,61 @@ - + This is an electricity meter that complies to the DSMR V4.2 specification. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v5.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v5.xml index 4591d58d25a6f..03f286215cf4d 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v5.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_dsmr_v5.xml @@ -6,63 +6,63 @@ - + This is an electricity meter that complies to the DSMR V5.0 specification. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_emucs_v1_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_emucs_v1_0.xml index 4de6e995d56c1..33f70144a7309 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_emucs_v1_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_emucs_v1_0.xml @@ -6,31 +6,31 @@ - + This is an electricity meter that complies to the e-MUCS V1.0 specification. - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave1_ace4000.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave1_ace4000.xml index 0ecdbf5a72a7a..d16d564697cc9 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave1_ace4000.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave1_ace4000.xml @@ -6,24 +6,24 @@ - + This is the first slave electricity meter that complies to the ACE4000 GTMM Mk3 specification. - - - - - - - - - - + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave2_ace4000.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave2_ace4000.xml index 1770bd83d098b..340b9802a16bb 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave2_ace4000.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave2_ace4000.xml @@ -6,24 +6,24 @@ - + This is the second slave electricity meter that complies to the ACE4000 GTMM Mk3 specification. - - - - - - - - - - + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave_v4.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave_v4.xml index 5ab826fa635e2..4b7bf463eb53f 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave_v4.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave_v4.xml @@ -6,19 +6,19 @@ - + This is the slave electricity meter that complies to the DSMR 4.x specification. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave_v5.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave_v5.xml index 6b7b05a0113ed..913ef482cd422 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave_v5.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_slave_v5.xml @@ -6,18 +6,18 @@ - + This is the slave electricity meter that complies to the DSMR 5.x specification. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_smarty_v1.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_smarty_v1.xml index cfa7e5c09c221..44bc4d830b528 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_smarty_v1.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_electricity_smarty_v1.xml @@ -6,67 +6,67 @@ - + This is an electricity meter that complies to the Luxembourg's Smarty V1.0 specification. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_ace4000.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_ace4000.xml index 193daf35cbcdc..5ffcf1f1646a9 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_ace4000.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_ace4000.xml @@ -6,18 +6,18 @@ - + This is a gas meter that complies to the ACE4000 GTMM Mk3 specification. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v2_1.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v2_1.xml index 199d397e1d367..c5e37f8193b18 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v2_1.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v2_1.xml @@ -6,20 +6,20 @@ - + This is a gas meter that complies to the DSMR V2.1 specification. - - - - - - + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v2_2.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v2_2.xml index 44975edfafeda..baa231632f0da 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v2_2.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v2_2.xml @@ -6,20 +6,20 @@ - + This is a gas meter that complies to the DSMR V2.2 specification. - - - - - - + + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v3_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v3_0.xml index 573ca1e4615be..b87ede5dad312 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v3_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gas_v3_0.xml @@ -6,19 +6,19 @@ - + This is a gas meter that complies to the DSMR V3.0 specification. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gasmeter_emucs_v1_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gasmeter_emucs_v1_0.xml index cc7feb33bfb70..5305125ca072e 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gasmeter_emucs_v1_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gasmeter_emucs_v1_0.xml @@ -6,19 +6,19 @@ - + This is a gas meter that complies to the e-MUCS V1.0 specification. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_generic_v3_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_generic_v3_0.xml index 2d6b2e277c30d..fa1a10d1ee790 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_generic_v3_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_generic_v3_0.xml @@ -6,18 +6,18 @@ - + This is a generic meter that complies to the DSMR V3.0 specification. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v3_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v3_0.xml index b04f8ad7969de..99cb90272e1b1 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v3_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v3_0.xml @@ -6,18 +6,18 @@ - + This is a Giga Joule meter that complies to the DSMR V3.0 specification. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v4.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v4.xml index 8e9ede8ab28d6..ea823c16a73f5 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v4.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v4.xml @@ -6,19 +6,19 @@ - + This is a Giga Joule meter that complies to the DSMR V4.x specification. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v5_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v5_0.xml index bc3f3b753cabc..abf843c397772 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v5_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_gj_v5_0.xml @@ -6,18 +6,18 @@ - + This is a Giga Joule meter that complies to the DSMR V5.0 specification. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_heating_ace4000.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_heating_ace4000.xml index 581f9b43ae697..1e5deb9b3ab15 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_heating_ace4000.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_heating_ace4000.xml @@ -6,16 +6,16 @@ - + This is a heating meter that complies to the ACE4000 GTMM Mk3 specification. - - + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_heating_v2_2.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_heating_v2_2.xml index e4e7cddd67215..082d67fa11a8d 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_heating_v2_2.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_heating_v2_2.xml @@ -6,17 +6,17 @@ - + This is a heating meter that complies to the DSMR V2.2 specification. - - - + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_m3_v4.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_m3_v4.xml index fac084be87501..1187630427fce 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_m3_v4.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_m3_v4.xml @@ -6,19 +6,19 @@ - + This is a m3 meter that complies to the DSMR V4.x specification. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_m3_v5_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_m3_v5_0.xml index 1cb83bf791b7e..c22b037651c6d 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_m3_v5_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_m3_v5_0.xml @@ -6,18 +6,18 @@ - + This is a m3 meter that complies to the DSMR V5.0 specification. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_ace4000.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_ace4000.xml index 7c6dd14f7987c..342226f74e82f 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_ace4000.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_ace4000.xml @@ -6,16 +6,16 @@ - + This is a water meter that complies to the ACE4000 GTMM Mk3 specification. - - + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_v2_2.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_v2_2.xml index 9afc6e199ec08..f64acbfc24bfd 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_v2_2.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_v2_2.xml @@ -6,17 +6,17 @@ - + This is a water meter that complies to the DSMR V2.2 specification. - - - + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_v3_0.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_v3_0.xml index b943afbf4f5ac..769ddb050fc9d 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_v3_0.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/meter_water_v3_0.xml @@ -6,18 +6,18 @@ - + This is a water meter that complies to the DSMR V3.0 specification. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/smarty_device.xml b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/smarty_device.xml index 2ea0a18555b1a..ff4f2d5d70ffa 100644 --- a/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/smarty_device.xml +++ b/bundles/org.openhab.binding.dsmr/src/main/resources/ESH-INF/thing/smarty_device.xml @@ -8,7 +8,7 @@ The Luxembourgian Smart Meter 'Smarty' - + diff --git a/bundles/org.openhab.binding.dsmr/src/test/java/org/openhab/binding/dsmr/internal/discovery/DSMRMeterDetectorTest.java b/bundles/org.openhab.binding.dsmr/src/test/java/org/openhab/binding/dsmr/internal/discovery/DSMRMeterDetectorTest.java index b1f5f3c6222fc..a68097142a766 100644 --- a/bundles/org.openhab.binding.dsmr/src/test/java/org/openhab/binding/dsmr/internal/discovery/DSMRMeterDetectorTest.java +++ b/bundles/org.openhab.binding.dsmr/src/test/java/org/openhab/binding/dsmr/internal/discovery/DSMRMeterDetectorTest.java @@ -89,5 +89,4 @@ public void testDetectMeters() { 1, detectMeters.stream().filter(e -> e.getMeterType() == meter).count()); } } - } diff --git a/bundles/org.openhab.binding.dwdpollenflug/.classpath b/bundles/org.openhab.binding.dwdpollenflug/.classpath index 14ba193a4882c..13d903b892ca6 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/.classpath +++ b/bundles/org.openhab.binding.dwdpollenflug/.classpath @@ -1,49 +1,49 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/.project b/bundles/org.openhab.binding.dwdpollenflug/.project index 3cf695e17193f..80deb524b1ffb 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/.project +++ b/bundles/org.openhab.binding.dwdpollenflug/.project @@ -1,23 +1,23 @@ - - - org.openhab.binding.dwdpollenflug - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - + + + org.openhab.binding.dwdpollenflug + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/README.md b/bundles/org.openhab.binding.dwdpollenflug/README.md index 6d23af4f8ebc0..a882215933cd7 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/README.md +++ b/bundles/org.openhab.binding.dwdpollenflug/README.md @@ -1,203 +1,203 @@ -# DWDPollenflug Binding - -The "Deutsche Wetterdienst" (DWD) reports the current pollen count index for Germany on a daily base and a forecast for tomorrow and the day after tomorrow. -This binding allows you to retrieve this data for your region or partregion. You can find a map of the data here: - -https://isabel.dwd.de/DE/leistungen/gefahrenindizespollen/gefahrenindexpollen.html - - -## Supported Things - -This binding supports a bridge thing (`bridge`), which polls the dataset for Germany in an adjustable interval. -And it supports a region thing (`region`), representing the data for all pollen types of a region or partregion. - -## Discovery - -This binding adds a default `bridge` thing to the Inbox. -This can be used for `region` things you may add manually. - -## Thing Configuration - -### Bridge - -| Parameter | Default | Required | Description | -| --------- | :-----: | :------: | ------------------------------------------------------------------------------------ | -| `refresh` | 30 | no | Define the interval for polling the data from DWD in minutes. Minimum is 15 minutes. | - -### Region - -| Parameter | Default | Required | Description | -| ---------- | :-----: | :------: | -------------------------------------------------------------------------------------------------------- | -| `regionID` | - | yes | In PaperUI just select the region you want to display data for. For files-configuration see table below. | - -#### Manual region or partregion selection #### - -The region ID is the partregion_id or if there is no partregion the region_id from this [json](https://opendata.dwd.de/climate_environment/health/alerts/s31fg.json) of DWD. -You can refer to the following table. - -| regionID | Region | Partregion | -| -------- | ------------------------------ | -------------------------------------------------- | -| 11 | Schleswig-Holstein und Hamburg | Inseln und Marschen | -| 12 | Schleswig-Holstein und Hamburg | Geest, Schleswig-Holstein und Hamburg | -| 20 | Mecklenburg-Vorpommern | - | -| 31 | Niedersachsen und Bremen | Westl. Niedersachsen/Bremen | -| 32 | Niedersachsen und Bremen | Östl. Niedersachsen | -| 41 | Nordrhein-Westfalen | Rhein.-Westfäl. Tiefland | -| 42 | Nordrhein-Westfalen | Ostwestfalen | -| 43 | Nordrhein-Westfalen | Mittelgebirge NRW | -| 50 | Brandenburg und Berlin | - | -| 61 | Sachsen-Anhalt | Tiefland Sachsen-Anhalt | -| 62 | Sachsen-Anhalt | Harz | -| 71 | Thüringen | Tiefland Thüringen | -| 72 | Thüringen | Mittelgebirge Thüringen | -| 81 | Sachsen | Tiefland Sachsen | -| 82 | Sachsen | Mittelgebirge Sachsen | -| 91 | Hessen | Nordhessen und hess. Mittelgebirge | -| 92 | Hessen | Rhein-Main | -| 101 | Rheinland-Pfalz und Saarland | Rhein, Pfalz, Nahe und Mosel | -| 102 | Rheinland-Pfalz und Saarland | Mittelgebirgsbereich Rheinland-Pfalz | -| 103 | Rheinland-Pfalz und Saarland | Saarland | -| 111 | Baden-Württemberg | Oberrhein und unteres Neckartal | -| 112 | Baden-Württemberg | Hohenlohe/mittlerer Neckar/Oberschwaben | -| 113 | Baden-Württemberg | Mittelgebirge Baden-Württemberg | -| 121 | Bayern | Allgäu/Oberbayern/Bay. Wald | -| 122 | Bayern | Donauniederungen | -| 123 | Bayern | Bayern n. der Donau, o. Bayr. Wald, o. Mainfranken | -| 124 | Bayern | Mainfranken | - -## Channels - -The bridge thing has following channels: - -| channel | description | -| --------------------- | ---------------------------------------------- | -| `updates#refreshed` | Hold the time of the bridge's last refresh | -| `updates#last_update` | The time when data was last updated by DWD | -| `updates#next_update` | The time when data will be updated next by DWD | - -For each of the eight pollen types reported by DWD the region thing has three channels for today, tomorrow and the day after tomorrow. - -| channels | pollen type | german name | -| ---------------------- | ----------- | ----------- | -| `alder#today` | alder | Erle | -| `alder#tomorrow` | | | -| `alder#dayafter_to` | | | -| `ambrosia#today` | ambrosia | Ambrosia | -| `ambrosia#tomorrow` | | | -| `ambrosia#dayafter_to` | | | -| `ash#today` | ash-tree | Esche | -| `ash#tomorrow` | | | -| `ash#dayafter_to` | | | -| `birch#today` | birch | Birke | -| `birch#tomorrow` | | | -| `birch#dayafter_to` | | | -| `grasses#today` | grasses | Gräser | -| `grasses#tomorrow` | | | -| `grasses#dayafter_to` | | | -| `hazel#today` | hazel | Hasel | -| `hazel#tomorrow` | | | -| `hazel#dayafter_to` | | | -| `mugwort#today` | mugwort | Beifuß | -| `mugwort#tomorrow` | | | -| `mugwort#dayafter_to` | | | -| `rye#today` | rye | Roggen | -| `rye#tomorrow` | | | -| `rye#dayafter_to` | | | - -There are the following possible string values: - -| value | description | -| ----- | --------------------------- | -| -1 | not specified | -| 0 | no pollen pollution | -| 0-1 | no to low pollen count | -| 1 | low pollen count | -| 1-2 | low to medium pollen count | -| 2 | medium pollen count | -| 2-3 | medium to high pollen count | -| 3 | high pollen count | - -## Full Example - -### Things file for region "Brandenburg und Berlin" and partregion "Bayern - Mainfranken" ### - -``` -Bridge dwdpollenflug:bridge:dwd "DWD pollen count Bridge" [refresh="15"] { - Thing region region50 "DWD pollen count region" @ "APIS" [regionID="50"] - Thing region partregion124 "DWD pollen count partregion" @ "APIS" [regionID="124"] -} -``` - -### Items example for region "Brandenburg und Berlin" and pollen type ash-tree ### - -``` -String pollenTodayEsche - "Esche [MAP(pollen.map):%s]" - {channel="dwdpollenflug:region:dwd:region50:ash#today"} - -String pollenTomorrowEsche - "Esche morgen [MAP(pollen.map):%s]" - {channel="dwdpollenflug:region:dwd:region50:ash#tomorrow"} - -String pollenDayAfterTomorrowEsche - "Esche übermorgen [MAP(pollen.map):%s]" - {channel="dwdpollenflug:region:dwd:region50:ash#dayafter_to"} - -``` - -### Transform map file pollen.map ### - -``` -0=keine (0) -0-1=keine bis gering (0-1) -1=gering (1) -1-2=gering bis mittel (1-2) -2=mittel (2) -2-3=mittel bis hoch (2-3) -3=hoch (3) --1=keine Daten --=keine Daten -NULL=keine Daten -``` - -### Sitemap example for region "Brandenburg und Berlin" and pollen type ash-tree ### - -``` -Text label="Pollenflugindex" { - Frame { - Text item=pollenTodayEsche - valuecolor=[=="3"="#f00014", - =="2-3"="#f00014", - =="2"="#ff9900", - =="1-2"="#ff9900", - =="1"="#ffff00", - =="0-1"="#00c83c"] { - Frame { - Text item=pollenTodayEsche - valuecolor=[=="3"="#f00014", - =="2-3"="#f00014", - =="2"="#ff9900", - =="1-2"="#ff9900", - =="1"="#ffff00", - =="0-1"="#00c83c"] - - Text item=pollenTomorrowEsche - valuecolor=[=="3"="#f00014", - =="2-3"="#f00014", - =="2"="#ff9900", - =="1-2"="#ff9900", - =="1"="#ffff00", - =="0-1"="#00c83c"] - - Text item=pollenDayAfterTomorrowEsche - valuecolor=[=="3"="#f00014", - =="2-3"="#f00014", - =="2"="#ff9900", - =="1-2"="#ff9900", - =="1"="#ffff00", - =="0-1"="#00c83c"] - } - } - } -} -``` +# DWDPollenflug Binding + +The "Deutsche Wetterdienst" (DWD) reports the current pollen count index for Germany on a daily base and a forecast for tomorrow and the day after tomorrow. +This binding allows you to retrieve this data for your region or partregion. You can find a map of the data here: + +https://isabel.dwd.de/DE/leistungen/gefahrenindizespollen/gefahrenindexpollen.html + + +## Supported Things + +This binding supports a bridge thing (`bridge`), which polls the dataset for Germany in an adjustable interval. +And it supports a region thing (`region`), representing the data for all pollen types of a region or partregion. + +## Discovery + +This binding adds a default `bridge` thing to the Inbox. +This can be used for `region` things you may add manually. + +## Thing Configuration + +### Bridge + +| Parameter | Default | Required | Description | +| --------- | :-----: | :------: | ------------------------------------------------------------------------------------ | +| `refresh` | 30 | no | Define the interval for polling the data from DWD in minutes. Minimum is 15 minutes. | + +### Region + +| Parameter | Default | Required | Description | +| ---------- | :-----: | :------: | -------------------------------------------------------------------------------------------------------- | +| `regionID` | - | yes | In PaperUI just select the region you want to display data for. For files-configuration see table below. | + +#### Manual region or partregion selection #### + +The region ID is the partregion_id or if there is no partregion the region_id from this [json](https://opendata.dwd.de/climate_environment/health/alerts/s31fg.json) of DWD. +You can refer to the following table. + +| regionID | Region | Partregion | +| -------- | ------------------------------ | -------------------------------------------------- | +| 11 | Schleswig-Holstein und Hamburg | Inseln und Marschen | +| 12 | Schleswig-Holstein und Hamburg | Geest, Schleswig-Holstein und Hamburg | +| 20 | Mecklenburg-Vorpommern | - | +| 31 | Niedersachsen und Bremen | Westl. Niedersachsen/Bremen | +| 32 | Niedersachsen und Bremen | Östl. Niedersachsen | +| 41 | Nordrhein-Westfalen | Rhein.-Westfäl. Tiefland | +| 42 | Nordrhein-Westfalen | Ostwestfalen | +| 43 | Nordrhein-Westfalen | Mittelgebirge NRW | +| 50 | Brandenburg und Berlin | - | +| 61 | Sachsen-Anhalt | Tiefland Sachsen-Anhalt | +| 62 | Sachsen-Anhalt | Harz | +| 71 | Thüringen | Tiefland Thüringen | +| 72 | Thüringen | Mittelgebirge Thüringen | +| 81 | Sachsen | Tiefland Sachsen | +| 82 | Sachsen | Mittelgebirge Sachsen | +| 91 | Hessen | Nordhessen und hess. Mittelgebirge | +| 92 | Hessen | Rhein-Main | +| 101 | Rheinland-Pfalz und Saarland | Rhein, Pfalz, Nahe und Mosel | +| 102 | Rheinland-Pfalz und Saarland | Mittelgebirgsbereich Rheinland-Pfalz | +| 103 | Rheinland-Pfalz und Saarland | Saarland | +| 111 | Baden-Württemberg | Oberrhein und unteres Neckartal | +| 112 | Baden-Württemberg | Hohenlohe/mittlerer Neckar/Oberschwaben | +| 113 | Baden-Württemberg | Mittelgebirge Baden-Württemberg | +| 121 | Bayern | Allgäu/Oberbayern/Bay. Wald | +| 122 | Bayern | Donauniederungen | +| 123 | Bayern | Bayern n. der Donau, o. Bayr. Wald, o. Mainfranken | +| 124 | Bayern | Mainfranken | + +## Channels + +The bridge thing has following channels: + +| channel | description | +| --------------------- | ---------------------------------------------- | +| `updates#refreshed` | Hold the time of the bridge's last refresh | +| `updates#last_update` | The time when data was last updated by DWD | +| `updates#next_update` | The time when data will be updated next by DWD | + +For each of the eight pollen types reported by DWD the region thing has three channels for today, tomorrow and the day after tomorrow. + +| channels | pollen type | german name | +| ---------------------- | ----------- | ----------- | +| `alder#today` | alder | Erle | +| `alder#tomorrow` | | | +| `alder#dayafter_to` | | | +| `ambrosia#today` | ambrosia | Ambrosia | +| `ambrosia#tomorrow` | | | +| `ambrosia#dayafter_to` | | | +| `ash#today` | ash-tree | Esche | +| `ash#tomorrow` | | | +| `ash#dayafter_to` | | | +| `birch#today` | birch | Birke | +| `birch#tomorrow` | | | +| `birch#dayafter_to` | | | +| `grasses#today` | grasses | Gräser | +| `grasses#tomorrow` | | | +| `grasses#dayafter_to` | | | +| `hazel#today` | hazel | Hasel | +| `hazel#tomorrow` | | | +| `hazel#dayafter_to` | | | +| `mugwort#today` | mugwort | Beifuß | +| `mugwort#tomorrow` | | | +| `mugwort#dayafter_to` | | | +| `rye#today` | rye | Roggen | +| `rye#tomorrow` | | | +| `rye#dayafter_to` | | | + +There are the following possible string values: + +| value | description | +| ----- | --------------------------- | +| -1 | not specified | +| 0 | no pollen pollution | +| 0-1 | no to low pollen count | +| 1 | low pollen count | +| 1-2 | low to medium pollen count | +| 2 | medium pollen count | +| 2-3 | medium to high pollen count | +| 3 | high pollen count | + +## Full Example + +### Things file for region "Brandenburg und Berlin" and partregion "Bayern - Mainfranken" ### + +``` +Bridge dwdpollenflug:bridge:dwd "DWD pollen count Bridge" [refresh="15"] { + Thing region region50 "DWD pollen count region" @ "APIS" [regionID="50"] + Thing region partregion124 "DWD pollen count partregion" @ "APIS" [regionID="124"] +} +``` + +### Items example for region "Brandenburg und Berlin" and pollen type ash-tree ### + +``` +String pollenTodayEsche + "Esche [MAP(pollen.map):%s]" + {channel="dwdpollenflug:region:dwd:region50:ash#today"} + +String pollenTomorrowEsche + "Esche morgen [MAP(pollen.map):%s]" + {channel="dwdpollenflug:region:dwd:region50:ash#tomorrow"} + +String pollenDayAfterTomorrowEsche + "Esche übermorgen [MAP(pollen.map):%s]" + {channel="dwdpollenflug:region:dwd:region50:ash#dayafter_to"} + +``` + +### Transform map file pollen.map ### + +``` +0=keine (0) +0-1=keine bis gering (0-1) +1=gering (1) +1-2=gering bis mittel (1-2) +2=mittel (2) +2-3=mittel bis hoch (2-3) +3=hoch (3) +-1=keine Daten +-=keine Daten +NULL=keine Daten +``` + +### Sitemap example for region "Brandenburg und Berlin" and pollen type ash-tree ### + +``` +Text label="Pollenflugindex" { + Frame { + Text item=pollenTodayEsche + valuecolor=[=="3"="#f00014", + =="2-3"="#f00014", + =="2"="#ff9900", + =="1-2"="#ff9900", + =="1"="#ffff00", + =="0-1"="#00c83c"] { + Frame { + Text item=pollenTodayEsche + valuecolor=[=="3"="#f00014", + =="2-3"="#f00014", + =="2"="#ff9900", + =="1-2"="#ff9900", + =="1"="#ffff00", + =="0-1"="#00c83c"] + + Text item=pollenTomorrowEsche + valuecolor=[=="3"="#f00014", + =="2-3"="#f00014", + =="2"="#ff9900", + =="1-2"="#ff9900", + =="1"="#ffff00", + =="0-1"="#00c83c"] + + Text item=pollenDayAfterTomorrowEsche + valuecolor=[=="3"="#f00014", + =="2-3"="#f00014", + =="2"="#ff9900", + =="1-2"="#ff9900", + =="1"="#ffff00", + =="0-1"="#00c83c"] + } + } + } +} +``` diff --git a/bundles/org.openhab.binding.dwdpollenflug/pom.xml b/bundles/org.openhab.binding.dwdpollenflug/pom.xml index fbdfff8493894..e37e8c25a4bd6 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/pom.xml +++ b/bundles/org.openhab.binding.dwdpollenflug/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.dwdpollenflug diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/feature/feature.xml b/bundles/org.openhab.binding.dwdpollenflug/src/main/feature/feature.xml index e4e5901453f68..800ebdbdef866 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.dwdpollenflug/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.dwdpollenflug/${project.version} + diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugBindingConstants.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugBindingConstants.java index 9f820c3ea481d..444e40f7be253 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugBindingConstants.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugBindingConstants.java @@ -1,77 +1,77 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal; - -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.core.thing.ThingTypeUID; - -/** - * The {@link DWDPollenflugBindingConstants} class defines common constants, which are - * used across the whole binding. - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDPollenflugBindingConstants { - - private static final String BINDING_ID = "dwdpollenflug"; - - // bridge - public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge"); - public static final String DWD = "dwd"; - public static final String BRIDGE_LABEL = "DWD Pollen Count Index (Bridge)"; - - // List of all Thing Type UIDs - public static final ThingTypeUID THING_TYPE_REGION = new ThingTypeUID(BINDING_ID, "region"); - - // @formatter:off - public static final Set SUPPORTED_THING_TYPES_UIDS = - Collections.unmodifiableSet(Stream - .of(THING_TYPE_BRIDGE, THING_TYPE_REGION) - .collect(Collectors.toSet()) - ); - // @formatter:on - - // Channels of pollen groups - public static final String CHANNEL_TODAY = "today"; - public static final String CHANNEL_TOMORROW = "tomorrow"; - public static final String CHANNEL_DAYAFTER_TO = "dayafter_to"; - - // Channels of region update - public static final String CHANNEL_UPDATES = "updates"; - public static final String CHANNEL_REFRESHED = "refreshed"; - public static final String CHANNEL_NEXT_UPDATE = "next_update"; - public static final String CHANNEL_LAST_UPDATE = "last_update"; - public static final String CHANNEL_UPDATED = "updated"; - - public static final String TRIGGER_REFRESHED = "REFRESHED"; - - // Bridge config properties - public static final String REFRESH = "refresh"; - - // Bridge properties - public static final String PROPERTY_SENDER = "sender"; - public static final String PROPERTY_NAME = "name"; - - // Region config properties - public static final String REGION_ID = "regionID"; - - // Region properties - public static final String PROPERTY_REGION_NAME = "region_name"; - public static final String PROPERTY_PARTREGION_NAME = "partregion_name"; -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link DWDPollenflugBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugBindingConstants { + + private static final String BINDING_ID = "dwdpollenflug"; + + // bridge + public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge"); + public static final String DWD = "dwd"; + public static final String BRIDGE_LABEL = "DWD Pollen Count Index (Bridge)"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_REGION = new ThingTypeUID(BINDING_ID, "region"); + + // @formatter:off + public static final Set SUPPORTED_THING_TYPES_UIDS = + Collections.unmodifiableSet(Stream + .of(THING_TYPE_BRIDGE, THING_TYPE_REGION) + .collect(Collectors.toSet()) + ); + // @formatter:on + + // Channels of pollen groups + public static final String CHANNEL_TODAY = "today"; + public static final String CHANNEL_TOMORROW = "tomorrow"; + public static final String CHANNEL_DAYAFTER_TO = "dayafter_to"; + + // Channels of region update + public static final String CHANNEL_UPDATES = "updates"; + public static final String CHANNEL_REFRESHED = "refreshed"; + public static final String CHANNEL_NEXT_UPDATE = "next_update"; + public static final String CHANNEL_LAST_UPDATE = "last_update"; + public static final String CHANNEL_UPDATED = "updated"; + + public static final String TRIGGER_REFRESHED = "REFRESHED"; + + // Bridge config properties + public static final String REFRESH = "refresh"; + + // Bridge properties + public static final String PROPERTY_SENDER = "sender"; + public static final String PROPERTY_NAME = "name"; + + // Region config properties + public static final String REGION_ID = "regionID"; + + // Region properties + public static final String PROPERTY_REGION_NAME = "region_name"; + public static final String PROPERTY_PARTREGION_NAME = "partregion_name"; +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugHandlerFactory.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugHandlerFactory.java index 9d181c52ce4bd..d7a94b9fbff16 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugHandlerFactory.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollenflugHandlerFactory.java @@ -1,66 +1,66 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal; - -import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; -import org.eclipse.smarthome.io.net.http.HttpClientFactory; -import org.openhab.binding.dwdpollenflug.internal.handler.DWDPollenflugBridgeHandler; -import org.openhab.binding.dwdpollenflug.internal.handler.DWDPollenflugRegionHandler; -import org.osgi.service.component.annotations.Activate; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; - -/** - * The {@link DWDPollenflugHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -@Component(configurationPid = "binding.dwdpollenflug", service = ThingHandlerFactory.class) -public class DWDPollenflugHandlerFactory extends BaseThingHandlerFactory { - private final HttpClient httpClient; - - @Activate - public DWDPollenflugHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { - this.httpClient = httpClientFactory.getCommonHttpClient(); - } - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected @Nullable ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - if (THING_TYPE_BRIDGE.equals(thingTypeUID)) { - return new DWDPollenflugBridgeHandler((Bridge) thing, httpClient); - } else if (THING_TYPE_REGION.equals(thingTypeUID)) { - return new DWDPollenflugRegionHandler(thing); - } - - return null; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal; + +import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.net.http.HttpClientFactory; +import org.openhab.binding.dwdpollenflug.internal.handler.DWDPollenflugBridgeHandler; +import org.openhab.binding.dwdpollenflug.internal.handler.DWDPollenflugRegionHandler; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link DWDPollenflugHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.dwdpollenflug", service = ThingHandlerFactory.class) +public class DWDPollenflugHandlerFactory extends BaseThingHandlerFactory { + private final HttpClient httpClient; + + @Activate + public DWDPollenflugHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_BRIDGE.equals(thingTypeUID)) { + return new DWDPollenflugBridgeHandler((Bridge) thing, httpClient); + } else if (THING_TYPE_REGION.equals(thingTypeUID)) { + return new DWDPollenflugRegionHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollingException.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollingException.java index 26d3de7073652..da578def3807a 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollingException.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/DWDPollingException.java @@ -1,34 +1,34 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * The {@link DWDPollingException} class is the exception for all polling errors. - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDPollingException extends Exception { - - private static final long serialVersionUID = 1L; - - public DWDPollingException(String message) { - super(message); - } - - public DWDPollingException(String message, Throwable throwable) { - super(message, throwable); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link DWDPollingException} class is the exception for all polling errors. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollingException extends Exception { + + private static final long serialVersionUID = 1L; + + public DWDPollingException(String message) { + super(message); + } + + public DWDPollingException(String message, Throwable throwable) { + super(message, throwable); + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugBridgeConfiguration.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugBridgeConfiguration.java index ea73d371cc69f..4873cd265e519 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugBridgeConfiguration.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugBridgeConfiguration.java @@ -1,29 +1,29 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal.config; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * Configuration for the {@link DWDPollenflugBridgeHandler} - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDPollenflugBridgeConfiguration { - public int refresh = 30; - - public boolean isValid() { - return refresh >= 15; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Configuration for the {@link DWDPollenflugBridgeHandler} + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugBridgeConfiguration { + public int refresh = 30; + + public boolean isValid() { + return refresh >= 15; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugRegionConfiguration.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugRegionConfiguration.java index 87fe8de2661ee..dfa22ad948e29 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugRegionConfiguration.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/config/DWDPollenflugRegionConfiguration.java @@ -1,29 +1,29 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal.config; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * Configuration for the {@link DWDPollenflugRegionHandler} - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDPollenflugRegionConfiguration { - public int regionID; - - public boolean isValid() { - return regionID > 0; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Configuration for the {@link DWDPollenflugRegionHandler} + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugRegionConfiguration { + public int regionID; + + public boolean isValid() { + return regionID > 0; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflug.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflug.java index b3edfa797bc7e..6edf7e63b9b8f 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflug.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflug.java @@ -1,111 +1,111 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal.dto; - -import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.google.gson.annotations.SerializedName; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.types.DateTimeType; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.UnDefType; - -/** - * The {@link DWDPollenflug} class is internal DWD data structure. - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDPollenflug { - private String sender = ""; - - private String name = ""; - - private final Date created = new Date(); - - @SerializedName("next_update") - private @Nullable String nextUpdate; - - @SerializedName("last_update") - private @Nullable String lastUpdate; - - @SerializedName("content") - private @Nullable Set regions; - - public Map getProperties() { - Map map = new HashMap<>(); - - map.put(PROPERTY_NAME, name); - map.put(PROPERTY_SENDER, sender); - - return Collections.unmodifiableMap(map); - } - - public Map getChannelsStateMap() { - Map map = new HashMap<>(); - - map.put(CHANNEL_UPDATES + "#" + CHANNEL_REFRESHED, parseDate(created)); - map.put(CHANNEL_UPDATES + "#" + CHANNEL_LAST_UPDATE, parseDate(lastUpdate)); - map.put(CHANNEL_UPDATES + "#" + CHANNEL_NEXT_UPDATE, parseDate(nextUpdate)); - - return Collections.unmodifiableMap(map); - } - - private State parseDate(final @Nullable String dateString) { - try { - if (dateString != null) { - SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm"); - Date date = formatter.parse(dateString.replace("Uhr", "").trim()); - return parseDate(date); - } - - return UnDefType.NULL; - } catch (ParseException e) { - return UnDefType.NULL; - } - } - - private State parseDate(final @Nullable Date date) { - if (date == null) { - return UnDefType.NULL; - } else { - ZonedDateTime zoned = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); - return new DateTimeType(zoned); - } - } - - public @Nullable DWDRegion getRegion(int key) { - final Set localRegions = regions; - if (localRegions != null) { - for (DWDRegion region : localRegions) { - if (region.getRegionID() == key) { - return region; - } - } - } - - return null; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal.dto; + +import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.DateTimeType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link DWDPollenflug} class is internal DWD data structure. + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflug { + private String sender = ""; + + private String name = ""; + + private final Date created = new Date(); + + @SerializedName("next_update") + private @Nullable String nextUpdate; + + @SerializedName("last_update") + private @Nullable String lastUpdate; + + @SerializedName("content") + private @Nullable Set regions; + + public Map getProperties() { + Map map = new HashMap<>(); + + map.put(PROPERTY_NAME, name); + map.put(PROPERTY_SENDER, sender); + + return Collections.unmodifiableMap(map); + } + + public Map getChannelsStateMap() { + Map map = new HashMap<>(); + + map.put(CHANNEL_UPDATES + "#" + CHANNEL_REFRESHED, parseDate(created)); + map.put(CHANNEL_UPDATES + "#" + CHANNEL_LAST_UPDATE, parseDate(lastUpdate)); + map.put(CHANNEL_UPDATES + "#" + CHANNEL_NEXT_UPDATE, parseDate(nextUpdate)); + + return Collections.unmodifiableMap(map); + } + + private State parseDate(final @Nullable String dateString) { + try { + if (dateString != null) { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + Date date = formatter.parse(dateString.replace("Uhr", "").trim()); + return parseDate(date); + } + + return UnDefType.NULL; + } catch (ParseException e) { + return UnDefType.NULL; + } + } + + private State parseDate(final @Nullable Date date) { + if (date == null) { + return UnDefType.NULL; + } else { + ZonedDateTime zoned = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()); + return new DateTimeType(zoned); + } + } + + public @Nullable DWDRegion getRegion(int key) { + final Set localRegions = regions; + if (localRegions != null) { + for (DWDRegion region : localRegions) { + if (region.getRegionID() == key) { + return region; + } + } + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflugPollen.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflugPollen.java index 4e03734e74518..fbe9e51e0e1be 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflugPollen.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollenflugPollen.java @@ -1,39 +1,39 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal.dto; - -/** - * The {@link DWDPollenflug} class is internal DWD data structure. - * - * @author Johannes Ott - Initial contribution - */ -public enum DWDPollenflugPollen { - AMBROSIA("ambrosia"), - BEIFUSS("mugwort"), - BIRKE("birch"), - ERLE("alder"), - ESCHE("ash"), - GRAESER("grasses"), - HASEL("hazel"), - ROGGEN("rye"); - - private final String channelName; - - private DWDPollenflugPollen(String channelName) { - this.channelName = channelName; - } - - public String getChannelName() { - return channelName; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal.dto; + +/** + * The {@link DWDPollenflug} class is internal DWD data structure. + * + * @author Johannes Ott - Initial contribution + */ +public enum DWDPollenflugPollen { + AMBROSIA("ambrosia"), + BEIFUSS("mugwort"), + BIRKE("birch"), + ERLE("alder"), + ESCHE("ash"), + GRAESER("grasses"), + HASEL("hazel"), + ROGGEN("rye"); + + private final String channelName; + + private DWDPollenflugPollen(String channelName) { + this.channelName = channelName; + } + + public String getChannelName() { + return channelName; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollentypeJSON.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollentypeJSON.java index e1188299f460d..1ead0a889e423 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollentypeJSON.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDPollentypeJSON.java @@ -1,32 +1,32 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal.dto; - -import com.google.gson.annotations.SerializedName; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * DTO for data per pollen type - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDPollentypeJSON { - public String today = "-1"; - - public String tomorrow = "-1"; - - @SerializedName("dayafter_to") - public String dayAfterTomorrow = "-1"; -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal.dto; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.SerializedName; + +/** + * DTO for data per pollen type + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollentypeJSON { + public String today = "-1"; + + public String tomorrow = "-1"; + + @SerializedName("dayafter_to") + public String dayAfterTomorrow = "-1"; +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDRegion.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDRegion.java index aa1772346411f..f8351072ea565 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDRegion.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/dto/DWDRegion.java @@ -1,80 +1,80 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal.dto; - -import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import com.google.gson.annotations.SerializedName; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.types.State; - -/** - * The {@link DWDRegion} class holds the internal data representation of each Region - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDRegion { - @SerializedName("region_id") - public int regionID = 0; - - @SerializedName("region_name") - public String regionName = ""; - - @SerializedName("partregion_id") - public int partRegionID = 0; - - @SerializedName("partregion_name") - public String partRegionName = ""; - - @SerializedName("Pollen") - private @Nullable Map pollen; - - public Map getProperties() { - Map map = new HashMap<>(); - map.put(PROPERTY_REGION_NAME, regionName); - map.put(PROPERTY_PARTREGION_NAME, partRegionName); - return Collections.unmodifiableMap(map); - } - - public int getRegionID() { - if (partRegionID > 0) { - return partRegionID; - } - return regionID; - } - - public Map getChannelsStateMap() { - final Map localPollen = pollen; - if (localPollen != null) { - Map map = new HashMap<>(); - localPollen.forEach((k, jsonType) -> { - final String pollenType = DWDPollenflugPollen.valueOf(k.toUpperCase()).getChannelName(); - map.put(pollenType + "#" + CHANNEL_TODAY, new StringType(jsonType.today)); - map.put(pollenType + "#" + CHANNEL_TOMORROW, new StringType(jsonType.tomorrow)); - map.put(pollenType + "#" + CHANNEL_DAYAFTER_TO, new StringType(jsonType.dayAfterTomorrow)); - }); - - return Collections.unmodifiableMap(map); - } - - return Collections.emptyMap(); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal.dto; + +import static org.openhab.binding.dwdpollenflug.internal.DWDPollenflugBindingConstants.*; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.types.State; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link DWDRegion} class holds the internal data representation of each Region + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDRegion { + @SerializedName("region_id") + public int regionID = 0; + + @SerializedName("region_name") + public String regionName = ""; + + @SerializedName("partregion_id") + public int partRegionID = 0; + + @SerializedName("partregion_name") + public String partRegionName = ""; + + @SerializedName("Pollen") + private @Nullable Map pollen; + + public Map getProperties() { + Map map = new HashMap<>(); + map.put(PROPERTY_REGION_NAME, regionName); + map.put(PROPERTY_PARTREGION_NAME, partRegionName); + return Collections.unmodifiableMap(map); + } + + public int getRegionID() { + if (partRegionID > 0) { + return partRegionID; + } + return regionID; + } + + public Map getChannelsStateMap() { + final Map localPollen = pollen; + if (localPollen != null) { + Map map = new HashMap<>(); + localPollen.forEach((k, jsonType) -> { + final String pollenType = DWDPollenflugPollen.valueOf(k.toUpperCase()).getChannelName(); + map.put(pollenType + "#" + CHANNEL_TODAY, new StringType(jsonType.today)); + map.put(pollenType + "#" + CHANNEL_TOMORROW, new StringType(jsonType.tomorrow)); + map.put(pollenType + "#" + CHANNEL_DAYAFTER_TO, new StringType(jsonType.dayAfterTomorrow)); + }); + + return Collections.unmodifiableMap(map); + } + + return Collections.emptyMap(); + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugBridgeHandler.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugBridgeHandler.java index 225e86343d0a3..5d4307327c50d 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugBridgeHandler.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugBridgeHandler.java @@ -1,211 +1,211 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal.handler; - -import java.net.URI; -import java.util.Set; -import java.net.SocketTimeoutException; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.HttpResponse; -import org.eclipse.jetty.client.api.Request; -import org.eclipse.jetty.client.api.Result; -import org.eclipse.jetty.client.util.BufferingResponseListener; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.dwdpollenflug.internal.DWDPollingException; -import org.openhab.binding.dwdpollenflug.internal.config.DWDPollenflugBridgeConfiguration; -import org.openhab.binding.dwdpollenflug.internal.dto.DWDPollenflug; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link DWDPollenflugBridgeHandler} is the handler for bridge thing - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDPollenflugBridgeHandler extends BaseBridgeHandler { - private static final String DWD_URL = "https://opendata.dwd.de/climate_environment/health/alerts/s31fg.json"; - - private final Logger logger = LoggerFactory.getLogger(DWDPollenflugBridgeHandler.class); - - private DWDPollenflugBridgeConfiguration bridgeConfig = new DWDPollenflugBridgeConfiguration(); - private @Nullable ScheduledFuture pollingJob; - private @Nullable DWDPollenflug pollenflug; - private final Set regionListeners = ConcurrentHashMap.newKeySet(); - private final HttpClient client; - private final Gson gson = new Gson(); - - public DWDPollenflugBridgeHandler(Bridge bridge, HttpClient client) { - super(bridge); - this.client = client; - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - if (command instanceof RefreshType) { - final DWDPollenflug localPollenflug = pollenflug; - if (localPollenflug != null) { - notifyOnUpdate(localPollenflug); - } - } - } - - @Override - public void initialize() { - logger.debug("Initializing DWD Pollenflug bridge handler"); - bridgeConfig = getConfigAs(DWDPollenflugBridgeConfiguration.class); - - if (bridgeConfig.isValid()) { - updateStatus(ThingStatus.UNKNOWN); - startPolling(); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Refresh interval has to be at least 15 minutes."); - } - } - - @Override - public void dispose() { - logger.debug("Handler disposed."); - stopPolling(); - } - - private void startPolling() { - final ScheduledFuture localPollingJob = this.pollingJob; - if (localPollingJob == null || localPollingJob.isCancelled()) { - logger.debug("Start polling."); - pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, bridgeConfig.refresh, TimeUnit.MINUTES); - } - } - - private void stopPolling() { - final ScheduledFuture localPollingJob = this.pollingJob; - if (localPollingJob != null && !localPollingJob.isCancelled()) { - logger.debug("Stop polling."); - localPollingJob.cancel(true); - pollingJob = null; - } - } - - private void poll() { - logger.debug("Polling"); - requestRefresh().handle((resultPollenflug, pollException) -> { - if (resultPollenflug == null) { - if (pollException == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - pollException.getMessage()); - } - } else { - updateStatus(ThingStatus.ONLINE); - notifyOnUpdate(resultPollenflug); - } - - return null; - }); - } - - private CompletableFuture<@Nullable DWDPollenflug> requestRefresh() { - CompletableFuture<@Nullable DWDPollenflug> f = new CompletableFuture<>(); - Request request = client.newRequest(URI.create(DWD_URL)); - - request.method(HttpMethod.GET).timeout(2000, TimeUnit.SECONDS).send(new BufferingResponseListener() { - @NonNullByDefault({}) - @Override - public void onComplete(Result result) { - final HttpResponse response = (HttpResponse) result.getResponse(); - if (result.getFailure() != null) { - Throwable e = result.getFailure(); - if (e instanceof SocketTimeoutException || e instanceof TimeoutException) { - f.completeExceptionally(new DWDPollingException("Request timeout", e)); - } else { - f.completeExceptionally(new DWDPollingException("Request failed", e)); - } - } else if (response.getStatus() != 200) { - f.completeExceptionally(new DWDPollingException(getContentAsString())); - } else { - try { - DWDPollenflug pollenflugJSON = gson.fromJson(getContentAsString(), DWDPollenflug.class); - f.complete(pollenflugJSON); - } catch (JsonSyntaxException ex2) { - f.completeExceptionally(new DWDPollingException("Parsing of response failed")); - } - } - } - }); - - return f; - } - - @Override - public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { - if (childHandler instanceof DWDPollenflugRegionHandler) { - logger.debug("Register region listener."); - final DWDPollenflugRegionHandler regionListener = (DWDPollenflugRegionHandler) childHandler; - if (regionListeners.add(regionListener)) { - final DWDPollenflug localPollenflug = pollenflug; - if (localPollenflug != null) { - regionListener.notifyOnUpdate(localPollenflug); - } - } else { - logger.warn("Tried to add listener {} but it was already present. This is probably an error.", - childHandler); - } - } - } - - @Override - public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { - if (childHandler instanceof DWDPollenflugRegionHandler) { - logger.debug("Unregister region listener."); - if (!regionListeners.remove((DWDPollenflugRegionHandler) childHandler)) { - logger.warn("Tried to remove listener {} but it was not registered. This is probably an error.", - childHandler); - } - } - } - - public void notifyOnUpdate(@Nullable DWDPollenflug newPollenflug) { - if (newPollenflug != null) { - pollenflug = newPollenflug; - updateProperties(newPollenflug.getProperties()); - regionListeners.forEach(listener -> listener.notifyOnUpdate(newPollenflug)); - newPollenflug.getChannelsStateMap().forEach(this::updateState); - } - } - - public @Nullable DWDPollenflug getPollenflug() { - return pollenflug; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal.handler; + +import java.net.SocketTimeoutException; +import java.net.URI; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.HttpResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.util.BufferingResponseListener; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.dwdpollenflug.internal.DWDPollingException; +import org.openhab.binding.dwdpollenflug.internal.config.DWDPollenflugBridgeConfiguration; +import org.openhab.binding.dwdpollenflug.internal.dto.DWDPollenflug; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +/** + * The {@link DWDPollenflugBridgeHandler} is the handler for bridge thing + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugBridgeHandler extends BaseBridgeHandler { + private static final String DWD_URL = "https://opendata.dwd.de/climate_environment/health/alerts/s31fg.json"; + + private final Logger logger = LoggerFactory.getLogger(DWDPollenflugBridgeHandler.class); + + private DWDPollenflugBridgeConfiguration bridgeConfig = new DWDPollenflugBridgeConfiguration(); + private @Nullable ScheduledFuture pollingJob; + private @Nullable DWDPollenflug pollenflug; + private final Set regionListeners = ConcurrentHashMap.newKeySet(); + private final HttpClient client; + private final Gson gson = new Gson(); + + public DWDPollenflugBridgeHandler(Bridge bridge, HttpClient client) { + super(bridge); + this.client = client; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + final DWDPollenflug localPollenflug = pollenflug; + if (localPollenflug != null) { + notifyOnUpdate(localPollenflug); + } + } + } + + @Override + public void initialize() { + logger.debug("Initializing DWD Pollenflug bridge handler"); + bridgeConfig = getConfigAs(DWDPollenflugBridgeConfiguration.class); + + if (bridgeConfig.isValid()) { + updateStatus(ThingStatus.UNKNOWN); + startPolling(); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Refresh interval has to be at least 15 minutes."); + } + } + + @Override + public void dispose() { + logger.debug("Handler disposed."); + stopPolling(); + } + + private void startPolling() { + final ScheduledFuture localPollingJob = this.pollingJob; + if (localPollingJob == null || localPollingJob.isCancelled()) { + logger.debug("Start polling."); + pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, bridgeConfig.refresh, TimeUnit.MINUTES); + } + } + + private void stopPolling() { + final ScheduledFuture localPollingJob = this.pollingJob; + if (localPollingJob != null && !localPollingJob.isCancelled()) { + logger.debug("Stop polling."); + localPollingJob.cancel(true); + pollingJob = null; + } + } + + private void poll() { + logger.debug("Polling"); + requestRefresh().handle((resultPollenflug, pollException) -> { + if (resultPollenflug == null) { + if (pollException == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + pollException.getMessage()); + } + } else { + updateStatus(ThingStatus.ONLINE); + notifyOnUpdate(resultPollenflug); + } + + return null; + }); + } + + private CompletableFuture<@Nullable DWDPollenflug> requestRefresh() { + CompletableFuture<@Nullable DWDPollenflug> f = new CompletableFuture<>(); + Request request = client.newRequest(URI.create(DWD_URL)); + + request.method(HttpMethod.GET).timeout(2000, TimeUnit.SECONDS).send(new BufferingResponseListener() { + @NonNullByDefault({}) + @Override + public void onComplete(Result result) { + final HttpResponse response = (HttpResponse) result.getResponse(); + if (result.getFailure() != null) { + Throwable e = result.getFailure(); + if (e instanceof SocketTimeoutException || e instanceof TimeoutException) { + f.completeExceptionally(new DWDPollingException("Request timeout", e)); + } else { + f.completeExceptionally(new DWDPollingException("Request failed", e)); + } + } else if (response.getStatus() != 200) { + f.completeExceptionally(new DWDPollingException(getContentAsString())); + } else { + try { + DWDPollenflug pollenflugJSON = gson.fromJson(getContentAsString(), DWDPollenflug.class); + f.complete(pollenflugJSON); + } catch (JsonSyntaxException ex2) { + f.completeExceptionally(new DWDPollingException("Parsing of response failed")); + } + } + } + }); + + return f; + } + + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof DWDPollenflugRegionHandler) { + logger.debug("Register region listener."); + final DWDPollenflugRegionHandler regionListener = (DWDPollenflugRegionHandler) childHandler; + if (regionListeners.add(regionListener)) { + final DWDPollenflug localPollenflug = pollenflug; + if (localPollenflug != null) { + regionListener.notifyOnUpdate(localPollenflug); + } + } else { + logger.warn("Tried to add listener {} but it was already present. This is probably an error.", + childHandler); + } + } + } + + @Override + public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof DWDPollenflugRegionHandler) { + logger.debug("Unregister region listener."); + if (!regionListeners.remove((DWDPollenflugRegionHandler) childHandler)) { + logger.warn("Tried to remove listener {} but it was not registered. This is probably an error.", + childHandler); + } + } + } + + public void notifyOnUpdate(@Nullable DWDPollenflug newPollenflug) { + if (newPollenflug != null) { + pollenflug = newPollenflug; + updateProperties(newPollenflug.getProperties()); + regionListeners.forEach(listener -> listener.notifyOnUpdate(newPollenflug)); + newPollenflug.getChannelsStateMap().forEach(this::updateState); + } + } + + public @Nullable DWDPollenflug getPollenflug() { + return pollenflug; + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugRegionHandler.java b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugRegionHandler.java index 1b1949f0eb5c5..a007b988e6712 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugRegionHandler.java +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/java/org/openhab/binding/dwdpollenflug/internal/handler/DWDPollenflugRegionHandler.java @@ -1,112 +1,112 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.dwdpollenflug.internal.handler; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.dwdpollenflug.internal.config.DWDPollenflugRegionConfiguration; -import org.openhab.binding.dwdpollenflug.internal.dto.DWDPollenflug; -import org.openhab.binding.dwdpollenflug.internal.dto.DWDRegion; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link DWDPollenflugRegionHandler} is the handler for bridge thing - * - * @author Johannes Ott - Initial contribution - */ -@NonNullByDefault -public class DWDPollenflugRegionHandler extends BaseThingHandler { - - private final Logger logger = LoggerFactory.getLogger(DWDPollenflugRegionHandler.class); - - private DWDPollenflugRegionConfiguration thingConfig = new DWDPollenflugRegionConfiguration(); - - public DWDPollenflugRegionHandler(Thing thing) { - super(thing); - } - - @Override - public void initialize() { - logger.debug("Initializing DWD Pollenflug region handler"); - thingConfig = getConfigAs(DWDPollenflugRegionConfiguration.class); - - if (thingConfig.isValid()) { - DWDPollenflugBridgeHandler handler = getBridgeHandler(); - if (handler == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge handler missing"); - } else { - updateStatus(ThingStatus.ONLINE); - } - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No valid region id given."); - } - } - - private @Nullable DWDPollenflugBridgeHandler getBridgeHandler() { - Bridge bridge = getBridge(); - if (bridge != null) { - ThingHandler handler = bridge.getHandler(); - if (handler instanceof DWDPollenflugBridgeHandler) { - DWDPollenflugBridgeHandler bridgeHandler = (DWDPollenflugBridgeHandler) handler; - return bridgeHandler; - } - } - - return null; - } - - @Override - public void dispose() { - logger.debug("DWDPollenflug region handler disposes."); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - if (command instanceof RefreshType) { - refresh(); - } - } - - private void refresh() { - DWDPollenflugBridgeHandler handler = getBridgeHandler(); - if (handler != null) { - DWDPollenflug pollenflug = handler.getPollenflug(); - if (pollenflug != null) { - notifyOnUpdate(pollenflug); - } - } - } - - public void notifyOnUpdate(DWDPollenflug pollenflug) { - DWDRegion region = pollenflug.getRegion(thingConfig.regionID); - if (region == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Region not found"); - return; - } - - updateStatus(ThingStatus.ONLINE); - updateProperties(region.getProperties()); - - region.getChannelsStateMap().forEach(this::updateState); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.dwdpollenflug.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.dwdpollenflug.internal.config.DWDPollenflugRegionConfiguration; +import org.openhab.binding.dwdpollenflug.internal.dto.DWDPollenflug; +import org.openhab.binding.dwdpollenflug.internal.dto.DWDRegion; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link DWDPollenflugRegionHandler} is the handler for bridge thing + * + * @author Johannes Ott - Initial contribution + */ +@NonNullByDefault +public class DWDPollenflugRegionHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(DWDPollenflugRegionHandler.class); + + private DWDPollenflugRegionConfiguration thingConfig = new DWDPollenflugRegionConfiguration(); + + public DWDPollenflugRegionHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + logger.debug("Initializing DWD Pollenflug region handler"); + thingConfig = getConfigAs(DWDPollenflugRegionConfiguration.class); + + if (thingConfig.isValid()) { + DWDPollenflugBridgeHandler handler = getBridgeHandler(); + if (handler == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Bridge handler missing"); + } else { + updateStatus(ThingStatus.ONLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No valid region id given."); + } + } + + private @Nullable DWDPollenflugBridgeHandler getBridgeHandler() { + Bridge bridge = getBridge(); + if (bridge != null) { + ThingHandler handler = bridge.getHandler(); + if (handler instanceof DWDPollenflugBridgeHandler) { + DWDPollenflugBridgeHandler bridgeHandler = (DWDPollenflugBridgeHandler) handler; + return bridgeHandler; + } + } + + return null; + } + + @Override + public void dispose() { + logger.debug("DWDPollenflug region handler disposes."); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + refresh(); + } + } + + private void refresh() { + DWDPollenflugBridgeHandler handler = getBridgeHandler(); + if (handler != null) { + DWDPollenflug pollenflug = handler.getPollenflug(); + if (pollenflug != null) { + notifyOnUpdate(pollenflug); + } + } + } + + public void notifyOnUpdate(DWDPollenflug pollenflug) { + DWDRegion region = pollenflug.getRegion(thingConfig.regionID); + if (region == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Region not found"); + return; + } + + updateStatus(ThingStatus.ONLINE); + updateProperties(region.getProperties()); + + region.getChannelsStateMap().forEach(this::updateState); + } +} diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/binding/binding.xml index 8ba0620c7c198..31b817f4ce151 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/binding/binding.xml @@ -1,10 +1,10 @@ - - - - DWD Pollenflug Binding - This is the binding for DWDPollenflug. - Johannes Ott - - + + + + DWD Pollenflug Binding + This is the binding for DWDPollenflug. + Johannes Ott + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/bridge.xml index 68fb42028e654..21de0a4aa54dc 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,51 +1,51 @@ - - - - - - Bridge for accessing pollen count index data of the DWD - - - - - - - - - - - - - 30 - - Time between two API requests in minutes. Minimum 15 minutes. - - - - - - - - Information about data state - - - - - - - - - - - - - - - DateTime - - - - + + + + + + Bridge for accessing pollen count index data of the DWD + + + + + + + + + + + + + 30 + + Time between two API requests in minutes. Minimum 15 minutes. + + + + + + + + Information about data state + + + + + + + + + + + + + + + DateTime + + + + diff --git a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/region.xml b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/region.xml index 7c6fdba3d0e8f..c2a9e43e0dabc 100644 --- a/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/region.xml +++ b/bundles/org.openhab.binding.dwdpollenflug/src/main/resources/ESH-INF/thing/region.xml @@ -1,113 +1,113 @@ - - - - - - - - - - Pollen count index for a region or partregion - - - - - Information for alder - - - - Information for ambrosia - - - - Information for ash tree - - - - Information for birch - - - - Information for grasses - - - - Information for hazel - - - - Information for mugwort - - - - Information for rye - - - - - - - - - - - - The partregion or region that should be reported. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - For each pollen type there are three channels for today, tomorrow and day after tomorrow - - - - - - - - - - - - - - - String - - - - + + + + + + + + + + Pollen count index for a region or partregion + + + + + Information for alder + + + + Information for ambrosia + + + + Information for ash tree + + + + Information for birch + + + + Information for grasses + + + + Information for hazel + + + + Information for mugwort + + + + Information for rye + + + + + + + + + + + + The partregion or region that should be reported. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + For each pollen type there are three channels for today, tomorrow and day after tomorrow + + + + + + + + + + + + + + + String + + + + diff --git a/bundles/org.openhab.binding.dwdunwetter/pom.xml b/bundles/org.openhab.binding.dwdunwetter/pom.xml index 4856a2bd406e0..7ca215409fe23 100644 --- a/bundles/org.openhab.binding.dwdunwetter/pom.xml +++ b/bundles/org.openhab.binding.dwdunwetter/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.dwdunwetter diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/feature/feature.xml b/bundles/org.openhab.binding.dwdunwetter/src/main/feature/feature.xml index 73926267cd318..94b1988e847e6 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.dwdunwetter/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.dwdunwetter/${project.version} + diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/DwdUnwetterBindingConstants.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/DwdUnwetterBindingConstants.java index 76bb37c0572e9..193efd3c34e28 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/DwdUnwetterBindingConstants.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/DwdUnwetterBindingConstants.java @@ -46,5 +46,4 @@ public class DwdUnwetterBindingConstants { public static final String CHANNEL_CEILING = "ceiling"; public static final String CHANNEL_INSTRUCTION = "instruction"; public static final String CHANNEL_URGENCY = "urgency"; - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningCache.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningCache.java index 47497b25e3e77..6b90c8ff4636b 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningCache.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningCache.java @@ -60,5 +60,4 @@ public void deleteOldEntries() { .collect(Collectors.toList()); oldEntries.forEach(idExpiresMap::remove); } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningData.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningData.java index f69884021b5d6..eb2afa2557a16 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningData.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningData.java @@ -181,5 +181,4 @@ public boolean equals(Object obj) { } return true; } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningDataAccess.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningDataAccess.java index 628214f6f0a60..9b3d14d1e241b 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningDataAccess.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningDataAccess.java @@ -65,5 +65,4 @@ public String getDataFromEndpoint(String cellId) { return StringUtils.EMPTY; } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningsData.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningsData.java index 452ff51e227f7..f5f991bccd454 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningsData.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningsData.java @@ -309,5 +309,4 @@ protected void setDataAccess(DwdWarningDataAccess dataAccess) { dataAccessCached = new ExpiringCache<>(Duration.ofMinutes(MIN_REFRESH_WAIT_MINUTES), () -> dataAccess.getDataFromEndpoint("")); } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdXmlTag.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdXmlTag.java index 010aa78e9b105..127ce02791bd3 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdXmlTag.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/DwdXmlTag.java @@ -55,5 +55,4 @@ public static DwdXmlTag getDwdXmlTag(String tag) { return Arrays.asList(DwdXmlTag.values()).stream().filter(t -> StringUtils.equals(t.getTag(), tag)).findFirst() .orElse(UNKNOWN); } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/Severity.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/Severity.java index 3c30efcb1e40b..6fa32919fd642 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/Severity.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/Severity.java @@ -49,5 +49,4 @@ public static Severity getSeverity(String input) { return Arrays.asList(Severity.values()).stream() .filter(sev -> StringUtils.equalsIgnoreCase(input, sev.getText())).findAny().orElse(UNKNOWN); } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/SeverityComparator.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/SeverityComparator.java index 054d56ffdc8c0..6efb210418cc6 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/SeverityComparator.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/SeverityComparator.java @@ -34,5 +34,4 @@ public int compare(DwdWarningData o1, DwdWarningData o2) { } return result; } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/Urgency.java b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/Urgency.java index 90db7d82ac9d9..fbba85862ff46 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/Urgency.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/java/org/openhab/binding/dwdunwetter/internal/data/Urgency.java @@ -41,5 +41,4 @@ public static Urgency getUrgency(String input) { return Arrays.asList(Urgency.values()).stream() .filter(urg -> StringUtils.equalsIgnoreCase(input, urg.getText())).findAny().orElse(UNKNOWN); } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.dwdunwetter/src/main/resources/ESH-INF/thing/thing-types.xml index 5710b40ff2cf5..714e92133f61f 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.dwdunwetter/src/main/resources/ESH-INF/thing/thing-types.xml @@ -10,7 +10,7 @@ - @@ -22,7 +22,7 @@ With the % sign at the end it is possible to query multiple cells at once. For e 1 - @@ -33,7 +33,7 @@ The warnings are sorted by severity first and begin second so the first warning DateTime Timestamp of the last update from the endpoint - + Switch @@ -41,12 +41,12 @@ The warnings are sorted by severity first and begin second so the first warning - + trigger - @@ -71,55 +71,55 @@ This happens after all other channels are populated]]> String Textual description of the warning. - + DateTime Issued Date and Time - + DateTime Start Date and Time for which the warning is valid - + DateTime End Date and Time for which the warning is valid - + String Headline of the warning like "Amtliche Warnung vor FROST" - + String Type of the warning, e.g. FROST - + Number:Length Lower Height above sea level for which the warning is valid - + Number:Length Upper Height above sea level for which the warning is valid - + String Instructions and safety information - + String diff --git a/bundles/org.openhab.binding.dwdunwetter/src/test/java/org/openhab/binding/dwdunwetter/DwdUnwetterHandlerTest.java b/bundles/org.openhab.binding.dwdunwetter/src/test/java/org/openhab/binding/dwdunwetter/DwdUnwetterHandlerTest.java index eded0a5d7a779..ad3cf44ba8f79 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/test/java/org/openhab/binding/dwdunwetter/DwdUnwetterHandlerTest.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/test/java/org/openhab/binding/dwdunwetter/DwdUnwetterHandlerTest.java @@ -91,7 +91,6 @@ public void testInitializeShouldCallTheCallback() { // assert that the (temporary) UNKNOWN status was to the mocked thing first: assertThat(statusInfoCaptor.getAllValues().get(0).getStatus(), is(ThingStatus.UNKNOWN)); - } /** @@ -138,5 +137,4 @@ private String getLabel(NodeList nodeList) { } return null; } - } diff --git a/bundles/org.openhab.binding.dwdunwetter/src/test/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningCacheTest.java b/bundles/org.openhab.binding.dwdunwetter/src/test/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningCacheTest.java index eb02be90dd287..85399a1803395 100644 --- a/bundles/org.openhab.binding.dwdunwetter/src/test/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningCacheTest.java +++ b/bundles/org.openhab.binding.dwdunwetter/src/test/java/org/openhab/binding/dwdunwetter/internal/data/DwdWarningCacheTest.java @@ -54,7 +54,6 @@ public void testDeleteOldEntries() { assertThat(cache.addEntry(data), is(false)); cache.deleteOldEntries(); assertThat(cache.addEntry(data), is(true)); - } private DwdWarningData createData(String id, long secondsBeforeNow) { diff --git a/bundles/org.openhab.binding.ecobee/README.md b/bundles/org.openhab.binding.ecobee/README.md index 20d0ed2e698e7..edac7608e1076 100644 --- a/bundles/org.openhab.binding.ecobee/README.md +++ b/bundles/org.openhab.binding.ecobee/README.md @@ -29,10 +29,32 @@ thermostat will be added to the inbox. The binding will detect the capabilities (e.g. temperature, humidity, occupancy) supported by the sensor, and then dynamically create channels for those capabilities. -## Authorization +## Getting Started -After you have installed the binding, and have created the Account thing with a valid API key, -the binding will try to get information about your thermostats from the Ecobee web service. +### Getting an API Key + +Before you can start using the Ecobee binding, you need to get an API key. +The following steps describe what you need to do. + +1. First you need to register your thermostat(s) with Ecobee. +To complete this step, follow the directions in your Ecobee set up documentation. + +2. Once the thermostats are registered, the next step is to sign up as a developer. +Do this from the Ecobee [developer portal](https://www.ecobee.com/developers/). + +3. Now that you are set up as an Ecobee developer, login to your Ecobee [web portal](https://www.ecobee.com/). +Once logged in, select the **Developer** option from the menu. +If you don't see the **Developer** option on the menu, then something went wrong with the previous step. + +4. Finally, create a new application. +Give the application a name and fill in the application summary. +Select the **Ecobee PIN** Authorization Method, then press **Create**. +You now should see the **API key** for the application you just created. + +### Authorization + +After you have installed the binding, you can create the Account thing using the API key you just created. +Once the Account thing is created, the binding will try to get information about your thermostats from the Ecobee web service. When this happens, the binding will determine that it has not yet been authorized by the Ecobee web service. At this point the binding will retrieve a four-character PIN code from the Ecobee web service. diff --git a/bundles/org.openhab.binding.ecobee/pom.xml b/bundles/org.openhab.binding.ecobee/pom.xml index ee082c2f2dfd1..72c98838edf1a 100644 --- a/bundles/org.openhab.binding.ecobee/pom.xml +++ b/bundles/org.openhab.binding.ecobee/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.ecobee diff --git a/bundles/org.openhab.binding.ecobee/src/main/feature/feature.xml b/bundles/org.openhab.binding.ecobee/src/main/feature/feature.xml index baef6d6d391f3..00d29280f2150 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.ecobee/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.ecobee/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.ecobee/${project.version} + diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/action/EcobeeActions.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/action/EcobeeActions.java index fb14cdb0ce5d4..0cf808fe64024 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/action/EcobeeActions.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/action/EcobeeActions.java @@ -164,7 +164,8 @@ public static boolean acknowledge(@Nullable ThingActions actions, @Nullable Stri public static boolean controlPlug(@Nullable ThingActions actions, @Nullable String plugName, @Nullable String plugState, @Nullable Date startDateTime, @Nullable Date endDateTime, @Nullable String holdType, @Nullable Number holdHours) { - return invokeMethodOf(actions).controlPlug(plugName, plugState, startDateTime, endDateTime, holdType, holdHours); + return invokeMethodOf(actions).controlPlug(plugName, plugState, startDateTime, endDateTime, holdType, + holdHours); } /** diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/EcobeeBindingConstants.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/EcobeeBindingConstants.java index d204811444332..b020dc8dc572d 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/EcobeeBindingConstants.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/EcobeeBindingConstants.java @@ -20,6 +20,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.openhab.binding.ecobee.internal.dto.thermostat.AlertDTO; import org.openhab.binding.ecobee.internal.dto.thermostat.EventDTO; import org.openhab.binding.ecobee.internal.dto.thermostat.HouseDetailsDTO; @@ -376,6 +377,12 @@ public class EcobeeBindingConstants { public static final String CH_SENSOR_CODE = "code"; public static final String CH_SENSOR_IN_USE = "inUse"; + // Channel Type UIDs for dynamically created sensor channels + public static final ChannelTypeUID CHANNELTYPEUID_TEMPERATURE = new ChannelTypeUID(BINDING_ID, "sensorTemperature"); + public static final ChannelTypeUID CHANNELTYPEUID_HUMIDITY = new ChannelTypeUID(BINDING_ID, "sensorHumidity"); + public static final ChannelTypeUID CHANNELTYPEUID_OCCUPANCY = new ChannelTypeUID(BINDING_ID, "sensorOccupancy"); + public static final ChannelTypeUID CHANNELTYPEUID_GENERIC = new ChannelTypeUID(BINDING_ID, "sensorGeneric"); + public static final AlertDTO EMPTY_ALERT = new AlertDTO(); public static final EventDTO EMPTY_EVENT = new EventDTO(); public static final LocationDTO EMPTY_LOCATION = new LocationDTO(); diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java index 6a69d19ef8362..de068f7a3093d 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/api/EcobeeApi.java @@ -20,6 +20,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; import java.util.List; import java.util.Properties; import java.util.Set; @@ -77,6 +78,7 @@ public class EcobeeApi implements AccessTokenRefreshListener { // These errors from the API will require an Ecobee authorization private static final int ECOBEE_TOKEN_EXPIRED = 14; private static final int ECOBEE_DEAUTHORIZED_TOKEN = 16; + private static final int TOKEN_EXPIRES_IN_BUFFER_SECONDS = 120; public static final Properties HTTP_HEADERS; static { @@ -101,7 +103,7 @@ public static Gson getGson() { private @NonNullByDefault({}) OAuthClientService oAuthClientService; private @NonNullByDefault({}) EcobeeAuth ecobeeAuth; - private String accessToken = ""; + private @Nullable AccessTokenResponse accessTokenResponse; public EcobeeApi(final EcobeeAccountBridgeHandler bridgeHandler, final String apiKey, final int apiTimeout, org.eclipse.smarthome.core.auth.client.oauth2.OAuthFactory oAuthFactory, HttpClient httpClient) { @@ -145,10 +147,13 @@ public void closeOAuthClientService() { private boolean isAuthorized() { boolean isAuthorized = false; try { - AccessTokenResponse accessTokenResponse = oAuthClientService.getAccessTokenResponse(); - if (accessTokenResponse != null) { - logger.trace("API: Got AccessTokenResponse from OAuth service: {}", accessTokenResponse); - accessToken = accessTokenResponse.getAccessToken(); + AccessTokenResponse localAccessTokenResponse = oAuthClientService.getAccessTokenResponse(); + if (localAccessTokenResponse != null) { + logger.trace("API: Got AccessTokenResponse from OAuth service: {}", localAccessTokenResponse); + if (localAccessTokenResponse.isExpired(LocalDateTime.now(), TOKEN_EXPIRES_IN_BUFFER_SECONDS)) { + logger.debug("API: Token is expiring soon. Refresh it now"); + localAccessTokenResponse = oAuthClientService.refreshToken(); + } ecobeeAuth.setState(EcobeeAuthState.COMPLETE); isAuthorized = true; } else { @@ -157,6 +162,7 @@ private boolean isAuthorized() { ecobeeAuth.setState(EcobeeAuthState.NEED_PIN); } } + accessTokenResponse = localAccessTokenResponse; ecobeeAuth.doAuthorization(); } catch (OAuthException | IOException | RuntimeException e) { logger.info("API: Got exception trying to get access token from OAuth service", e); @@ -173,7 +179,6 @@ private boolean isAuthorized() { @Override public void onAccessTokenResponse(AccessTokenResponse accessTokenResponse) { - accessToken = accessTokenResponse.getAccessToken(); } public @Nullable SummaryResponseDTO performThermostatSummaryQuery() { @@ -257,6 +262,8 @@ private String buildQueryUrl(String baseUrl, String requestJson) throws Unsuppor logger.trace("API: Response took {} msec: {}", System.currentTimeMillis() - startTime, response); } catch (IOException e) { logIOException(e); + } catch (EcobeeAuthException e) { + logger.info("API: Unable to execute GET: {}", e.getMessage()); } return response; } @@ -276,6 +283,8 @@ private boolean executePost(String url, String json) { } } catch (IOException e) { logIOException(e); + } catch (EcobeeAuthException e) { + logger.info("API: Unable to execute POST: {}", e.getMessage()); } return false; } @@ -306,21 +315,31 @@ private boolean isSuccess(@Nullable AbstractResponseDTO response) { } else if (response.status.code.intValue() != 0) { logger.info("API: Ecobee API returned unsuccessful status: code={}, message={}", response.status.code, response.status.message); - // The following error indicate that the Ecobee PIN authorization - // process needs to be restarted - if (response.status.code == ECOBEE_TOKEN_EXPIRED || response.status.code == ECOBEE_DEAUTHORIZED_TOKEN) { + if (response.status.code == ECOBEE_DEAUTHORIZED_TOKEN) { + // Token has been deauthorized, so restart the authorization process from the beginning + logger.warn("API: Reset OAuth Client Service due to deauthorized token"); deleteOAuthClientService(); createOAuthClientService(); + } else if (response.status.code == ECOBEE_TOKEN_EXPIRED) { + // Check isAuthorized again to see if we can get a valid token + logger.info("API: Unable to complete API call because token is expired"); + if (!isAuthorized()) { + logger.warn("API: isAuthorized was NOT successful on second try"); + } } success = false; } return success; } - private Properties setHeaders() { + private Properties setHeaders() throws EcobeeAuthException { + AccessTokenResponse atr = accessTokenResponse; + if (atr == null) { + throw new EcobeeAuthException("Can not set auth header because access token is null"); + } Properties headers = new Properties(); headers.putAll(HTTP_HEADERS); - headers.put("Authorization", "Bearer " + accessToken); + headers.put("Authorization", "Bearer " + atr.getAccessToken()); return headers; } } diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/discovery/SensorDiscoveryService.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/discovery/SensorDiscoveryService.java index c8f73060735fb..187d096786df1 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/discovery/SensorDiscoveryService.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/discovery/SensorDiscoveryService.java @@ -117,7 +117,8 @@ private synchronized void discoverSensors() { private DiscoveryResult createDiscoveryResult(ThingUID sensorUID, ThingUID bridgeUID, RemoteSensorDTO sensor) { Map properties = new HashMap<>(2); properties.put(CONFIG_SENSOR_ID, sensor.id); - return DiscoveryResultBuilder.create(sensorUID).withProperties(properties).withRepresentationProperty(sensor.id) - .withBridge(bridgeUID).withLabel(buildLabel(sensor.name)).build(); + return DiscoveryResultBuilder.create(sensorUID).withProperties(properties) + .withRepresentationProperty(CONFIG_SENSOR_ID).withBridge(bridgeUID).withLabel(buildLabel(sensor.name)) + .build(); } } diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/discovery/ThermostatDiscoveryService.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/discovery/ThermostatDiscoveryService.java index 78eb02083df99..b91e7bdcf86dd 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/discovery/ThermostatDiscoveryService.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/discovery/ThermostatDiscoveryService.java @@ -126,7 +126,7 @@ private DiscoveryResult createDiscoveryResult(ThingUID thermostatUID, String ide Map properties = new HashMap<>(2); properties.put(CONFIG_THERMOSTAT_ID, identifier); return DiscoveryResultBuilder.create(thermostatUID).withProperties(properties) - .withRepresentationProperty(identifier).withBridge(bridgeHandler.getThing().getUID()) + .withRepresentationProperty(CONFIG_THERMOSTAT_ID).withBridge(bridgeHandler.getThing().getUID()) .withLabel(buildLabel(name)).build(); } } diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/EquipmentSettingDTO.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/EquipmentSettingDTO.java index 94ea3d79a9e79..781a5050358ef 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/EquipmentSettingDTO.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/dto/thermostat/EquipmentSettingDTO.java @@ -67,5 +67,4 @@ public class EquipmentSettingDTO { * technician/contractor assoicated with the thermostat. */ public Boolean remindTechnician; - } diff --git a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeSensorThingHandler.java b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeSensorThingHandler.java index 659a1e69af847..575673c5c11e8 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeSensorThingHandler.java +++ b/bundles/org.openhab.binding.ecobee/src/main/java/org/openhab/binding/ecobee/internal/handler/EcobeeSensorThingHandler.java @@ -29,6 +29,7 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; @@ -119,8 +120,10 @@ private void updateCapabilityChannels(RemoteSensorCapabilityDTO capability) { logger.debug("SensorThing: Create channel '{}'", uid); ThingBuilder thingBuilder; thingBuilder = editThing(); - thingBuilder.withChannel(ChannelBuilder.create(uid, getChannelType(capability.type)) - .withLabel("Sensor " + WordUtils.capitalize(capability.type)).build()); + channel = ChannelBuilder.create(uid, getAcceptedItemType(capability.type)) + .withLabel("Sensor " + WordUtils.capitalize(capability.type)) + .withType(getChannelTypeUID(capability.type)).build(); + thingBuilder.withChannel(channel); updateThing(thingBuilder.build()); } logger.trace("Capability '{}' has type '{}' with value '{}'", capability.id, capability.type, capability.value); @@ -128,27 +131,50 @@ private void updateCapabilityChannels(RemoteSensorCapabilityDTO capability) { } // adc, co2, dryContact, humidity, temperature, occupancy, unknown. - private String getChannelType(String capabilityType) { - String type; + private String getAcceptedItemType(String capabilityType) { + String acceptedItemType; switch (capabilityType) { case CAPABILITY_TEMPERATURE: - type = "Number:Temperature"; + acceptedItemType = "Number:Temperature"; break; case CAPABILITY_HUMIDITY: - type = "Number:Dimensionless"; + acceptedItemType = "Number:Dimensionless"; break; case CAPABILITY_OCCUPANCY: - type = "Switch"; + acceptedItemType = "Switch"; break; case CAPABILITY_ADC: case CAPABILITY_CO2: case CAPABILITY_DRY_CONTACT: case CAPABILITY_UNKNOWN: default: - type = "String"; + acceptedItemType = "String"; break; } - return type; + return acceptedItemType; + } + + private ChannelTypeUID getChannelTypeUID(String capabilityType) { + ChannelTypeUID channelTypeUID; + switch (capabilityType) { + case CAPABILITY_TEMPERATURE: + channelTypeUID = CHANNELTYPEUID_TEMPERATURE; + break; + case CAPABILITY_HUMIDITY: + channelTypeUID = CHANNELTYPEUID_HUMIDITY; + break; + case CAPABILITY_OCCUPANCY: + channelTypeUID = CHANNELTYPEUID_OCCUPANCY; + break; + case CAPABILITY_ADC: + case CAPABILITY_CO2: + case CAPABILITY_DRY_CONTACT: + case CAPABILITY_UNKNOWN: + default: + channelTypeUID = CHANNELTYPEUID_GENERIC; + break; + } + return channelTypeUID; } private void updateCapabilityState(String capabilityType, String value) { diff --git a/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/binding/binding.xml index 16fdb80327248..0c3b0ac36ce43 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Ecobee Binding diff --git a/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/config/config.xml index a24882469e1dd..006c43e434597 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/config/config.xml @@ -1,4 +1,5 @@ - diff --git a/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/thing/thing-types.xml index b71d5a78259f8..c112b8e278dfb 100644 --- a/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.ecobee/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -7,13 +8,13 @@ Represents an account at Ecobee - + - + An Ecobee thermostat @@ -85,1641 +86,1648 @@ - + thermostatId + - - - - - - - - - + + + + + + + + + String - + String - + String - + Switch - + String - + String - + String - + DateTime - + DateTime - + - + String - + - + String - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + String - + Switch - + DateTime - + DateTime - + DateTime - + DateTime - + DateTime - + String - + Number - + Number:Temperature - + Number:Dimensionless - + Number:Temperature - + Number - + Number:Temperature - + Number:Temperature - + Number:Dimensionless - + Number:Dimensionless - + String - + Number:Temperature - + Number:Temperature - + Number:Temperature - + Number:Temperature - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + String - + String - + Switch - + Number - + String - + String - + Number - + Switch - + String - + Number:Temperature - + Switch - + Number:Temperature - + Switch - + Number - + Number - + Number - + Number - + Number - + Number - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + String - + String - + String - + Number - + Number - + Number - + Number - + Number - + Number - + Number:Temperature - + Number - + Number - + Number - + Number - + Switch - + Switch - + Number - + Number - + Number - + String - + Switch - + String - + Number - + Switch - + Number - + Switch - + Switch - + Number:Temperature - + Number:Temperature - + Number:Temperature - + Number:Temperature - + Number:Temperature - + Number:Temperature - + Number:Temperature - + Number:Temperature - + String - + Number - + Number - + Number:Temperature - + Number:Temperature - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + String - + Switch - + Switch - + Number - + Number - + Number:Dimensionless - + Number:Dimensionless - + Switch - + Switch - + Switch - + Switch - + Switch - + Switch - + Number - + Switch - + Switch - + Number - + Number - + Number - + Number - + Number - + Switch - + Switch - + Switch - + Switch - + String - + Switch - + String - + Switch - + Switch - + Switch - + Switch - + Switch - + String - + String - + Number - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + String - + String - + String - + String - + String - + Number - + String - + Switch - + String - + Switch - + Switch - + Switch - + String - + Switch - + String - + String - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + String - + String - + Switch - + String - + String - + String - + String - + String - + Switch - + Switch - + Switch - + Number:Temperature - + Number:Temperature - + String - + String - + Number - + Switch - + Switch - + Number - + Number - + Switch - + Number - + Number - + Switch - + Switch - + Number - + Number - + String - + - + String - + - - + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + DateTime - + String - + Number - + String - + DateTime - + String - + Number:Temperature - + Number:Pressure - + Number:Dimensionless - + Number:Temperature - + Number - + Number:Speed - + Number:Speed - + String - + Number:Angle - + Number:Dimensionless - + Number:Temperature - + Number:Temperature - + Number - + String - + - - - - - - - - - - + + + + + + + + + + Number - + String - + Switch - + String - + String - + String - + String - + String - + String - + Location - + - - - - - - - + + + + + + + String - + Number - + Number - + Number - + Number - + Number - + Number - + - - - - - - - - + + + + + + + + String - + String - + String - + String - + String - + String - + Switch - + Switch - + - - - - - - - - - - + + + + + + + + + + String - + String - + String - + String - + String - + String - + String - + String - + String - + String - + - + An Ecobee remote sensor - - - - - + + + + + - + sensorId + String - + String - + String - + String - + Switch - + Number:Temperature - + Number:Dimensionless - + Switch - + + + + String + + diff --git a/bundles/org.openhab.binding.elerotransmitterstick/pom.xml b/bundles/org.openhab.binding.elerotransmitterstick/pom.xml index d18d3bcd8a372..8f59220d3697f 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/pom.xml +++ b/bundles/org.openhab.binding.elerotransmitterstick/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.elerotransmitterstick diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/feature/feature.xml b/bundles/org.openhab.binding.elerotransmitterstick/src/main/feature/feature.xml index 1c83b9aa29f8c..29a143e113289 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.elerotransmitterstick/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.elerotransmitterstick/${project.version} + diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/EleroTransmitterStickHandlerFactory.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/EleroTransmitterStickHandlerFactory.java index 88f222040fb40..d8654e92da44e 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/EleroTransmitterStickHandlerFactory.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/EleroTransmitterStickHandlerFactory.java @@ -14,12 +14,16 @@ import static org.openhab.binding.elerotransmitterstick.internal.EleroTransmitterStickBindingConstants.*; +import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.Hashtable; import java.util.Map; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; @@ -28,11 +32,14 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.elerotransmitterstick.internal.discovery.EleroChannelDiscoveryService; import org.openhab.binding.elerotransmitterstick.internal.handler.EleroChannelHandler; import org.openhab.binding.elerotransmitterstick.internal.handler.EleroTransmitterStickHandler; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link EleroTransmitterStickHandlerFactory} is responsible for creating things and thing @@ -40,16 +47,21 @@ * * @author Volker Bier - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.elerotransmitterstick") public class EleroTransmitterStickHandlerFactory extends BaseThingHandlerFactory { - private static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>(); - static { - SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_STICK); - SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_ELERO_CHANNEL); - } + private static final Set SUPPORTED_THING_TYPES_UIDS = Collections + .unmodifiableSet(Stream.of(THING_TYPE_STICK, THING_TYPE_ELERO_CHANNEL).collect(Collectors.toSet())); + + private final Map> discoveryServiceRegs = new HashMap<>(); - private Map> discoveryServiceRegs = new HashMap<>(); + private final SerialPortManager serialPortManager; + + @Activate + public EleroTransmitterStickHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -57,11 +69,12 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(THING_TYPE_STICK)) { - EleroTransmitterStickHandler bridgeHandler = new EleroTransmitterStickHandler((Bridge) thing); + EleroTransmitterStickHandler bridgeHandler = new EleroTransmitterStickHandler((Bridge) thing, + serialPortManager); EleroChannelDiscoveryService discoveryService = new EleroChannelDiscoveryService(bridgeHandler); discoveryServiceRegs.put(bridgeHandler.getThing().getUID(), bundleContext diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/handler/EleroTransmitterStickHandler.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/handler/EleroTransmitterStickHandler.java index dc6be5eb58928..250569248240c 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/handler/EleroTransmitterStickHandler.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/handler/EleroTransmitterStickHandler.java @@ -19,6 +19,7 @@ import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.thing.binding.BridgeHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.elerotransmitterstick.internal.config.EleroTransmitterStickConfig; import org.openhab.binding.elerotransmitterstick.internal.stick.TransmitterStick; import org.openhab.binding.elerotransmitterstick.internal.stick.TransmitterStick.StickListener; @@ -29,10 +30,12 @@ * @author Volker Bier - Initial contribution */ public class EleroTransmitterStickHandler extends BaseBridgeHandler implements BridgeHandler { - private TransmitterStick stick; + private final SerialPortManager serialPortManager; + private final TransmitterStick stick; - public EleroTransmitterStickHandler(Bridge bridge) { + public EleroTransmitterStickHandler(Bridge bridge, SerialPortManager serialPortManager) { super(bridge); + this.serialPortManager = serialPortManager; stick = new TransmitterStick(new StickListener() { @Override @@ -62,7 +65,7 @@ public void dispose() { public void initialize() { updateStatus(ThingStatus.UNKNOWN); - stick.initialize(getConfig().as(EleroTransmitterStickConfig.class), scheduler); + stick.initialize(getConfig().as(EleroTransmitterStickConfig.class), scheduler, serialPortManager); } public TransmitterStick getStick() { diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/CommandPacket.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/CommandPacket.java index 1b07d71e0c706..737375c2db90f 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/CommandPacket.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/CommandPacket.java @@ -58,5 +58,4 @@ private byte checksum(byte[] data) { public String toString() { return HexUtils.bytesToHex(data); } - } diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/DelayedCommand.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/DelayedCommand.java index d33e1af2f3392..cfe19e7724120 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/DelayedCommand.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/DelayedCommand.java @@ -47,5 +47,4 @@ public long getDelay(TimeUnit unit) { public String toString() { return super.toString() + " and delay " + getDelay(TimeUnit.MILLISECONDS); } - } diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/Response.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/Response.java index 119a4a9c8cbbb..41a285367bdde 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/Response.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/Response.java @@ -50,5 +50,4 @@ public ResponseStatus getStatus() { public String toString() { return status + " for channels " + Arrays.toString(channels); } - } diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/ResponseUtil.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/ResponseUtil.java index b853f5ee921d2..a3ee0c6f807c4 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/ResponseUtil.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/ResponseUtil.java @@ -52,5 +52,4 @@ private static int[] getChannelIds(byte upperChannelByte, byte lowerChannelByte) return Arrays.copyOfRange(result, 0, idx); } - } diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/SerialConnection.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/SerialConnection.java index a189e51f47cd6..2bbf2266433b6 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/SerialConnection.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/SerialConnection.java @@ -14,20 +14,20 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.List; import java.util.TooManyListenersException; import org.apache.commons.lang.ArrayUtils; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * @author Volker Bier - Initial contribution */ @@ -37,11 +37,13 @@ public class SerialConnection { private SerialPort serialPort; private boolean open; private String portName; - private final ArrayList bytes = new ArrayList<>(); + private final List bytes = new ArrayList<>(); private Response response = null; + private final SerialPortManager serialPortManager; - public SerialConnection(String portName) { + public SerialConnection(String portName, SerialPortManager serialPortManager) { this.portName = portName; + this.serialPortManager = serialPortManager; } public synchronized void open() throws ConnectException { @@ -49,10 +51,12 @@ public synchronized void open() throws ConnectException { if (!open) { logger.debug("Trying to open serial connection to port {}...", portName); - CommPortIdentifier portIdentifier; + SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(portName); + if (portIdentifier == null) { + throw new ConnectException("No such port: " + portName); + } try { - portIdentifier = CommPortIdentifier.getPortIdentifier(portName); serialPort = portIdentifier.open("openhab", 3000); open = true; logger.debug("Serial connection to port {} opened.", portName); @@ -79,7 +83,7 @@ public void serialEvent(SerialPortEvent event) { throw new ConnectException(ex); } } - } catch (NoSuchPortException | PortInUseException ex) { + } catch (PortInUseException ex) { throw new ConnectException(ex); } } @@ -203,5 +207,4 @@ private void analyzeBuffer() { } } } - } diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/TransmitterStick.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/TransmitterStick.java index bdf6521b893f6..f8121bd04fe3b 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/TransmitterStick.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/TransmitterStick.java @@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.elerotransmitterstick.internal.config.EleroTransmitterStickConfig; import org.openhab.binding.elerotransmitterstick.internal.handler.StatusListener; import org.slf4j.Logger; @@ -42,15 +43,18 @@ public class TransmitterStick { private final StickListener listener; private EleroTransmitterStickConfig config; + private SerialPortManager serialPortManager; private CommandWorker worker; public TransmitterStick(StickListener l) { listener = l; } - public synchronized void initialize(EleroTransmitterStickConfig stickConfig, ScheduledExecutorService scheduler) { + public synchronized void initialize(EleroTransmitterStickConfig stickConfig, ScheduledExecutorService scheduler, + SerialPortManager serialPortManager) { logger.debug("Initializing Transmitter Stick..."); config = stickConfig; + this.serialPortManager = serialPortManager; worker = new CommandWorker(); scheduler.schedule(worker, 0, TimeUnit.MILLISECONDS); logger.debug("Transmitter Stick initialized, worker running."); @@ -206,7 +210,7 @@ public boolean add(Command e) { }; CommandWorker() { - connection = new SerialConnection(config.portName); + connection = new SerialConnection(config.portName, serialPortManager); updateInterval = config.updateInterval; } diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.elerotransmitterstick/src/main/resources/ESH-INF/thing/thing-types.xml index 39adb39515cf2..2a1f8c04ab6a9 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/resources/ESH-INF/thing/thing-types.xml @@ -13,10 +13,12 @@ The name of the port to which the Elero Transmitter Stick is connected. serial-port + false - The number of seconds to wait before requesting the status of the elero channels from the Elero Transmitter Stick. + The number of seconds to wait before requesting the status of the elero channels from the Elero + Transmitter Stick. 30 @@ -24,15 +26,15 @@ - + One of the 15 elero channels available on an Elero Transmitter Stick. - - + + @@ -48,7 +50,8 @@ Rollershutter - Allows to control the devices connected to this elero channel or group by sending UP, DOWN, STOP commands. + Allows to control the devices connected to this elero channel or group by sending UP, DOWN, STOP + commands. @@ -56,7 +59,7 @@ String Read only channel providing the current status of this elero channel or group. - + diff --git a/bundles/org.openhab.binding.energenie/.classpath b/bundles/org.openhab.binding.energenie/.classpath new file mode 100644 index 0000000000000..a5d95095ccaaf --- /dev/null +++ b/bundles/org.openhab.binding.energenie/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.energenie/.project b/bundles/org.openhab.binding.energenie/.project new file mode 100644 index 0000000000000..32000eb2789d5 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/.project @@ -0,0 +1,23 @@ + + + org.openhab.binding.energenie + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.energenie/NOTICE b/bundles/org.openhab.binding.energenie/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.energenie/README.md b/bundles/org.openhab.binding.energenie/README.md new file mode 100644 index 0000000000000..602843cbb12fd --- /dev/null +++ b/bundles/org.openhab.binding.energenie/README.md @@ -0,0 +1,95 @@ +# Gembird energenie Binding + +This binding integrates the Gembird energenie range of power extenders by using the Energenie Data Exchange Protocol and power reading devices through HTTP interface. + + +## Supported Things + +The Binding supports PM2-LAN, PMS-LAN, PMS2-LAN or PMS-WLAN power extenders as well as PWM-LAN power measurement devices. + +## Discovery + +Gembird energenie devices don't support autodiscovery. +All Things need to be created manually either in PaperUI or within Things files. + +## Binding Configuration + +The Binding does not need any specific configuration + +## Thing Configuration + +The device requires the IP-address and a password as a configuration value in order for the binding to know where to access it and to login to the device. + +| Parameter | Description | +|-----------|------------------------------------------------------| +| host | IP-Address of energenie device | +| password | Password to access energenie device, defaults to "1" | + +## Channels + +The following channels are supported by PM2-LAN, PMS-LAN, PMS2-LAN or PMS-WLAN devices + +| channel | type | description | +|----------|--------|----------------------------------------------------| +| socket1 | Switch | This is the control channel for the first socket | +| socket2 | Switch | This is the control channel for the second socket | +| socket3 | Switch | This is the control channel for the third socket | +| socket4 | Switch | This is the control channel for the fourth socket | + +PWM-LAN devices support the following channels + +| channel | type | description | +|----------|--------------------------|------------------------------------------| +| voltage | Number:ElectricPotential | Channel for output voltage measurement | +| current | Number:ElectricCurrent | Channel for output current measurement | +| power | Number:Power | Channel for output power measurement | +| energy | Number:Energy | channel for output energy measurement | + +## Full Example + +Things + +``` +Thing energenie:pm2lan:pm2lan [ host="xxx.xxx.xxx.xxx", password="your password" ] +Thing energenie:pmslan:pmslan [ host="xxx.xxx.xxx.xxx", password="your password" ] +Thing energenie:pms2lan:pms2lan [ host="xxx.xxx.xxx.xxx", password="your password" ] +Thing energenie:pmswlan:pmswlan [ host="xxx.xxx.xxx.xxx", password="your password" ] +Thing energenie:pwmlan:pwmlan [ host="xxx.xxx.xxx.xxx", password="your password" ] +``` + +Items + +``` +//Power extenders +Switch Socket1 { channel="energenie:pm2lan:pm2lan:socket1" } +Switch Socket2 { channel="energenie:pm2lan:pm2lan:socket2" } +Switch Socket3 { channel="energenie:pm2lan:pm2lan:socket3" } +Switch Socket4 { channel="energenie:pm2lan:pm2lan:socket4" } + +//Power measurement +Number Voltage { channel="energenie:pwmlan:pwmlan:voltage" } +Number Current { channel="energenie:pwmlan:pwmlan:current" } +Number Power { channel="energenie:pwmlan:pwmlan:power" } +Number Energy { channel="energenie:pwmlan:pwmlan:energy" } +``` + +Sitemap + +``` +sitemap energenie label="Energenie Devices" +{ + Frame { + // Power extenders + Switch item=Socket1 + Switch item=Socket2 + Switch item=Socket3 + Switch item=Socket4 + + // Power measurement + Number item=Voltage + Number item=Current + Number item=Power + Number item=Energy + } +} +``` diff --git a/bundles/org.openhab.binding.energenie/pom.xml b/bundles/org.openhab.binding.energenie/pom.xml new file mode 100644 index 0000000000000..0cabd947bc067 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + + + org.openhab.binding.energenie + + openHAB Add-ons :: Bundles :: Energenie Binding + + diff --git a/bundles/org.openhab.binding.energenie/src/main/feature/feature.xml b/bundles/org.openhab.binding.energenie/src/main/feature/feature.xml new file mode 100644 index 0000000000000..9c09c9c1b6f01 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.energenie/${project.version} + + diff --git a/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieBindingConstants.java b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieBindingConstants.java new file mode 100644 index 0000000000000..eaeed1f30bdd5 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieBindingConstants.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energenie.internal; + +import java.util.Collections; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link EnergenieBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Hans-Jörg Merk - Initial contribution + */ +@NonNullByDefault +public class EnergenieBindingConstants { + + private static final String BINDING_ID = "energenie"; + + public static final int TCP_PORT = 5000; + + public static final int STATCRYP_LEN = 4; + public static final int CTRLCRYP_LEN = 4; + public static final int KEY_LEN = 8; + public static final int TASK_LEN = 4; + public static final int SOLUTION_LEN = 4; + + public static final String STATE_ON = "0x11"; + public static final String STATE_ON_NO_VOLTAGE = "0x12"; + public static final String STATE_OFF = "0x22"; + public static final String STATE_OFF_NO_VOLTAGE = "0x21"; + + public static final String V21_STATE_ON = "0x41"; + public static final String V21_STATE_OFF = "0x82"; + + public static final String WLAN_STATE_ON = "0x51"; + public static final String WLAN_STATE_OFF = "0x92"; + + public static final byte SWITCH_ON = 0x01; + public static final byte SWITCH_OFF = 0x02; + public static final byte DONT_SWITCH = 0x04; + + public static final int SOCKET_COUNT = 4; // AC power sockets, not network ones + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_PM2LAN = new ThingTypeUID(BINDING_ID, "pm2lan"); + public static final ThingTypeUID THING_TYPE_PMSLAN = new ThingTypeUID(BINDING_ID, "pmslan"); + public static final ThingTypeUID THING_TYPE_PMS2LAN = new ThingTypeUID(BINDING_ID, "pms2lan"); + public static final ThingTypeUID THING_TYPE_PMSWLAN = new ThingTypeUID(BINDING_ID, "pmswlan"); + public static final ThingTypeUID THING_TYPE_PWMLAN = new ThingTypeUID(BINDING_ID, "pwmlan"); + + // List of all Channel ids + public static final Pattern CHANNEL_SOCKET = Pattern.compile("socket(\\d)"); + + public static final String VOLTAGE = "voltage"; + public static final String CURRENT = "current"; + public static final String POWER = "power"; + public static final String ENERGY = "energy"; + + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( + Stream.of(THING_TYPE_PM2LAN, THING_TYPE_PMSLAN, THING_TYPE_PMS2LAN, THING_TYPE_PMSLAN, THING_TYPE_PWMLAN) + .collect(Collectors.toSet())); +} diff --git a/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieHandlerFactory.java b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieHandlerFactory.java new file mode 100644 index 0000000000000..9bb7af2ea4979 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieHandlerFactory.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energenie.internal; + +import static org.openhab.binding.energenie.internal.EnergenieBindingConstants.*; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.energenie.internal.handler.EnergenieHandler; +import org.openhab.binding.energenie.internal.handler.EnergeniePWMHandler; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link EnergenieHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Hans-Jörg Merk - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.energenie", service = ThingHandlerFactory.class) +public class EnergenieHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = EnergenieBindingConstants.SUPPORTED_THING_TYPES_UIDS; + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_PMSLAN.equals(thingTypeUID)) { + return new EnergenieHandler(thing, EnergenieProtocolEnum.V20); + } else if (THING_TYPE_PM2LAN.equals(thingTypeUID)) { + return new EnergenieHandler(thing, EnergenieProtocolEnum.V20); + } else if (THING_TYPE_PMS2LAN.equals(thingTypeUID)) { + return new EnergenieHandler(thing, EnergenieProtocolEnum.V21); + } else if (THING_TYPE_PMSWLAN.equals(thingTypeUID)) { + return new EnergenieHandler(thing, EnergenieProtocolEnum.WLAN); + } else if (THING_TYPE_PWMLAN.equals(thingTypeUID)) { + return new EnergeniePWMHandler(thing); + } + return null; + } +} diff --git a/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergeniePWMStateEnum.java b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergeniePWMStateEnum.java new file mode 100644 index 0000000000000..12f17c89001b7 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergeniePWMStateEnum.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energenie.internal; + +import javax.measure.Unit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EnergeniePWMStateEnum} contains informations for parsing the readState() result. + * + * @author Hans-Jörg Merk - Initial contribution + */ + +@NonNullByDefault +public enum EnergeniePWMStateEnum { + VOLTAGE("var V = ", 9, 20, 10, SmartHomeUnits.VOLT), + CURRENT("var V = ", 9, 20, 100, SmartHomeUnits.AMPERE), + POWER("var P=", 6, 20, 466, SmartHomeUnits.WATT), + ENERGY("var E=", 6, 20, 25600, SmartHomeUnits.WATT_HOUR); + + private final Logger logger = LoggerFactory.getLogger(EnergeniePWMStateEnum.class); + + private final String stateResponseSearch; + private final int start; + private final int stop; + private final int divisor; + private final Unit unit; + + private EnergeniePWMStateEnum(final String stateResponseSearch, final int start, final int stop, final int divisor, + final Unit unit) { + this.stateResponseSearch = stateResponseSearch; + this.start = start; + this.stop = stop; + this.divisor = divisor; + this.unit = unit; + } + + public String getStateResponseSearch() { + return stateResponseSearch; + } + + public int getStart() { + return start; + } + + public int getStop() { + return stop; + } + + public int getDivisor() { + return divisor; + } + + public State readState(final String loginResponseString) { + final int findState = loginResponseString.lastIndexOf(stateResponseSearch); + + if (findState > 0) { + logger.trace("searchstring {} found at position {}", stateResponseSearch, findState); + final String slicedResponseTmp = loginResponseString.substring(findState + start, findState + stop); + logger.trace("transformed state response = {}", slicedResponseTmp); + final String[] slicedResponse = slicedResponseTmp.split(";"); + logger.trace("transformed state response = {} - {}", slicedResponse[0], slicedResponse[1]); + final double value; + try { + value = Double.parseDouble(slicedResponse[0]) / divisor; + return QuantityType.valueOf(value, unit); + } catch (NumberFormatException e) { + logger.debug("Could not Parse State", e); + return UnDefType.UNDEF; + } + } else { + logger.trace("searchstring '{} not found", stateResponseSearch); + return UnDefType.UNDEF; + } + } +} diff --git a/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieProtocolEnum.java b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieProtocolEnum.java new file mode 100644 index 0000000000000..1e3709890df6d --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/EnergenieProtocolEnum.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energenie.internal; + +import static org.openhab.binding.energenie.internal.EnergenieBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link EnergenieProtocolEnum} contains informations for parsing the readState() result. + * + * @author Hans-Jörg Merk - Initial contribution + */ + +@NonNullByDefault +public enum EnergenieProtocolEnum { + V20(STATE_ON), + V21(V21_STATE_ON), + WLAN(WLAN_STATE_ON); + + private final String statusOn; + + private EnergenieProtocolEnum(String statusOn) { + this.statusOn = statusOn; + } + + public String getStatusOn() { + return statusOn; + } +} diff --git a/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/config/EnergenieConfiguration.java b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/config/EnergenieConfiguration.java new file mode 100644 index 0000000000000..b2c74434c7fcf --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/config/EnergenieConfiguration.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energenie.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link EnergenieConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Hans-Jörg Merk - Initial contribution + */ +@NonNullByDefault +public class EnergenieConfiguration { + /** + * The default refresh interval in Seconds. + */ + public static final int DEFAULT_REFRESH_INTERVAL = 60; + + public String host = ""; + public String password = ""; +} diff --git a/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergenieHandler.java b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergenieHandler.java new file mode 100644 index 0000000000000..cc6b945adedee --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergenieHandler.java @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energenie.internal.handler; + +import static org.openhab.binding.energenie.internal.EnergenieBindingConstants.*; + +import java.io.IOException; +import java.net.UnknownHostException; +import java.time.Duration; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.cache.ExpiringCache; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.util.ThingHandlerHelper; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.energenie.internal.EnergenieProtocolEnum; +import org.openhab.binding.energenie.internal.config.EnergenieConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EnergenieHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Hans-Jörg Merk - Initial contribution + */ +@NonNullByDefault +public class EnergenieHandler extends BaseThingHandler { + + private static final String CHANNEL_SOCKET_PREFIX = "socket"; + private final Logger logger = LoggerFactory.getLogger(EnergenieHandler.class); + + /** + * Use cache for refresh command to not update again when call is made within 4 seconds of previous call. + */ + private final ExpiringCache refreshCache = new ExpiringCache<>(Duration.ofSeconds(5), this::refreshState); + private final String statusOn; + + private @Nullable EnergenieSocket energenieSocket; + private @Nullable ScheduledFuture refreshJob; + + private int refreshInterval; + private @Nullable String host; + + public EnergenieHandler(final Thing thing, final EnergenieProtocolEnum protocol) { + super(thing); + this.statusOn = protocol.getStatusOn(); + } + + @Override + public void handleCommand(final ChannelUID channelUID, final Command command) { + if (command instanceof RefreshType) { + refreshCache.getValue(); + } else if (command instanceof OnOffType) { + final byte[] ctrl = { DONT_SWITCH, DONT_SWITCH, DONT_SWITCH, DONT_SWITCH }; + final Matcher matcher = CHANNEL_SOCKET.matcher(channelUID.getId()); + + try { + boolean found = false; + + if (matcher.find()) { + final int index = Integer.parseInt(matcher.group(1)) - 1; + + if (index >= 0 && index < SOCKET_COUNT) { + ctrl[index] = OnOffType.ON.equals(command) ? SWITCH_ON : SWITCH_OFF; + stateUpdate(energenieSocket.sendCommand(ctrl)); + found = true; + } + } + if (!found) { + logger.debug("Invalid channel id {}, should be value between 1 and {}", channelUID, SOCKET_COUNT); + } + } catch (final IOException e) { + updateStatus(ThingStatus.OFFLINE); + logger.debug("Couldn't get I/O for the connection to: {}:{}.", host, TCP_PORT, e); + } + } + } + + @Override + public void initialize() { + final EnergenieConfiguration config = getConfigAs(EnergenieConfiguration.class); + + if (!config.host.isEmpty() && !config.password.isEmpty()) { + refreshInterval = EnergenieConfiguration.DEFAULT_REFRESH_INTERVAL; + host = config.host; + logger.debug("Initializing EnergenieHandler for Host '{}'", config.host); + energenieSocket = new EnergenieSocket(config.host, config.password); + + updateStatus(ThingStatus.UNKNOWN); + refreshJob = scheduler.scheduleWithFixedDelay(this::refreshState, 6, refreshInterval, TimeUnit.SECONDS); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Can not access device , IP-Address or password not set"); + } + } + + @Override + public void dispose() { + logger.debug("EnergenieHandler disposed."); + final ScheduledFuture refreshJob = this.refreshJob; + + if (refreshJob != null) { + refreshJob.cancel(true); + this.refreshJob = null; + } + } + + private boolean refreshState() { + final EnergenieSocket socket = this.energenieSocket; + + if (socket != null) { + try { + stateUpdate(socket.retrieveStatus()); + if (thing.getStatus() != ThingStatus.ONLINE && ThingHandlerHelper.isHandlerInitialized(thing)) { + updateStatus(ThingStatus.ONLINE); + } + return true; + } catch (final UnknownHostException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Can't find host: " + e.getMessage()); + } catch (final IOException e) { + logger.debug("Couldn't get I/O for the connection to: {}:{}.", host, TCP_PORT, e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Couldn't get I/O for the connection"); + } catch (final RuntimeException e) { + logger.debug("Unexpected error", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, e.getMessage()); + } + } + return false; + } + + public void stateUpdate(final byte[] status) { + for (int i = 0; i < 4; i++) { + final String socket = CHANNEL_SOCKET_PREFIX + (i + 1); + final String stringStatus = String.format("0x%02x", status[i]); + updateState(socket, OnOffType.from(stringStatus.equals(statusOn))); + } + } +} diff --git a/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergeniePWMHandler.java b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergeniePWMHandler.java new file mode 100644 index 0000000000000..2cc74eafe9491 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergeniePWMHandler.java @@ -0,0 +1,131 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energenie.internal.handler; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.io.net.http.HttpUtil; +import org.openhab.binding.energenie.internal.EnergeniePWMStateEnum; +import org.openhab.binding.energenie.internal.config.EnergenieConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EnergeniePWMHandler} is responsible for reading states and update PWM channels. + * + * @author Hans-Jörg Merk - Initial contribution + */ + +@NonNullByDefault +public class EnergeniePWMHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(EnergeniePWMHandler.class); + + private static final int HTTP_TIMEOUT_MILLISECONDS = 6000; + + private String host = ""; + private String password = ""; + private int refreshInterval; + + private @Nullable ScheduledFuture refreshJob; + + public EnergeniePWMHandler(Thing thing) { + super(thing); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + scheduler.execute(this::getState); + } + } + + @Override + public void initialize() { + EnergenieConfiguration config = getConfigAs(EnergenieConfiguration.class); + + if (!config.host.isEmpty() && !config.password.isEmpty()) { + host = config.host; + password = config.password; + refreshInterval = EnergenieConfiguration.DEFAULT_REFRESH_INTERVAL; + logger.debug("Initializing EnergeniePWMHandler for Host '{}'", host); + updateStatus(ThingStatus.ONLINE); + onUpdate(); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Can not access device , IP-Address or password not set"); + } + } + + @Override + public void dispose() { + logger.debug("EnergeniePWMHandler disposed."); + final ScheduledFuture refreshJob = this.refreshJob; + + if (refreshJob != null) { + refreshJob.cancel(true); + this.refreshJob = null; + } + } + + public synchronized void getState() { + String url = "http://" + host + "/login.html"; + String urlParameters = "pw=" + password; + InputStream urlContent = new ByteArrayInputStream(urlParameters.getBytes(StandardCharsets.UTF_8)); + String loginResponseString = null; + + try { + logger.trace("sending 'POST' request to URL : {}", url); + loginResponseString = HttpUtil.executeUrl("POST", url, urlContent, "TEXT/PLAIN", HTTP_TIMEOUT_MILLISECONDS); + + if (loginResponseString != null) { + updateState("voltage", EnergeniePWMStateEnum.VOLTAGE.readState(loginResponseString)); + updateState("current", EnergeniePWMStateEnum.CURRENT.readState(loginResponseString)); + updateState("power", EnergeniePWMStateEnum.POWER.readState(loginResponseString)); + updateState("energy", EnergeniePWMStateEnum.ENERGY.readState(loginResponseString)); + try { + HttpUtil.executeUrl("POST", url, HTTP_TIMEOUT_MILLISECONDS); + logger.trace("logout from ip {}", host); + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "failed to logout: " + e.getMessage()); + } + } + + } catch (IOException e) { + logger.debug("energenie: failed to login to {} with ip {}", thing.getUID(), host, e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + private synchronized void onUpdate() { + ScheduledFuture refreshJob = this.refreshJob; + if (refreshJob == null || refreshJob.isCancelled()) { + this.refreshJob = scheduler.scheduleWithFixedDelay(this::getState, 5, refreshInterval, TimeUnit.SECONDS); + } + } +} diff --git a/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergenieSocket.java b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergenieSocket.java new file mode 100644 index 0000000000000..ab9e476f60860 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/java/org/openhab/binding/energenie/internal/handler/EnergenieSocket.java @@ -0,0 +1,182 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.energenie.internal.handler; + +import static org.openhab.binding.energenie.internal.EnergenieBindingConstants.*; + +import java.io.Closeable; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.util.HexUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Class handling the Socket connections. + * + * @author Hans-Jörg Merk - Initial contribution + * @author Hilbrand Bouwkamp - Moved Socket to it's own class + */ +@NonNullByDefault +class EnergenieSocket { + + private static final int SOCKET_TIMEOUT_MILLISECONDS = 1500; + private static final byte[] MESSAGE = { 0x11 }; + + private final Logger logger = LoggerFactory.getLogger(EnergenieSocket.class); + private final String host; + private final byte[] key; + + public EnergenieSocket(final String host, final String password) { + this.host = host; + this.key = getKey(password); + } + + private static byte[] getKey(final String password) { + final int passwordLength = password.length(); + String passwordString = password; + for (int i = 0; i < (8 - passwordLength); i++) { + passwordString = passwordString + " "; + } + return passwordString.getBytes(); + } + + public synchronized byte[] sendCommand(final byte[] ctrl) throws IOException { + try (final TaskSocket taskSocket = authorize()) { + final OutputStream output = taskSocket.socket.getOutputStream(); + final DataInputStream input = new DataInputStream(taskSocket.socket.getInputStream()); + + if (output == null) { + throw new IOException("No connection"); + } else { + if (logger.isTraceEnabled()) { + logger.trace("Control message send to EG (int) '{}' (hex)'{}'", ctrl, HexUtils.bytesToHex(ctrl)); + } + output.write(encryptControls(ctrl, taskSocket.task)); + output.flush(); + readStatus(input, taskSocket); + return updateStatus(taskSocket); + } + } + } + + public synchronized byte[] retrieveStatus() throws IOException { + try (final TaskSocket taskSocket = authorize()) { + return updateStatus(taskSocket); + } + } + + private TaskSocket authorize() throws IOException { + final TaskSocket taskSocket = new TaskSocket(); + final OutputStream output = taskSocket.socket.getOutputStream(); + final DataInputStream input = new DataInputStream(taskSocket.socket.getInputStream()); + if (output == null) { + throw new IOException("No connection"); + } + output.write(MESSAGE); + output.flush(); + logger.trace("Start Condition '{}' send to EG", MESSAGE); + input.readFully(taskSocket.task); + + if (logger.isTraceEnabled()) { + logger.trace("EG responded with task (int) '{}' (hex) '{}'", taskSocket.task, + HexUtils.bytesToHex(taskSocket.task)); + } + final byte[] solutionMessage = calculateSolution(taskSocket.task); + + output.write(solutionMessage); + output.flush(); + logger.trace("Solution '{}' send to EG", solutionMessage); + readStatus(input, taskSocket); + return taskSocket; + } + + private void readStatus(final DataInputStream input, final TaskSocket taskSocket) throws IOException { + input.readFully(taskSocket.statcryp); + if (logger.isTraceEnabled()) { + logger.trace("EG responded with statcryp (int) '{}' (hex) '{}'", taskSocket.statcryp, + HexUtils.bytesToHex(taskSocket.statcryp)); + } + } + + private byte[] updateStatus(final TaskSocket taskSocket) throws IOException { + final byte[] status = decryptStatus(taskSocket); + + if (logger.isTraceEnabled()) { + logger.trace("EG responded with status (int) '{}' (hex) '{}'", status, HexUtils.bytesToHex(status)); + } + return status; + } + + private byte[] calculateSolution(final byte[] task) { + final int[] uIntTask = new int[4]; + + for (int i = 0; i < 4; i++) { + uIntTask[i] = Byte.toUnsignedInt(task[i]); + } + final int solutionLoword = (((uIntTask[0] ^ key[2]) * key[0]) ^ (key[6] | (key[4] << 8)) ^ uIntTask[2]); + final byte[] loword = ByteBuffer.allocate(4).putInt(solutionLoword).array(); + + final int solutionHiword = (((uIntTask[1] ^ key[3]) * key[1]) ^ (key[7] | (key[5] << 8)) ^ uIntTask[3]); + final byte[] hiword = ByteBuffer.allocate(4).putInt(solutionHiword).array(); + final byte[] solution = new byte[SOLUTION_LEN]; + + solution[0] = loword[3]; + solution[1] = loword[2]; + solution[2] = hiword[3]; + solution[3] = hiword[2]; + + return solution; + } + + private byte[] decryptStatus(final TaskSocket taskSocket) { + final byte[] status = new byte[4]; + + for (int i = 0; i < 4; i++) { + status[i] = (byte) ((((taskSocket.statcryp[3 - i] - key[1]) ^ key[0]) - taskSocket.task[3]) + ^ taskSocket.task[2]); + } + return status; + } + + private byte[] encryptControls(final byte[] controls, final byte[] task) { + final byte[] ctrlcryp = new byte[CTRLCRYP_LEN]; + + for (int i = 0; i < 4; i++) { + ctrlcryp[i] = (byte) ((((controls[3 - i] ^ task[2]) + task[3]) ^ key[0]) + key[1]); + } + return ctrlcryp; + } + + private class TaskSocket implements Closeable { + final Socket socket; + final byte[] task = new byte[TASK_LEN]; + final byte[] statcryp = new byte[STATCRYP_LEN]; + + public TaskSocket() throws UnknownHostException, IOException { + socket = new Socket(host, TCP_PORT); + socket.setSoTimeout(SOCKET_TIMEOUT_MILLISECONDS); + } + + @Override + public void close() throws IOException { + socket.close(); + } + } +} diff --git a/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..8582bce616318 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + Energenie Binding + This is the binding for Energenie. + Hans-Jörg Merk + + diff --git a/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/config/config.xml new file mode 100644 index 0000000000000..5b79eac6206ee --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/config/config.xml @@ -0,0 +1,19 @@ + + + + + + The IP address of this device + network-address + + + + The password of this device + 1 + password + + + diff --git a/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..75e7a05f28f21 --- /dev/null +++ b/bundles/org.openhab.binding.energenie/src/main/resources/ESH-INF/thing/thing-types.xml @@ -0,0 +1,134 @@ + + + + + + Energenie programmable power strip with LAN interface + + + + + + + + + + + + + + + Energenie programmable power strip with LAN interface + + + + + + + + + + + + + + + Energenie programmable power strip with LAN interface + + + + + + + + + + + + + + + Energenie programmable power strip with WLAN interface + + + + + + + + + + + + + + + Energenie energy meter with LAN interface + + + + + + + + + + + + + + Switch + + Channel representing the state of socket 1 + + + + Switch + + Channel representing the state of socket 2 + + + + Switch + + Channel representing the state of socket 3 + + + + Switch + + Channel representing the state of socket 4 + + + + Number:ElectricPotential + + Channel representing the voltage + + + + + Number:ElectricCurrent + + Channel representing the current + + + + + Number:Power + + Channel representing the power consumption + + + + + Number:Energy + + Channel representing the energy consumption + + + + diff --git a/bundles/org.openhab.binding.enigma2/NOTICE b/bundles/org.openhab.binding.enigma2/NOTICE new file mode 100644 index 0000000000000..38d625e349232 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.enigma2/README.md b/bundles/org.openhab.binding.enigma2/README.md new file mode 100644 index 0000000000000..fb8f2219bbc97 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/README.md @@ -0,0 +1,409 @@ +# Enigma2 Binding + +The binding integrates Enigma2 devices. + +## Supported Things + +### Enigma2 devices + +Enigma2 based set-top boxes with an installed OpenWebIf are supported. + +#### Device Settings + +The Device must be connected to the same network as openHAB. + +## Discovery + +Devices are auto discovered through HTTP in the local network. + +If automatic discovery is not possible you may still manually configure a device based on the hostname. + +## Thing Configuration + +Enigma2 has the following configuration parameters: + +| Name | Description | Mandatory | +|-----------------|----------------------------------------------------|-----------| +| host | Hostname or IP address of the Enigma2 device | yes | +| refreshInterval | The refresh interval in seconds | yes | +| timeout | The timeout for reading from the device in seconds | yes | +| user | Optional: The Username of the Enigma2 Web API | no | +| password | Optional: The Password of the Enigma2 Web API | no | + +### Configuration in .things file + +Set the parameters as in the following example: + +``` +Thing enigma2:device:192_168_0_3 [host="192.168.1.3", refreshInterval="5", timeout="5", user="usename" , password="***"] +``` + +## Channels + +| Channel Type ID | Item Type | Description | Read/Write | +|-----------------|-----------|----------------------------------------------------------------------------------------------|------------| +| power | Switch | Current power setting. | RW | +| mute | Switch | Current mute setting. | RW | +| volume | Dimmer | Current volume setting. | RW | +| channel | String | Current channel. Use only the channel text as command to update the channel. | RW | +| title | String | Current program title of the current channel. | R | +| description | String | Current program description of the current channel. | R | +| mediaPlayer | Player | Media control player. | RW | +| mediaStop | Switch | Media control stop. | RW | +| answer | String | Receives an answer to a send question of the device. | R | + +## Example + +demo.things: + +``` +Thing enigma2:device:192_168_0_3 [host="192.168.1.3", refreshInterval="5"] +``` + +demo.items: + +``` +Switch Enigma2_Power "Power: [%s]" { channel="enigma2:device:192_168_0_3:power" } +Dimmer Enigma2_Volume "Volume: [%d %%]" { channel="enigma2:device:192_168_0_3:volume" } +Switch Enigma2_Mute "Mute: [%s]" { channel="enigma2:device:192_168_0_3:mute" } +Switch Enigma2_Stop "Stop: [%s]" { channel="enigma2:device:192_168_0_3:mediaStop", autoupdate="false" } +Player Enigma2_PlayerControl "Mode: [%s]" { channel="enigma2:device:192_168_0_3:mediaPlayer" } +String Enigma2_Channel "Channel: [%s]" { channel="enigma2:device:192_168_0_3:channel" } +String Enigma2_Title "Title: [%s]" { channel="enigma2:device:192_168_0_3:title" } +String Enigma2_Description "Description: [%s]" { channel="enigma2:device:192_168_0_3:description" } +String Enigma2_Answer "Answer: [%s]" { channel="enigma2:device:192_168_0_3:answer" } +String Enigma2_RemoteKeys "[]" { autoupdate="false" } +String Enigma2_SendError "Error" { autoupdate="false" } +String Enigma2_SendWarning "Warning" { autoupdate="false" } +String Enigma2_SendInfo "Info" { autoupdate="false" } +``` + +demo.sitemap: + +``` +sitemap demo label="Enigma2 Demo" +{ + Frame label="Enigma2" { + Switch item=Enigma2_Power + Slider item=Enigma2_Volume step=5 minValue=0 maxValue=100 + Setpoint item=Enigma2_Volume step=5 minValue=0 maxValue=100 + Switch item=Enigma2_Mute + Default item=Enigma2_PlayerControl + Switch item=Enigma2_Stop mappings=[ON="Stop"] + Text item=Enigma2_Channel + Text item=Enigma2_Title + Text item=Enigma2_Description + } + Frame label="Enigma2 Remote" { + Switch item=Enigma2_RemoteKeys mappings=[POWER="POWER"] + Switch item=Enigma2_RemoteKeys mappings=[TEXT="[=]", SUBTITLE="[_]", MUTE="MUTE"] + Switch item=Enigma2_RemoteKeys mappings=[KEY_1="1", KEY_2="2", KEY_3="3"] + Switch item=Enigma2_RemoteKeys mappings=[KEY_4="4", KEY_5="5", KEY_6="6"] + Switch item=Enigma2_RemoteKeys mappings=[KEY_7="7", KEY_8="8", KEY_9="9"] + Switch item=Enigma2_RemoteKeys mappings=[ARROW_LEFT="<", KEY_0="0", ARROW_RIGHT=">"] + Switch item=Enigma2_RemoteKeys mappings=[RED="R", GREEN="G", YELLOW="Y", BLUE="B"] + Switch item=Enigma2_RemoteKeys mappings=[UP="Up"] + Switch item=Enigma2_RemoteKeys mappings=[LEFT="Left", OK="Ok", RIGHT="Right"] + Switch item=Enigma2_RemoteKeys mappings=[DOWN="Down"] + Switch item=Enigma2_RemoteKeys mappings=[VOLUME_UP="+", EXIT="Exit", CHANNEL_UP="+"] + Switch item=Enigma2_RemoteKeys mappings=[VOLUME_DOWN="-", EPG="Epg", CHANNEL_DOWN="-"] + Switch item=Enigma2_RemoteKeys mappings=[MENU="Menu", VIDEO="[=R]", AUDIO="Audio", HELP="Help"] + Switch item=Enigma2_RemoteKeys mappings=[FAST_BACKWARD="<<", PLAY=">", PAUSE="||", FAST_FORWARD=">>"] + Switch item=Enigma2_RemoteKeys mappings=[TV="TV", RECORD="O", STOP="[]", RADIO="Radio"] + Switch item=Enigma2_RemoteKeys mappings=[INFO="INFO"] + } + Frame label="Enigma2 Messages" { + Switch item=Enigma2_SendError mappings=[SEND="SEND"] + Switch item=Enigma2_SendWarning mappings=[SEND="SEND"] + Switch item=Enigma2_SendInfo mappings=[SEND="SEND"] + Switch item=Enigma2_SendQuestion mappings=[SEND="SEND"] + Text item=Enigma2_Answer + } +} +``` + + +demo.rules: + +``` +rule "Enigma2_KeyS" +when Item Enigma2_RemoteKeys received command +then + val actions = getActions("enigma2","enigma2:device:192_168_0_3") + if(null === actions) { + logInfo("actions", "Actions not found, check thing ID") + return + } + actions.sendRcCommand(receivedCommand.toString) +end + +rule "Enigma2_SendError" +when Item Enigma2_SendError received command +then + val actions = getActions("enigma2","enigma2:device:192_168_0_3") + if(null === actions) { + logInfo("actions", "Actions not found, check thing ID") + return + } + actions.sendError(receivedCommand.toString, 10) +end + +rule "Enigma2_SendWarning" +when Item Enigma2_SendWarning received command +then + val actions = getActions("enigma2","enigma2:device:192_168_0_3") + if(null === actions) { + logInfo("actions", "Actions not found, check thing ID") + return + } + actions.sendWarning(receivedCommand.toString, 10) +end + +rule "Enigma2_SendInfo" +when Item Enigma2_SendInfo received command +then + val actions = getActions("enigma2","enigma2:device:192_168_0_3") + if(null === actions) { + logInfo("actions", "Actions not found, check thing ID") + return + } + actions.sendInfo(receivedCommand.toString, 10) +end + +rule "Enigma2_SendQuestion" +when Item Enigma2_SendQuestion received command +then + val actions = getActions("enigma2","enigma2:device:192_168_0_3") + if(null === actions) { + logInfo("actions", "Actions not found, check thing ID") + return + } + actions.sendQuestion(receivedCommand.toString, 10) +end + +rule "Enigma2_Answer" +when Item Enigma2_Answer received update +then + val actions = getActions("enigma2","enigma2:device:192_168_0_3") + if(null === actions) { + logInfo("actions", "Actions not found, check thing ID") + return + } + logInfo("actions", "Answer is " + Enigma2_Answer.state) +end +``` + +## Rule Actions + +Multiple actions are supported by this binding. In classic rules these are accessible as shown in this example (adjust getActions with your ThingId): + +Example + +``` + val actions = getActions("enigma2","enigma2:device:192_168_0_3") + if(null === actions) { + logInfo("actions", "Actions not found, check thing ID") + return + } +``` + +### sendInfo(text) + +Sends an info message to the device with will be shown on the TV screen for 30 seconds. + +Parameters: + +| Name | Description | +|---------|----------------------------------------------------------------------| +| text | The text to display | + +Example: + +``` +actions.sendInfo("Hello World") +``` + +### sendInfo(text, timeout) + +Sends an info message to the device with will be shown on the TV screen. + +Parameters: + +| Name | Description | +|---------|----------------------------------------------------------------------| +| text | The text to display | +| timeout | The timeout in seconds | + +Example: + +``` +actions.sendInfo("Hello World", 10) +``` + +### sendWarning(text) + +Sends a warning message to the device with will be shown on the TV screen for 30 seconds. + +Parameters: + +| Name | Description | +|---------|----------------------------------------------------------------------| +| text | The text to display | + +Example: + +``` +actions.sendWarning("Hello World") +``` + +### sendWarning(text, timeout) + +Sends a warning message to the device with will be shown on the TV screen. + +Parameters: + +| Name | Description | +|---------|----------------------------------------------------------------------| +| text | The text to display | +| timeout | The timeout in seconds | + +Example: + +``` +actions.sendWarning("Hello World", 10) +``` + +### sendError(text) + +Sends an error message to the device with will be shown on the TV screen for 30 seconds. + +Parameters: + +| Name | Description | +|---------|----------------------------------------------------------------------| +| text | The text to display | + +Example: + +``` +actions.sendError("Hello World") +``` + +### sendError(text, timeout) + +Sends an error message to the device with will be shown on the TV screen. + +Parameters: + +| Name | Description | +|---------|----------------------------------------------------------------------| +| text | The text to display | +| timeout | The timeout in seconds | + +Example: + +``` +actions.sendError("Hello World", 10) +``` + +### sendQuestion(text) + +Sends a question message to the device with will be shown on the TV screen for 30 seconds. +The answer is provided to the "answer"-channel. + +Parameters: + +| Name | Description | +|---------|----------------------------------------------------------------------| +| text | The text to display | + +Example: + +``` +actions.sendQuestion("Say hello?") +``` + +### sendQuestion(text, timeout) + +Sends an question message to the device with will be shown on the TV screen. +The answer is provided to the "answer"-channel. + +Parameters: + +| Name | Description | +|---------|----------------------------------------------------------------------| +| text | The text to display | +| timeout | The timeout in seconds | + +Example: + +``` +actions.sendQuestion("Say hello?", 10) +``` + +### sendRcCommand(button) + +Sends a button press event to the device. + +Parameters: + +| Name | Description | +|---------|------------------------------------------------------------------------| +| button | see the supported buttons in chapter 'Remote Control Buttons' | + + +The button parameter has only been tested on a Vu+Solo2 and this is a list of button codes that are known to work with this device. + +| Code String | +|---------------| +| POWER | +| KEY_0 | +| KEY_1 | +| KEY_2 | +| KEY_3 | +| KEY_4 | +| KEY_5 | +| KEY_6 | +| KEY_7 | +| KEY_8 | +| KEY_9 | +| ARROW_LEFT | +| ARROW_RIGHT | +| VOLUME_DOWN | +| VOLUME_UP | +| MUTE | +| CHANNEL_UP | +| CHANNEL_DOWN | +| LEFT | +| RIGHT | +| UP | +| DOWN | +| OK | +| EXIT | +| RED | +| GREEN | +| YELLOW | +| BLUE | +| PLAY | +| PAUSE | +| STOP | +| RECORD | +| FAST_FORWARD | +| FAST_BACKWARD | +| TV | +| RADIO | +| AUDIO | +| VIDEO | +| TEXT | +| INFO | +| MENU | +| HELP | +| SUBTITLE | +| EPG | + +Example: + +``` +actions.sendRcCommand("KEY_1") +``` + diff --git a/bundles/org.openhab.binding.enigma2/pom.xml b/bundles/org.openhab.binding.enigma2/pom.xml new file mode 100644 index 0000000000000..82f7c91880db7 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/pom.xml @@ -0,0 +1,16 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + + + org.openhab.binding.enigma2 + + openHAB Add-ons :: Bundles :: Enigma2 Binding + + diff --git a/bundles/org.openhab.binding.enigma2/src/main/feature/feature.xml b/bundles/org.openhab.binding.enigma2/src/main/feature/feature.xml new file mode 100644 index 0000000000000..c11cd51078003 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.enigma2/${project.version} + + diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/actions/Enigma2Actions.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/actions/Enigma2Actions.java new file mode 100644 index 0000000000000..f49b54357887e --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/actions/Enigma2Actions.java @@ -0,0 +1,180 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.actions; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.binding.ThingActions; +import org.eclipse.smarthome.core.thing.binding.ThingActionsScope; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.openhab.binding.enigma2.handler.Enigma2Handler; +import org.openhab.binding.enigma2.internal.Enigma2BindingConstants; +import org.openhab.core.automation.annotation.ActionInput; +import org.openhab.core.automation.annotation.RuleAction; + +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +/** + * This is the automation engine actions handler service for the + * enigma2 actions. + * + * @author Guido Dolfen - Initial contribution + */ +@ThingActionsScope(name = "enigma2") +@NonNullByDefault +public class Enigma2Actions implements ThingActions, IEnigma2Actions { + private @Nullable Enigma2Handler handler; + + @Override + public void setThingHandler(@Nullable ThingHandler handler) { + this.handler = (Enigma2Handler) handler; + } + + @Override + public @Nullable Enigma2Handler getThingHandler() { + return this.handler; + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-rc-button.label", description = "@text/actions.enigma2.send-rc-button.description") + @SuppressWarnings("null") + public void sendRcCommand( + @ActionInput(name = "rcButton", label = "@text/actions-input.enigma2.rc-button.label", description = "@text/actions-input.enigma2.rc-button.description") String rcButton) { + handler.sendRcCommand(rcButton); + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-info.label", description = "@text/actions.enigma2.send-info.description") + @SuppressWarnings("null") + public void sendInfo( + @ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text) { + handler.sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, text); + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-info.label", description = "@text/actions.enigma2.send-info.description") + @SuppressWarnings("null") + public void sendInfo( + @ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text, + @ActionInput(name = "timeout", label = "@text/actions-input.enigma2.timeout.label", description = "@text/actions-input.enigma2.timeout.description") int timeout) { + handler.sendInfo(timeout, text); + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-warning.label", description = "@text/actions.enigma2.send-warning.description") + @SuppressWarnings("null") + public void sendWarning( + @ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text) { + handler.sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, text); + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-warning.label", description = "@text/actions.enigma2.send-warning.description") + @SuppressWarnings("null") + public void sendWarning( + @ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text, + @ActionInput(name = "timeout", label = "@text/actions-input.enigma2.timeout.label", description = "@text/actions-input.enigma2.timeout.description") int timeout) { + handler.sendWarning(timeout, text); + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-error.label", description = "@text/actions.enigma2.send-error.description") + @SuppressWarnings("null") + public void sendError( + @ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text) { + handler.sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, text); + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-error.label", description = "@text/actions.enigma2.send-error.description") + @SuppressWarnings("null") + public void sendError( + @ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text, + @ActionInput(name = "timeout", label = "@text/actions-input.enigma2.timeout.label", description = "@text/actions-input.enigma2.timeout.description") int timeout) { + handler.sendError(timeout, text); + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-error.label", description = "@text/actions.enigma2.send-question.description") + @SuppressWarnings("null") + public void sendQuestion( + @ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text) { + handler.sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, text); + } + + @Override + @RuleAction(label = "@text/actions.enigma2.send-error.label", description = "@text/actions.enigma2.send-question.description") + @SuppressWarnings("null") + public void sendQuestion( + @ActionInput(name = "text", label = "@text/actions-input.enigma2.text.label", description = "@text/actions-input.enigma2.text.description") String text, + @ActionInput(name = "timeout", label = "@text/actions-input.enigma2.timeout.label", description = "@text/actions-input.enigma2.timeout.description") int timeout) { + handler.sendQuestion(timeout, text); + } + + // delegation methods for "legacy" rule support + public static void sendRcCommand(@Nullable ThingActions actions, String rcButton) { + invokeMethodOf(actions).sendRcCommand(rcButton); + } + + public static void sendInfo(@Nullable ThingActions actions, String info) { + invokeMethodOf(actions).sendInfo(info); + } + + public static void sendInfo(@Nullable ThingActions actions, String info, int timeout) { + invokeMethodOf(actions).sendInfo(info, timeout); + } + + public static void sendWarning(@Nullable ThingActions actions, String warning) { + invokeMethodOf(actions).sendWarning(warning); + } + + public static void sendWarning(@Nullable ThingActions actions, String warning, int timeout) { + invokeMethodOf(actions).sendWarning(warning, timeout); + } + + public static void sendError(@Nullable ThingActions actions, String error) { + invokeMethodOf(actions).sendError(error); + } + + public static void sendError(@Nullable ThingActions actions, String error, int timeout) { + invokeMethodOf(actions).sendError(error, timeout); + } + + public static void sendQuestion(@Nullable ThingActions actions, String text) { + invokeMethodOf(actions).sendQuestion(text); + } + + public static void sendQuestion(@Nullable ThingActions actions, String text, int timeout) { + invokeMethodOf(actions).sendQuestion(text, timeout); + } + + private static IEnigma2Actions invokeMethodOf(@Nullable ThingActions actions) { + if (actions == null) { + throw new IllegalArgumentException("actions cannot be null"); + } + if (actions.getClass().getName().equals(Enigma2Actions.class.getName())) { + if (actions instanceof IEnigma2Actions) { + return (IEnigma2Actions) actions; + } else { + return (IEnigma2Actions) Proxy.newProxyInstance(IEnigma2Actions.class.getClassLoader(), + new Class[] { IEnigma2Actions.class }, (Object proxy, Method method, Object[] args) -> { + Method m = actions.getClass().getDeclaredMethod(method.getName(), + method.getParameterTypes()); + return m.invoke(actions, args); + }); + } + } + throw new IllegalArgumentException("Actions is not an instance of Enigma2Actions"); + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/actions/IEnigma2Actions.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/actions/IEnigma2Actions.java new file mode 100644 index 0000000000000..591d2565cf13c --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/actions/IEnigma2Actions.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.actions; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link IEnigma2Actions} defines the interface for all thing actions supported by the binding. + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +public interface IEnigma2Actions { + void sendRcCommand(String rcButton); + + void sendInfo(String text); + + void sendInfo(String text, int timeout); + + void sendWarning(String text); + + void sendWarning(String text, int timeout); + + void sendError(String text); + + void sendError(String text, int timeout); + + void sendQuestion(String text); + + void sendQuestion(String text, int timeout); +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/handler/Enigma2Handler.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/handler/Enigma2Handler.java new file mode 100644 index 0000000000000..37c18cfc09c1e --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/handler/Enigma2Handler.java @@ -0,0 +1,301 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.handler; + +import static org.openhab.binding.enigma2.internal.Enigma2BindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.*; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.enigma2.actions.Enigma2Actions; +import org.openhab.binding.enigma2.internal.Enigma2Client; +import org.openhab.binding.enigma2.internal.Enigma2Configuration; +import org.openhab.binding.enigma2.internal.Enigma2RemoteKey; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * The {@link Enigma2Handler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +public class Enigma2Handler extends BaseThingHandler { + private final Logger logger = LoggerFactory.getLogger(Enigma2Handler.class); + private Enigma2Configuration configuration = new Enigma2Configuration(); + private Optional enigma2Client = Optional.empty(); + private @Nullable ScheduledFuture refreshJob; + private LocalDateTime lastAnswerTime = LocalDateTime.now(); + + public Enigma2Handler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + configuration = getConfigAs(Enigma2Configuration.class); + if (configuration.host.isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "host must not be empty"); + } else if (configuration.timeout <= 0 || configuration.timeout > 300) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "timeout must be between 0 and 300 seconds"); + } else if (configuration.refreshInterval <= 0 || configuration.refreshInterval > 3600) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "refreshInterval must be between 0 and 3600 seconds"); + } + enigma2Client = Optional.of(new Enigma2Client(configuration.host, configuration.user, configuration.password, + configuration.timeout)); + refreshJob = scheduler.scheduleWithFixedDelay(this::refresh, 2, configuration.refreshInterval, TimeUnit.SECONDS); + } + + private void refresh() { + getEnigma2Client().ifPresent(client -> { + boolean online = client.refresh(); + if (online) { + updateStatus(ThingStatus.ONLINE); + updateState(CHANNEL_POWER, client.isPower() ? OnOffType.ON : OnOffType.OFF); + updateState(CHANNEL_MUTE, client.isMute() ? OnOffType.ON : OnOffType.OFF); + updateState(CHANNEL_VOLUME, new PercentType(client.getVolume())); + updateState(CHANNEL_CHANNEL, new StringType(client.getChannel())); + updateState(CHANNEL_TITLE, new StringType(client.getTitle())); + updateState(CHANNEL_DESCRIPTION, new StringType(client.getDescription())); + if (lastAnswerTime.isBefore(client.getLastAnswerTime())) { + lastAnswerTime = client.getLastAnswerTime(); + updateState(CHANNEL_ANSWER, new StringType(client.getAnswer())); + } + } else { + updateStatus(ThingStatus.OFFLINE); + } + }); + } + + @Override + public void dispose() { + ScheduledFuture job = this.refreshJob; + if(job != null) { + job.cancel(true); + } + this.refreshJob = null; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + logger.debug("handleCommand({},{})", channelUID, command); + getEnigma2Client().ifPresent(client -> { + switch (channelUID.getId()) { + case CHANNEL_POWER: + handlePower(channelUID, command, client); + break; + case CHANNEL_CHANNEL: + handleChannel(channelUID, command, client); + break; + case CHANNEL_MEDIA_PLAYER: + handleMediaPlayer(channelUID, command); + break; + case CHANNEL_MEDIA_STOP: + handleMediaStop(channelUID, command); + break; + case CHANNEL_MUTE: + handleMute(channelUID, command, client); + break; + case CHANNEL_VOLUME: + handleVolume(channelUID, command, client); + break; + case CHANNEL_TITLE: + handleTitle(channelUID, command, client); + break; + case CHANNEL_DESCRIPTION: + handleDescription(channelUID, command, client); + break; + case CHANNEL_ANSWER: + handleAnswer(channelUID, command, client); + break; + default: + logger.debug("Channel {} is not supported", channelUID); + break; + } + }); + } + + private void handleVolume(ChannelUID channelUID, Command command, Enigma2Client client) { + if (command instanceof RefreshType) { + client.refreshVolume(); + updateState(channelUID, new PercentType(client.getVolume())); + } else if (command instanceof PercentType) { + client.setVolume(((PercentType) command).intValue()); + } else if (command instanceof DecimalType) { + client.setVolume(((DecimalType) command).intValue()); + } else { + logger.info("Channel {} only accepts PercentType, DecimalType, RefreshType. Type was {}.", channelUID, + command.getClass()); + } + } + + private void handleMute(ChannelUID channelUID, Command command, Enigma2Client client) { + if (command instanceof RefreshType) { + client.refreshVolume(); + updateState(channelUID, client.isMute() ? OnOffType.ON : OnOffType.OFF); + } else if (OnOffType.ON.equals(command)) { + client.setMute(true); + } else if (OnOffType.OFF.equals(command)) { + client.setMute(false); + } else { + logger.info("Channel {} only accepts OnOffType, RefreshType. Type was {}.", channelUID, command.getClass()); + } + } + + private void handleAnswer(ChannelUID channelUID, Command command, Enigma2Client client) { + if (command instanceof RefreshType) { + client.refreshAnswer(); + if (lastAnswerTime.isBefore(client.getLastAnswerTime())) { + lastAnswerTime = client.getLastAnswerTime(); + updateState(channelUID, new StringType(client.getAnswer())); + } + } else { + logger.info("Channel {} only accepts RefreshType. Type was {}.", channelUID, command.getClass()); + } + } + + private void handleMediaStop(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + return; + } else if (command instanceof OnOffType) { + sendRcCommand(Enigma2RemoteKey.STOP); + } else { + logger.info("Channel {} only accepts OnOffType, RefreshType. Type was {}.", channelUID, command.getClass()); + } + } + + private void handleMediaPlayer(ChannelUID channelUID, Command command) { + if (RefreshType.REFRESH == command) { + return; + } else if (PlayPauseType.PLAY == command) { + sendRcCommand(Enigma2RemoteKey.PLAY); + } else if (PlayPauseType.PAUSE == command) { + sendRcCommand(Enigma2RemoteKey.PAUSE); + } else if (NextPreviousType.NEXT == command) { + sendRcCommand(Enigma2RemoteKey.FAST_FORWARD); + } else if (NextPreviousType.PREVIOUS == command) { + sendRcCommand(Enigma2RemoteKey.FAST_BACKWARD); + } else { + logger.info("Channel {} only accepts PlayPauseType, NextPreviousType, RefreshType. Type was {}.", + channelUID, command.getClass()); + } + } + + private void handleChannel(ChannelUID channelUID, Command command, Enigma2Client client) { + if (command instanceof RefreshType) { + client.refreshChannel(); + updateState(channelUID, new StringType(client.getChannel())); + } else if (command instanceof StringType) { + client.setChannel(command.toString()); + } else { + logger.info("Channel {} only accepts StringType, RefreshType. Type was {}.", channelUID, + command.getClass()); + } + } + + private void handleTitle(ChannelUID channelUID, Command command, Enigma2Client client) { + if (command instanceof RefreshType) { + client.refreshEpg(); + updateState(channelUID, new StringType(client.getTitle())); + } else { + logger.info("Channel {} only accepts RefreshType. Type was {}.", channelUID, command.getClass()); + } + } + + private void handleDescription(ChannelUID channelUID, Command command, Enigma2Client client) { + if (command instanceof RefreshType) { + client.refreshEpg(); + updateState(channelUID, new StringType(client.getDescription())); + } else { + logger.info("Channel {} only accepts RefreshType. Type was {}.", channelUID, command.getClass()); + } + } + + private void handlePower(ChannelUID channelUID, Command command, Enigma2Client client) { + if (RefreshType.REFRESH == command) { + client.refreshPower(); + updateState(channelUID, client.isPower() ? OnOffType.ON : OnOffType.OFF); + } else if (OnOffType.ON == command) { + client.setPower(true); + } else if (OnOffType.OFF == command) { + client.setPower(false); + } else { + logger.info("Channel {} only accepts OnOffType, RefreshType. Type was {}.", channelUID, command.getClass()); + } + } + + public void sendRcCommand(String rcButton) { + logger.debug("sendRcCommand({})", rcButton); + try { + Enigma2RemoteKey remoteKey = Enigma2RemoteKey.valueOf(rcButton); + sendRcCommand(remoteKey); + } catch (IllegalArgumentException ex) { + logger.warn("{} is not a valid value for button - available are: {}", rcButton, + Stream.of(Enigma2RemoteKey.values()).map(b -> b.name()).collect(Collectors.joining(", "))); + } + } + + private void sendRcCommand(Enigma2RemoteKey remoteKey) { + getEnigma2Client().ifPresent(client -> client.sendRcCommand(remoteKey.getValue())); + } + + public void sendInfo(int timeout, String text) { + getEnigma2Client().ifPresent(client -> client.sendInfo(timeout, text)); + } + + public void sendWarning(int timeout, String text) { + getEnigma2Client().ifPresent(client -> client.sendWarning(timeout, text)); + } + + public void sendError(int timeout, String text) { + getEnigma2Client().ifPresent(client -> client.sendError(timeout, text)); + } + + public void sendQuestion(int timeout, String text) { + getEnigma2Client().ifPresent(client -> client.sendQuestion(timeout, text)); + } + + @Override + public Collection> getServices() { + return Collections.singleton(Enigma2Actions.class); + } + + /** + * Getter for Test-Injection + * + * @return Enigma2Client. + */ + Optional getEnigma2Client() { + return enigma2Client; + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2BindingConstants.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2BindingConstants.java new file mode 100644 index 0000000000000..57844e7a5295d --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2BindingConstants.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +import java.util.Collections; +import java.util.Set; + +/** + * The {@link Enigma2BindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +public class Enigma2BindingConstants { + + private static final String BINDING_ID = "enigma2"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device"); + + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_DEVICE); + + // List of all Channel ids + public static final String CHANNEL_VOLUME = "volume"; + public static final String CHANNEL_POWER = "power"; + public static final String CHANNEL_MUTE = "mute"; + public static final String CHANNEL_CHANNEL = "channel"; + public static final String CHANNEL_TITLE = "title"; + public static final String CHANNEL_DESCRIPTION = "description"; + public static final String CHANNEL_MEDIA_PLAYER = "mediaPlayer"; + public static final String CHANNEL_MEDIA_STOP = "mediaStop"; + public static final String CHANNEL_ANSWER = "answer"; + + // List of all configuration parameters + public static final String CONFIG_HOST = "host"; + public static final String CONFIG_USER = "user"; + public static final String CONFIG_PASSWORD = "password"; + public static final String CONFIG_REFRESH = "refreshInterval"; + public static final String CONFIG_TIMEOUT = "timeout"; + + public static final int MESSAGE_TIMEOUT = 30; +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2Client.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2Client.java new file mode 100644 index 0000000000000..8cf8da55d5321 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2Client.java @@ -0,0 +1,351 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import java.io.IOException; +import java.io.StringReader; +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.util.UrlEncoded; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * The {@link Enigma2Client} class is responsible for communicating with the Enigma2 device. + * + * @see OpenWebif-API-documentation + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +public class Enigma2Client { + private final Logger logger = LoggerFactory.getLogger(Enigma2Client.class); + + static final String PATH_REMOTE_CONTROL = "/web/remotecontrol?command="; + static final String PATH_POWER = "/web/powerstate"; + static final String PATH_VOLUME = "/web/vol"; + static final String PATH_SET_VOLUME = "/web/vol?set=set"; + static final String PATH_TOGGLE_MUTE = "/web/vol?set=mute"; + static final String PATH_TOGGLE_POWER = "/web/powerstate?newstate=0"; + static final String PATH_MESSAGE = "/web/message?type="; + static final String PATH_ALL_SERVICES = "/web/getallservices"; + static final String PATH_ZAP = "/web/zap?sRef="; + static final String PATH_CHANNEL = "/web/subservices"; + static final String PATH_EPG = "/web/epgservicenow?sRef="; + static final String PATH_ANSWER = "/web/messageanswer?getanswer=now"; + static final int TYPE_QUESTION = 0; + static final int TYPE_INFO = 1; + static final int TYPE_WARNING = 2; + static final int TYPE_ERROR = 3; + private final Map channels = new ConcurrentHashMap<>(); + private final String host; + private boolean power; + private String channel = ""; + private String title = ""; + private String description = ""; + private String answer = ""; + private int volume = 0; + private boolean mute; + private boolean online; + private boolean initialized; + private boolean asking; + private LocalDateTime lastAnswerTime = LocalDateTime.of(2020, 1, 1, 0, 0); // Date in the past + private final Enigma2HttpClient enigma2HttpClient; + private final DocumentBuilderFactory factory; + + public Enigma2Client(String host, @Nullable String user, @Nullable String password, int requestTimeout) { + this.enigma2HttpClient = new Enigma2HttpClient(requestTimeout); + this.factory = DocumentBuilderFactory.newInstance(); + if (StringUtils.isNotEmpty(user) && StringUtils.isNotEmpty(password)) { + this.host = "http://" + user + ":" + password + "@" + host; + } else { + this.host = "http://" + host; + } + } + + public boolean refresh() { + boolean wasOnline = online; + refreshPower(); + if (!wasOnline && online) { + // Only refresh all services if the box changed from offline to online and power is on + // because it is a performance intensive action. + refreshAllServices(); + } + refreshChannel(); + refreshEpg(); + refreshVolume(); + refreshAnswer(); + return online; + } + + public void refreshPower() { + Optional document = transmitWithResult(PATH_POWER); + if (document.isPresent()) { + online = true; + processPowerResult(document.get()); + } else { + online = false; + power = false; + } + initialized = true; + } + + public void refreshAllServices() { + if (power || channels.isEmpty()) { + transmitWithResult(PATH_ALL_SERVICES).ifPresent(this::processAllServicesResult); + } + } + + public void refreshChannel() { + if (power) { + transmitWithResult(PATH_CHANNEL).ifPresent(this::processChannelResult); + } + } + + public void refreshAnswer() { + if (asking) { + transmitWithResult(PATH_ANSWER).ifPresent(this::processAnswerResult); + } + } + + public void refreshVolume() { + if (power) { + transmitWithResult(PATH_VOLUME).ifPresent(this::processVolumeResult); + } + } + + public void refreshEpg() { + if (power) { + Optional.ofNullable(channels.get(channel)) + .flatMap(name -> transmitWithResult(PATH_EPG + UrlEncoded.encodeString(name))) + .ifPresent(this::processEpgResult); + } + } + + private Optional transmitWithResult(String path) { + try { + Optional xml = transmit(path); + if(xml.isPresent()) { + DocumentBuilder builder = factory.newDocumentBuilder(); + return Optional.ofNullable(builder.parse(new InputSource(new StringReader(xml.get())))); + } + return Optional.empty(); + } catch (IOException | SAXException | ParserConfigurationException | IllegalArgumentException e) { + if (online || !initialized) { + logger.debug("Error on transmit {}{}.", host, path, e); + } + return Optional.empty(); + } + } + + private Optional transmit(String path) { + String url = host + path; + try { + logger.debug("Transmitting {}", url); + String result = getEnigma2HttpClient().get(url); + logger.debug("Transmitting result is {}", result); + return Optional.ofNullable(result); + } catch (IOException | IllegalArgumentException e) { + if (online || !initialized) { + logger.debug("Error on transmit {}.", url, e); + } + return Optional.empty(); + } + } + + public void setMute(boolean mute) { + refreshVolume(); + if (this.mute != mute) { + transmitWithResult(PATH_TOGGLE_MUTE).ifPresent(this::processVolumeResult); + } + } + + public void setPower(boolean power) { + refreshPower(); + if (this.power != power) { + transmitWithResult(PATH_TOGGLE_POWER).ifPresent(this::processPowerResult); + } + } + + public void setVolume(int volume) { + transmitWithResult(PATH_SET_VOLUME + volume).ifPresent(this::processVolumeResult); + } + + public void setChannel(String name) { + if (channels.containsKey(name)) { + String id = channels.get(name); + transmitWithResult(PATH_ZAP + UrlEncoded.encodeString(id)).ifPresent(document -> channel = name); + } else { + logger.warn("Channel {} not found.", name); + } + } + + public void sendRcCommand(int key) { + transmit(PATH_REMOTE_CONTROL + key); + } + + public void sendError(int timeout, String text) { + sendMessage(TYPE_ERROR, timeout, text); + } + + public void sendWarning(int timeout, String text) { + sendMessage(TYPE_WARNING, timeout, text); + } + + public void sendInfo(int timeout, String text) { + sendMessage(TYPE_INFO, timeout, text); + } + + public void sendQuestion(int timeout, String text) { + asking = true; + sendMessage(TYPE_QUESTION, timeout, text); + } + + private void sendMessage(int type, int timeout, String text) { + transmit(PATH_MESSAGE + type + "&timeout=" + timeout + "&text=" + UrlEncoded.encodeString(text)); + } + + private void processPowerResult(Document document) { + power = !getBoolean(document, "e2instandby"); + if (!power) { + title = ""; + description = ""; + channel = ""; + } + } + + private void processChannelResult(Document document) { + channel = getString(document, "e2servicename"); + // Add channel-Reference-ID if not known + if (!channels.containsKey(channel)) { + channels.put(channel, getString(document, "e2servicereference")); + } + } + + private void processAnswerResult(Document document) { + if (asking) { + boolean state = getBoolean(document, "e2state"); + if (state) { + String[] text = getString(document, "e2statetext").split(" "); + answer = text[text.length - 1].replace("!", ""); + asking = false; + lastAnswerTime = LocalDateTime.now(); + } + } + } + + private void processVolumeResult(Document document) { + volume = getInt(document, "e2current"); + mute = getBoolean(document, "e2ismuted"); + } + + private void processEpgResult(Document document) { + title = getString(document, "e2eventtitle"); + description = getString(document, "e2eventdescription"); + } + + private void processAllServicesResult(Document document) { + NodeList bouquetList = document.getElementsByTagName("e2bouquet"); + channels.clear(); + for (int i = 0; i < bouquetList.getLength(); i++) { + Element bouquet = (Element) bouquetList.item(i); + NodeList serviceList = bouquet.getElementsByTagName("e2service"); + for (int j = 0; j < serviceList.getLength(); j++) { + Element service = (Element) serviceList.item(j); + String id = service.getElementsByTagName("e2servicereference").item(0).getTextContent(); + String name = service.getElementsByTagName("e2servicename").item(0).getTextContent(); + channels.put(name, id); + } + } + } + + private String getString(Document document, String elementId) { + return Optional.ofNullable(document.getElementsByTagName(elementId)).map(nodeList -> nodeList.item(0)) + .map(Node::getTextContent).map(String::trim).orElse(""); + } + + private boolean getBoolean(Document document, String elementId) { + return Boolean.parseBoolean(getString(document, elementId)); + } + + private int getInt(Document document, String elementId) { + try { + return Integer.parseInt(getString(document, elementId)); + } catch (NumberFormatException e) { + return 0; + } + } + + public int getVolume() { + return volume; + } + + public boolean isMute() { + return mute; + } + + public boolean isPower() { + return power; + } + + public LocalDateTime getLastAnswerTime() { + return lastAnswerTime; + } + + public String getChannel() { + return channel; + } + + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public String getAnswer() { + return answer; + } + + public Collection getChannels() { + return channels.keySet(); + } + + /** + * Getter for Test-Injection + * + * @return HttpGet. + */ + Enigma2HttpClient getEnigma2HttpClient() { + return enigma2HttpClient; + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2Configuration.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2Configuration.java new file mode 100644 index 0000000000000..23830fd8354ad --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2Configuration.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link Enigma2Configuration} class contains fields mapping thing configuration parameters. + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +public class Enigma2Configuration { + + /** + * Hostname or IP address of the Enigma2 device. + */ + public String host = ""; + /** + * The refresh interval in seconds. + */ + public int refreshInterval = 5; + /** + * The refresh interval in seconds. + */ + public int timeout = 5; + /** + * The Username of the Enigma2 Web API. + */ + public String user = ""; + /** + * The Password of the Enigma2 Web API. + */ + public String password = ""; +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2HandlerFactory.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2HandlerFactory.java new file mode 100644 index 0000000000000..9625a3a2377ef --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2HandlerFactory.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import static org.openhab.binding.enigma2.internal.Enigma2BindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.enigma2.handler.Enigma2Handler; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link Enigma2HandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.enigma2", service = ThingHandlerFactory.class) +public class Enigma2HandlerFactory extends BaseThingHandlerFactory { + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_DEVICE.equals(thingTypeUID)) { + return new Enigma2Handler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2HttpClient.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2HttpClient.java new file mode 100644 index 0000000000000..a0c8e70b8d4ae --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2HttpClient.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.io.net.http.HttpUtil; + +import java.io.IOException; +import java.util.regex.Pattern; + +/** + * The {@link Enigma2HttpClient} class is responsible for sending HTTP-Get requests to the Enigma2 device. + * It is devided from {@link Enigma2Client} for better testing purpose. + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +public class Enigma2HttpClient { + public static final Pattern PATTERN = Pattern.compile("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD\\u10000-\\u10FFF]+"); + private final int timeout; + + public Enigma2HttpClient(int timeout) { + this.timeout = timeout; + } + + public String get(String url) throws IOException, IllegalArgumentException { + String xml = HttpUtil.executeUrl("GET", url, timeout * 1000); + // remove some unsupported xml-characters + return PATTERN.matcher(xml).replaceAll(""); + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2RemoteKey.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2RemoteKey.java new file mode 100644 index 0000000000000..4492e11d1a445 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/Enigma2RemoteKey.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link Enigma2RemoteKey} class defines the remote keys of an enigma2 device + * used across the whole binding. + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +public enum Enigma2RemoteKey { + POWER(116), + + KEY_0(11), + KEY_1(2), + KEY_2(3), + KEY_3(4), + KEY_4(5), + KEY_5(6), + KEY_6(7), + KEY_7(8), + KEY_8(9), + KEY_9(10), + + ARROW_LEFT(412), + ARROW_RIGHT(407), + + VOLUME_DOWN(114), + VOLUME_UP(115), + MUTE(113), + + CHANNEL_UP(402), + CHANNEL_DOWN(403), + + LEFT(105), + RIGHT(106), + UP(103), + DOWN(108), + OK(352), + EXIT(174), + + RED(398), + GREEN(399), + YELLOW(400), + BLUE(401), + + PLAY(207), + PAUSE(119), + STOP(128), + RECORD(167), + FAST_FORWARD(208), + FAST_BACKWARD(168), + + TV(377), + RADIO(385), + AUDIO(392), + VIDEO(393), + TEXT(388), + INFO(358), + MENU(139), + HELP(138), + SUBTITLE(370), + EPG(358); + + private final int value; + + Enigma2RemoteKey(int value) { + this.value = value; + } + + public int getValue() { + return value; + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/discovery/Enigma2DiscoveryParticipant.java b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/discovery/Enigma2DiscoveryParticipant.java new file mode 100644 index 0000000000000..098da525d6096 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/java/org/openhab/binding/enigma2/internal/discovery/Enigma2DiscoveryParticipant.java @@ -0,0 +1,111 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal.discovery; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + +import javax.jmdns.ServiceInfo; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.config.discovery.mdns.MDNSDiscoveryParticipant; +import org.openhab.binding.enigma2.internal.Enigma2BindingConstants; +import org.openhab.binding.enigma2.internal.Enigma2HttpClient; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link Enigma2DiscoveryParticipant} is responsible processing the + * results of searches for mDNS services of type _http._tcp.local. and finding a webinterface + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +@Component(service = MDNSDiscoveryParticipant.class, immediate = true) +public class Enigma2DiscoveryParticipant implements MDNSDiscoveryParticipant { + + private final Logger logger = LoggerFactory.getLogger(Enigma2DiscoveryParticipant.class); + + @Override + public Set getSupportedThingTypeUIDs() { + return Enigma2BindingConstants.SUPPORTED_THING_TYPES_UIDS; + } + + @Override + public @Nullable DiscoveryResult createResult(ServiceInfo info) { + logger.debug("ServiceInfo {}", info); + String ipAddress = getIPAddress(info); + if (ipAddress != null && isEnigma2Device(ipAddress)) { + logger.debug("Enigma2 device discovered: IP-Adress={}, name={}", ipAddress, info.getName()); + ThingUID uid = getThingUID(info); + if(uid != null) { + Map properties = new HashMap<>(); + properties.put(Enigma2BindingConstants.CONFIG_HOST, ipAddress); + properties.put(Enigma2BindingConstants.CONFIG_REFRESH, 5); + properties.put(Enigma2BindingConstants.CONFIG_TIMEOUT, 5); + return DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(info.getName()).build(); + } + } + return null; + } + + @Override + public @Nullable ThingUID getThingUID(ServiceInfo info) { + logger.debug("ServiceInfo {}", info); + String ipAddress = getIPAddress(info); + if( ipAddress != null) { + return new ThingUID(Enigma2BindingConstants.THING_TYPE_DEVICE, ipAddress.replace(".", "_")); + } + return null; + } + + @Override + public String getServiceType() { + return "_http._tcp.local."; + } + + private boolean isEnigma2Device(String ipAddress) { + try { + return getEnigma2HttpClient().get("http://" + ipAddress + "/web/about").contains("e2enigmaversion"); + } catch (IOException ignore) { + return false; + } + } + + private @Nullable String getIPAddress(ServiceInfo info) { + InetAddress[] addresses = info.getInet4Addresses(); + if (addresses.length > 1) { + logger.debug("Enigma2 device {} reports multiple addresses - using the first one! {}", info.getName(), addresses); + } + return Stream.of(addresses).findFirst().map(InetAddress::getHostAddress).orElse(null); + } + + /** + * Getter for Test-Injection + * + * @return HttpGet. + */ + Enigma2HttpClient getEnigma2HttpClient() { + return new Enigma2HttpClient(5); + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..d6906c6b8a1b4 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + Enigma2 Binding + This is the binding for Enigma2. + Guido Dolfen + + diff --git a/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/i18n/enigma2.properties b/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/i18n/enigma2.properties new file mode 100644 index 0000000000000..3eca7bac7b98d --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/i18n/enigma2.properties @@ -0,0 +1,36 @@ +# FIXME: please substitute the xx_XX with a proper locale, ie. de_DE +# FIXME: please do not add the file to the repo if you add or change no content +# binding +binding.enigma2.name = Enigma2 Binding +binding.enigma2.description = This is the binding for Enigma2 + +# thing types +thing-type.enigma2.device.label = Enigma2 +thing-type.enigma2.device.description = The Thing represents an Enigma2 device + +# thing type config description +thing-type.config.enigma2.host.label = Host Address +thing-type.config.enigma2.host.description = Hostname or IP address of the Enigma2 device + +# channel types +channel-type.enigma2.power.label = Power +channel-type.enigma2.power.description = Setting the power to on/off. + +# actions +action.enigma2.send-rc-button.label=sendRcCommand +action.enigma2.send-rc-button.description=Send an Remote Control Command +action-input.enigma2.rc-button.label=rcButton +action-input.enigma2.rc-button.description=The Remote Control Button + +action.enigma2.send-info.label=sendInfo +action.enigma2.send-info.description=Send an info message to the TV screen +action.enigma2.send-warning.label=sendWarning +action.enigma2.send-warning.description=Send an warning message to the TV screen +action.enigma2.send-error.label=sendError +action.enigma2.send-error.description=Send an error message to the TV screen +action.enigma2.send-question.label=sendQuestion +action.enigma2.send-question.description=Send a question message to the TV screen +action-input.enigma2.text.label=text +action-input.enigma2.text.description=The message text +action-input.enigma2.timeout.label=timeout +action-input.enigma2.timeout.description=The timeout in seconds diff --git a/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..c52f4408f34ed --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/main/resources/ESH-INF/thing/thing-types.xml @@ -0,0 +1,99 @@ + + + + + The Thing represents an Enigma2 device + + + + + + + + + + + + + + network-address + + Hostname or IP address of the Enigma2 device. + + + + The refresh interval in seconds. + 5 + + + + The timeout for reading from the device in seconds. + 5 + + + + The Username of the Enigma2 Web API. + + + password + + The Password of the Enigma2 Web API. + + + + + Switch + + Setting the power to on/off. + + + Switch + + Current Mute Setting + SoundVolume + + + Dimmer + + Current Volume Setting + SoundVolume + + + + String + + Current Channel + + + String + + Current Title of the current Channel + + + + String + + Current Description of the current Channel + + + + Player + + Control media (e.g. audio or video) playback + MediaControl + + + Switch + + Stop Playback + + + String + + Receives an answer to a send question of the device + + + diff --git a/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/actions/Enigma2ActionsTest.java b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/actions/Enigma2ActionsTest.java new file mode 100644 index 0000000000000..eadf7465877c5 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/actions/Enigma2ActionsTest.java @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.actions; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.*; + +import org.openhab.binding.enigma2.handler.Enigma2Handler; +import org.openhab.binding.enigma2.internal.Enigma2BindingConstants; + +/** + * The {@link Enigma2ActionsTest} class is responsible for testing {@link Enigma2Actions}. + * + * @author Guido Dolfen - Initial contribution + */ +@SuppressWarnings("null") +@NonNullByDefault +public class Enigma2ActionsTest { + @Nullable + private Enigma2Actions enigma2Actions; + @Nullable + private Enigma2Handler enigma2Handler; + public static final String SOME_TEXT = "some Text"; + + @Before + public void setUp() { + enigma2Handler = mock(Enigma2Handler.class); + enigma2Actions = new Enigma2Actions(); + enigma2Actions.setThingHandler(enigma2Handler); + } + + @Test + public void testGetThingHandler() { + assertThat(enigma2Actions.getThingHandler(), is(enigma2Handler)); + } + + @Test + public void testSendRcCommand() { + enigma2Actions.sendRcCommand("KEY_1"); + verify(enigma2Handler).sendRcCommand("KEY_1"); + } + + @Test + public void testSendInfo() { + enigma2Actions.sendInfo(SOME_TEXT); + verify(enigma2Handler).sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendInfoTimeout() { + enigma2Actions.sendInfo(SOME_TEXT, 10); + verify(enigma2Handler).sendInfo(10, SOME_TEXT); + } + + @Test + public void testSendError() { + enigma2Actions.sendError(SOME_TEXT); + verify(enigma2Handler).sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendErrorTimeout() { + enigma2Actions.sendError(SOME_TEXT, 10); + verify(enigma2Handler).sendError(10, SOME_TEXT); + } + + @Test + public void testSendWarning() { + enigma2Actions.sendWarning(SOME_TEXT); + verify(enigma2Handler).sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendWarningTimeout() { + enigma2Actions.sendWarning(SOME_TEXT, 10); + verify(enigma2Handler).sendWarning(10, SOME_TEXT); + } + + @Test + public void testSendQuestion() { + enigma2Actions.sendQuestion(SOME_TEXT); + verify(enigma2Handler).sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendQuestionTimeout() { + enigma2Actions.sendQuestion(SOME_TEXT, 10); + verify(enigma2Handler).sendQuestion(10, SOME_TEXT); + } + + @Test + public void testSendRcCommandStatic() { + Enigma2Actions.sendRcCommand(enigma2Actions, "KEY_1"); + verify(enigma2Handler).sendRcCommand("KEY_1"); + } + + @Test(expected = IllegalArgumentException.class) + public void testSendRcCommandStaticWithException() { + Enigma2Actions.sendRcCommand(null, "KEY_1"); + } + + @Test + public void testSendInfoStatic() { + Enigma2Actions.sendInfo(enigma2Actions, SOME_TEXT); + verify(enigma2Handler).sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendInfoTimeoutStatic() { + Enigma2Actions.sendInfo(enigma2Actions, SOME_TEXT, 10); + verify(enigma2Handler).sendInfo(10, SOME_TEXT); + } + + @Test(expected = IllegalArgumentException.class) + public void testSendInfoStaticWithException() { + Enigma2Actions.sendInfo(null, SOME_TEXT); + } + + @Test + public void testSendErrorStatic() { + Enigma2Actions.sendError(enigma2Actions, SOME_TEXT); + verify(enigma2Handler).sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendErrorTimeoutStatic() { + Enigma2Actions.sendError(enigma2Actions, SOME_TEXT, 10); + verify(enigma2Handler).sendError(10, SOME_TEXT); + } + + @Test(expected = IllegalArgumentException.class) + public void testSendErrorStaticWithException() { + Enigma2Actions.sendError(null, SOME_TEXT); + } + + @Test + public void testSendWarningStatic() { + Enigma2Actions.sendWarning(enigma2Actions, SOME_TEXT); + verify(enigma2Handler).sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendWarningTimeoutStatic() { + Enigma2Actions.sendWarning(enigma2Actions, SOME_TEXT, 10); + verify(enigma2Handler).sendWarning(10, SOME_TEXT); + } + + @Test(expected = IllegalArgumentException.class) + public void testSendWarningStaticWithException() { + Enigma2Actions.sendWarning(null, SOME_TEXT); + } + + @Test + public void testSendQuestionStatic() { + Enigma2Actions.sendQuestion(enigma2Actions, SOME_TEXT); + verify(enigma2Handler).sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendQuestionTimeoutStatic() { + Enigma2Actions.sendQuestion(enigma2Actions, SOME_TEXT, 10); + verify(enigma2Handler).sendQuestion(10, SOME_TEXT); + } + + @Test(expected = IllegalArgumentException.class) + public void testSendQuestionStaticWithException() { + Enigma2Actions.sendQuestion(null, SOME_TEXT); + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/handler/Enigma2HandlerTest.java b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/handler/Enigma2HandlerTest.java new file mode 100644 index 0000000000000..657a84e09b9d5 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/handler/Enigma2HandlerTest.java @@ -0,0 +1,381 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.library.types.*; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerCallback; +import org.eclipse.smarthome.core.types.RefreshType; +import org.junit.Before; +import org.junit.Test; +import org.openhab.binding.enigma2.actions.Enigma2Actions; +import org.openhab.binding.enigma2.internal.Enigma2BindingConstants; +import org.openhab.binding.enigma2.internal.Enigma2Client; +import org.openhab.binding.enigma2.internal.Enigma2Configuration; +import org.openhab.binding.enigma2.internal.Enigma2RemoteKey; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.Optional; + +import static org.eclipse.jdt.annotation.Checks.requireNonNull; +import static org.mockito.Mockito.*; +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; + +/** + * The {@link Enigma2HandlerTest} class is responsible for testing {@link Enigma2Handler}. + * + * @author Guido Dolfen - Initial contribution + */ +@SuppressWarnings({ "null", "unchecked" }) +@NonNullByDefault +public class Enigma2HandlerTest { + public static final String CHANNEL_UID_PREFIX = "enigma2:device:192_168_0_3:"; + public static final String SOME_TEXT = "some Text"; + @Nullable + private Enigma2Handler enigma2Handler; + @Nullable + private Enigma2Client enigma2Client; + @Nullable + private Thing thing; + @Nullable + private Configuration configuration; + @Nullable + private ThingHandlerCallback callback; + + @Before + public void setUp() { + enigma2Client = mock(Enigma2Client.class); + thing = mock(Thing.class); + callback = mock(ThingHandlerCallback.class); + configuration = mock(Configuration.class); + when(thing.getConfiguration()).thenReturn(requireNonNull(configuration)); + when(configuration.as(Enigma2Configuration.class)).thenReturn(new Enigma2Configuration()); + enigma2Handler = spy(new Enigma2Handler(requireNonNull(thing))); + enigma2Handler.setCallback(callback); + when(enigma2Handler.getEnigma2Client()).thenReturn(Optional.of(requireNonNull(enigma2Client))); + } + + @Test + public void testSendRcCommand() { + enigma2Handler.sendRcCommand("KEY_1"); + verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.KEY_1.getValue()); + } + + @Test + public void testSendInfo() { + enigma2Handler.sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + verify(enigma2Client).sendInfo(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendWarning() { + enigma2Handler.sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + verify(enigma2Client).sendWarning(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendError() { + enigma2Handler.sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + verify(enigma2Client).sendError(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testSendQuestion() { + enigma2Handler.sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + verify(enigma2Client).sendQuestion(Enigma2BindingConstants.MESSAGE_TIMEOUT, SOME_TEXT); + } + + @Test + public void testGetEnigma2Client() { + enigma2Handler = new Enigma2Handler(requireNonNull(thing)); + assertThat(enigma2Handler.getEnigma2Client(), is(Optional.empty())); + } + + @Test + public void testGetServices() { + enigma2Handler = new Enigma2Handler(requireNonNull(thing)); + assertThat(enigma2Handler.getServices(), contains(Enigma2Actions.class)); + } + + @Test + public void testSendRcCommandUnsupported() { + enigma2Handler.sendRcCommand("KEY_X"); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandPowerRefreshFalse() { + when(enigma2Client.isPower()).thenReturn(false); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshPower(); + verify(callback).stateUpdated(channelUID, OnOffType.OFF); + } + + @Test + public void testHandleCommandPowerRefreshTrue() { + when(enigma2Client.isPower()).thenReturn(true); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshPower(); + verify(callback).stateUpdated(channelUID, OnOffType.ON); + } + + @Test + public void testHandleCommandPowerOn() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER); + enigma2Handler.handleCommand(channelUID, OnOffType.ON); + verify(enigma2Client).setPower(true); + } + + @Test + public void testHandleCommandPowerOff() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER); + enigma2Handler.handleCommand(channelUID, OnOffType.OFF); + verify(enigma2Client).setPower(false); + } + + @Test + public void testHandleCommandPowerUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_POWER); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandChannelRefresh() { + when(enigma2Client.getChannel()).thenReturn(SOME_TEXT); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_CHANNEL); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshChannel(); + verify(callback).stateUpdated(channelUID, new StringType(SOME_TEXT)); + } + + @Test + public void testHandleCommandMuteRefreshFalse() { + when(enigma2Client.isMute()).thenReturn(false); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshVolume(); + verify(callback).stateUpdated(channelUID, OnOffType.OFF); + } + + @Test + public void testHandleCommandMuteRefreshTrue() { + when(enigma2Client.isMute()).thenReturn(true); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshVolume(); + verify(callback).stateUpdated(channelUID, OnOffType.ON); + } + + @Test + public void testHandleCommandMuteOn() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE); + enigma2Handler.handleCommand(channelUID, OnOffType.ON); + verify(enigma2Client).setMute(true); + } + + @Test + public void testHandleCommandMuteOff() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE); + enigma2Handler.handleCommand(channelUID, OnOffType.OFF); + verify(enigma2Client).setMute(false); + } + + @Test + public void testHandleCommandMuteUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MUTE); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandChannelString() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_CHANNEL); + enigma2Handler.handleCommand(channelUID, new StringType(SOME_TEXT)); + verify(enigma2Client).setChannel(SOME_TEXT); + } + + @Test + public void testHandleCommandChannelUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_CHANNEL); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandMediaPlayerRefresh() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandMediaPlay() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PLAY); + verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.PLAY.getValue()); + } + + @Test + public void testHandleCommandMediaPause() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.PAUSE.getValue()); + } + + @Test + public void testHandleCommandMediaNext() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER); + enigma2Handler.handleCommand(channelUID, NextPreviousType.NEXT); + verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.FAST_FORWARD.getValue()); + } + + @Test + public void testHandleCommandMediaPrevious() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER); + enigma2Handler.handleCommand(channelUID, NextPreviousType.PREVIOUS); + verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.FAST_BACKWARD.getValue()); + } + + @Test + public void testHandleCommandMediaPlayerUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_PLAYER); + enigma2Handler.handleCommand(channelUID, OnOffType.ON); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandMediaStopRefresh() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_STOP); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandMediaStopOn() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_STOP); + enigma2Handler.handleCommand(channelUID, OnOffType.ON); + verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.STOP.getValue()); + } + + @Test + public void testHandleCommandMediaStopOff() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_STOP); + enigma2Handler.handleCommand(channelUID, OnOffType.OFF); + verify(enigma2Client).sendRcCommand(Enigma2RemoteKey.STOP.getValue()); + } + + @Test + public void testHandleCommandMediaStopUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_MEDIA_STOP); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandTitleUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_TITLE); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandTitleRefresh() { + when(enigma2Client.getTitle()).thenReturn(SOME_TEXT); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_TITLE); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshEpg(); + verify(callback).stateUpdated(channelUID, new StringType(SOME_TEXT)); + } + + @Test + public void testHandleCommandAnswerUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_ANSWER); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandAnswerRefresh() { + when(enigma2Client.getAnswer()).thenReturn(SOME_TEXT); + when(enigma2Client.getLastAnswerTime()).thenReturn(LocalDateTime.now().plus(1, ChronoUnit.SECONDS)); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_ANSWER); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshAnswer(); + verify(callback).stateUpdated(channelUID, new StringType(SOME_TEXT)); + } + + @Test + public void testHandleCommandAnswerRefreshFalse() { + when(enigma2Client.getAnswer()).thenReturn(SOME_TEXT); + when(enigma2Client.getLastAnswerTime()).thenReturn(LocalDateTime.of(2020, 1, 1, 0, 0)); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_ANSWER); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshAnswer(); + verifyNoInteractions(callback); + } + + @Test + public void testHandleCommandDescriptionUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_DESCRIPTION); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verifyNoInteractions(enigma2Client); + } + + @Test + public void testHandleCommandDescriptionRefresh() { + when(enigma2Client.getDescription()).thenReturn(SOME_TEXT); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_DESCRIPTION); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshEpg(); + verify(callback).stateUpdated(channelUID, new StringType(SOME_TEXT)); + } + + @Test + public void testHandleCommandVolumeRefresh() { + when(enigma2Client.getVolume()).thenReturn(35); + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_VOLUME); + enigma2Handler.handleCommand(channelUID, RefreshType.REFRESH); + verify(enigma2Client).refreshVolume(); + verify(callback).stateUpdated(channelUID, new PercentType(35)); + } + + @Test + public void testHandleCommandVolumePercent() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_VOLUME); + enigma2Handler.handleCommand(channelUID, new PercentType(30)); + verify(enigma2Client).setVolume(30); + } + + @Test + public void testHandleCommandVolumeDecimal() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_VOLUME); + enigma2Handler.handleCommand(channelUID, new DecimalType(40)); + verify(enigma2Client).setVolume(40); + } + + @Test + public void testHandleCommandVolumeUnsupported() { + ChannelUID channelUID = new ChannelUID(CHANNEL_UID_PREFIX + Enigma2BindingConstants.CHANNEL_VOLUME); + enigma2Handler.handleCommand(channelUID, PlayPauseType.PAUSE); + verifyNoInteractions(enigma2Client); + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2ClientTest.java b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2ClientTest.java new file mode 100644 index 0000000000000..c38e07b187f81 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2ClientTest.java @@ -0,0 +1,323 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.time.LocalDateTime; + +import static org.eclipse.jdt.annotation.Checks.requireNonNull; +import static org.mockito.Mockito.*; +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; + +/** + * The {@link Enigma2ClientTest} class is responsible for testing {@link Enigma2Client}. + * + * @author Guido Dolfen - Initial contribution + */ +@SuppressWarnings({ "null" }) +@NonNullByDefault +public class Enigma2ClientTest { + public static final String HOST = "http://user:password@localhost:8080"; + public static final String SOME_TEXT = "some Text"; + public static final String SOME_TEXT_ENCODED = "some+Text"; + @Nullable + private Enigma2Client enigma2Client; + @Nullable + private Enigma2HttpClient enigma2HttpClient; + + @Before + public void setUp() throws IOException { + enigma2HttpClient = mock(Enigma2HttpClient.class); + enigma2Client = spy(new Enigma2Client("localhost:8080", "user", "password", 5)); + when(enigma2Client.getEnigma2HttpClient()).thenReturn(requireNonNull(enigma2HttpClient)); + when(enigma2HttpClient.get(anyString())).thenReturn(""); + } + + @Test + public void testSetPowerFalse() throws IOException { + whenStandby("true"); + enigma2Client.setPower(false); + verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_POWER); + verifyNoMoreInteractions(enigma2HttpClient); + } + + @Test + public void testSetPower() throws IOException { + whenStandby("true"); + enigma2Client.setPower(true); + verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_TOGGLE_POWER); + } + + @Test + public void testSetVolume() throws IOException { + enigma2Client.setVolume(20); + verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_SET_VOLUME + 20); + } + + @Test + public void testSetChannel() throws IOException { + whenStandby("false"); + whenAllServices(); + enigma2Client.refreshPower(); + enigma2Client.refreshAllServices(); + enigma2Client.setChannel("Channel 3"); + verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_ZAP + 3); + } + + @Test + public void testSetChannelUnknown() throws IOException { + enigma2Client.setChannel("Channel 3"); + verifyNoInteractions(enigma2HttpClient); + } + + @Test + public void testSetMuteFalse() throws IOException { + whenStandby("false"); + whenVolume("10", false); + enigma2Client.refreshPower(); + enigma2Client.setMute(false); + verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_POWER); + verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_VOLUME); + verifyNoMoreInteractions(enigma2HttpClient); + } + + @Test + public void testSetMute() throws IOException { + whenStandby("false"); + whenVolume("10", false); + enigma2Client.refreshPower(); + enigma2Client.setMute(true); + verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_TOGGLE_MUTE); + } + + @Test + public void testSendRcCommand() throws IOException { + enigma2Client.sendRcCommand(2); + verify(enigma2HttpClient).get(HOST + Enigma2Client.PATH_REMOTE_CONTROL + 2); + } + + @Test + public void testSendError() throws IOException { + enigma2Client.sendError(20, SOME_TEXT); + verify(enigma2HttpClient).get(HOST + "/web/message?type=3&timeout=20&text=" + SOME_TEXT_ENCODED); + } + + @Test + public void testSendWarning() throws IOException { + enigma2Client.sendWarning(35, SOME_TEXT); + verify(enigma2HttpClient).get(HOST + "/web/message?type=2&timeout=35&text=" + SOME_TEXT_ENCODED); + } + + @Test + public void testSendInfo() throws IOException { + enigma2Client.sendInfo(40, SOME_TEXT); + verify(enigma2HttpClient).get(HOST + "/web/message?type=1&timeout=40&text=" + SOME_TEXT_ENCODED); + } + + @Test + public void testSendQuestion() throws IOException { + enigma2Client.sendQuestion(50, SOME_TEXT); + verify(enigma2HttpClient).get(HOST + "/web/message?type=0&timeout=50&text=" + SOME_TEXT_ENCODED); + } + + @Test + public void testRefreshPowerTrue() throws IOException { + whenStandby(" FALSE "); + enigma2Client.refreshPower(); + assertThat(enigma2Client.isPower(), is(true)); + } + + @Test + public void testRefreshVolumeMuteTrue() throws IOException { + whenStandby("false"); + whenVolume("30", true); + enigma2Client.refreshPower(); + enigma2Client.refreshVolume(); + assertThat(enigma2Client.isMute(), is(true)); + assertThat(enigma2Client.getVolume(), is(30)); + } + + @Test + public void testRefreshVolumeMuteFalse() throws IOException { + whenStandby("false"); + whenVolume("30", false); + enigma2Client.refreshPower(); + enigma2Client.refreshVolume(); + assertThat(enigma2Client.isMute(), is(false)); + assertThat(enigma2Client.getVolume(), is(30)); + } + + @Test + public void testRefreshVolumePowerOff() throws IOException { + enigma2Client.refreshVolume(); + assertThat(enigma2Client.isMute(), is(false)); + assertThat(enigma2Client.getVolume(), is(0)); + } + + @Test + public void testRefreshPowerFalse() throws IOException { + whenStandby(" TRUE "); + enigma2Client.refreshPower(); + assertThat(enigma2Client.isPower(), is(false)); + } + + @Test + public void testRefreshPowerOffline() throws IOException { + IOException ioException = new IOException(); + when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_POWER)).thenThrow(ioException); + enigma2Client.refreshPower(); + assertThat(enigma2Client.isPower(), is(false)); + } + + @Test + public void testRefreshAllServices() throws IOException { + whenStandby("false"); + whenAllServices(); + enigma2Client.refreshAllServices(); + assertThat(enigma2Client.getChannels(), containsInAnyOrder("Channel 1", "Channel 2", "Channel 3")); + } + + @Test + public void testRefreshChannel() throws IOException { + whenStandby("false"); + whenChannel("2", "Channel 2"); + enigma2Client.refreshPower(); + enigma2Client.refreshChannel(); + assertThat(enigma2Client.getChannel(), is("Channel 2")); + } + + @Test + public void testRefreshEpg() throws IOException { + whenStandby("false"); + whenAllServices(); + whenChannel("2", "Channel 2"); + whenEpg("2", "Title", "Description"); + enigma2Client.refreshPower(); + enigma2Client.refreshAllServices(); + enigma2Client.refreshChannel(); + enigma2Client.refreshEpg(); + assertThat(enigma2Client.getTitle(), is("Title")); + assertThat(enigma2Client.getDescription(), is("Description")); + } + + @Test + public void testRefreshAnswerTimeout() throws IOException { + whenStandby("false"); + whenAnswer("False", "Timeout"); + enigma2Client.refreshPower(); + enigma2Client.refreshAnswer(); + assertThat(enigma2Client.getLastAnswerTime().isAfter(LocalDateTime.of(2020, 1, 1, 0, 0)), is(false)); + assertThat(enigma2Client.getAnswer(), is("")); + } + + @Test + public void testRefreshAnswerNoQuestion() throws IOException { + whenStandby("false"); + whenAnswer("True", "Antwort lautet NEIN!"); + enigma2Client.refreshPower(); + enigma2Client.refreshAnswer(); + assertThat(enigma2Client.getLastAnswerTime().isAfter(LocalDateTime.of(2020, 1, 1, 0, 0)), is(false)); + assertThat(enigma2Client.getAnswer(), is("")); + } + + @Test + public void testRefreshAnswer() throws IOException { + whenStandby("false"); + whenAnswer("True", "Antwort lautet NEIN!"); + enigma2Client.refreshPower(); + enigma2Client.sendQuestion(50, SOME_TEXT); + enigma2Client.refreshAnswer(); + assertThat(enigma2Client.getLastAnswerTime().isAfter(LocalDateTime.of(2020, 1, 1, 0, 0)), is(true)); + assertThat(enigma2Client.getAnswer(), is("NEIN")); + } + + @Test + public void testRefresh() throws IOException { + whenStandby("false"); + whenAllServices(); + whenVolume("A", false); + whenChannel("1", "Channel 1"); + whenEpg("1", "Title", "Description"); + assertThat(enigma2Client.refresh(), is(true)); + assertThat(enigma2Client.isPower(), is(true)); + assertThat(enigma2Client.isMute(), is(false)); + assertThat(enigma2Client.getVolume(), is(0)); + assertThat(enigma2Client.getChannel(), is("Channel 1")); + assertThat(enigma2Client.getTitle(), is("Title")); + assertThat(enigma2Client.getDescription(), is("Description")); + assertThat(enigma2Client.getChannels(), containsInAnyOrder("Channel 1", "Channel 2", "Channel 3")); + } + + @Test + public void testRefreshOffline() throws IOException { + IOException ioException = new IOException(); + when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_POWER)).thenThrow(ioException); + assertThat(enigma2Client.refresh(), is(false)); + assertThat(enigma2Client.isPower(), is(false)); + assertThat(enigma2Client.isMute(), is(false)); + assertThat(enigma2Client.getVolume(), is(0)); + assertThat(enigma2Client.getChannel(), is("")); + assertThat(enigma2Client.getTitle(), is("")); + assertThat(enigma2Client.getDescription(), is("")); + assertThat(enigma2Client.getChannels().isEmpty(), is(true)); + } + + @Test + public void testGetEnigma2HttpClient() { + enigma2Client = new Enigma2Client("http://localhost:8080", null, null, 5); + assertThat(enigma2Client.getEnigma2HttpClient(), is(notNullValue())); + } + + private void whenVolume(String volume, boolean mute) throws IOException { + when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_VOLUME)).thenReturn( + "" + volume + "" + mute + ""); + } + + private void whenEpg(String id, String title, String description) throws IOException { + when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_EPG + id)).thenReturn("" + title + + "" + description + ""); + } + + private void whenAnswer(String state, String answer) throws IOException { + when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_ANSWER)).thenReturn("" + state + + "" + answer + ""); + } + + private void whenStandby(String standby) throws IOException { + when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_POWER)) + .thenReturn("" + standby + ""); + } + + private void whenChannel(String id, String name) throws IOException { + when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_CHANNEL)).thenReturn( + "" + id + "" + name + + ""); + } + + private void whenAllServices() throws IOException { + when(enigma2HttpClient.get(HOST + Enigma2Client.PATH_ALL_SERVICES)) + .thenReturn("" + "" + "" + "" + + "1" + "Channel 1" + + "" + "" + "2" + + "Channel 2" + "" + "" + + "" + "" + "" + "" + + "3" + "Channel 3" + + "" + "" + "" + ""); + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2HandlerFactoryTest.java b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2HandlerFactoryTest.java new file mode 100644 index 0000000000000..e8a55a92a9402 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2HandlerFactoryTest.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.junit.Test; + +import static org.eclipse.jdt.annotation.Checks.requireNonNull; +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.openhab.binding.enigma2.internal.Enigma2BindingConstants.THING_TYPE_DEVICE; + +/** + * The {@link Enigma2HandlerFactoryTest} class is responsible for testing {@link Enigma2HandlerFactory}. + * + * @author Guido Dolfen - Initial contribution + */ +@SuppressWarnings("null") +@NonNullByDefault +public class Enigma2HandlerFactoryTest { + @Nullable + private Thing thing; + @Nullable + private Configuration configuration; + + @Test + public void testSupportsThingType() { + assertThat(new Enigma2HandlerFactory().supportsThingType(Enigma2BindingConstants.THING_TYPE_DEVICE), is(true)); + } + + @Test + public void testSupportsThingTypeFalse() { + assertThat(new Enigma2HandlerFactory().supportsThingType(new ThingTypeUID("any", "device")), is(false)); + } + + @Test + public void testCreateHandlerNull() { + thing = mock(Thing.class); + assertThat(new Enigma2HandlerFactory().createHandler(requireNonNull(thing)), is(nullValue())); + } + + @Test + public void testCreateHandler() { + thing = mock(Thing.class); + configuration = mock(Configuration.class); + when(thing.getConfiguration()).thenReturn(requireNonNull(configuration)); + when(configuration.as(Enigma2Configuration.class)).thenReturn(new Enigma2Configuration()); + when(thing.getThingTypeUID()).thenReturn(THING_TYPE_DEVICE); + assertThat(new Enigma2HandlerFactory().createHandler(requireNonNull(thing)), is(notNullValue())); + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2RemoteKeyTest.java b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2RemoteKeyTest.java new file mode 100644 index 0000000000000..ea5188dc2470a --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/Enigma2RemoteKeyTest.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Test; + +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; + +/** + * The {@link Enigma2RemoteKeyTest} class is responsible for testing {@link Enigma2RemoteKey}. + * + * @author Guido Dolfen - Initial contribution + */ +@NonNullByDefault +public class Enigma2RemoteKeyTest { + @Test + public void testGetValue() { + assertThat(Enigma2RemoteKey.ARROW_LEFT.getValue(), is(412)); + } +} diff --git a/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/discovery/Enigma2DiscoveryParticipantTest.java b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/discovery/Enigma2DiscoveryParticipantTest.java new file mode 100644 index 0000000000000..12d1f74ddd970 --- /dev/null +++ b/bundles/org.openhab.binding.enigma2/src/test/java/org/openhab/binding/enigma2/internal/discovery/Enigma2DiscoveryParticipantTest.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enigma2.internal.discovery; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.junit.Before; +import org.junit.Test; +import org.openhab.binding.enigma2.internal.Enigma2BindingConstants; +import org.openhab.binding.enigma2.internal.Enigma2HttpClient; + +import javax.jmdns.ServiceInfo; + +import java.net.Inet4Address; +import java.net.InetAddress; + +import static org.eclipse.jdt.annotation.Checks.requireNonNull; +import static org.junit.Assert.*; +import static org.hamcrest.Matchers.*; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; + +/** + * The {@link Enigma2DiscoveryParticipantTest} class is responsible for testing {@link Enigma2DiscoveryParticipant}. + * + * @author Guido Dolfen - Initial contribution + */ +@SuppressWarnings({ "null" }) +@NonNullByDefault +public class Enigma2DiscoveryParticipantTest { + @Nullable + private ServiceInfo serviceInfo; + @Nullable + private Enigma2HttpClient enigma2HttpClient; + @Nullable + private Enigma2DiscoveryParticipant enigma2DiscoveryParticipant; + + @Before + public void setUp() { + enigma2HttpClient = mock(Enigma2HttpClient.class); + serviceInfo = mock(ServiceInfo.class); + enigma2DiscoveryParticipant = spy(new Enigma2DiscoveryParticipant()); + when(enigma2DiscoveryParticipant.getEnigma2HttpClient()).thenReturn(requireNonNull(enigma2HttpClient)); + } + + @Test + public void testGetSupportedThingTypeUIDs() { + assertThat(enigma2DiscoveryParticipant.getSupportedThingTypeUIDs(), + contains(Enigma2BindingConstants.THING_TYPE_DEVICE)); + } + + @Test + public void testGetServiceType() { + assertThat(enigma2DiscoveryParticipant.getServiceType(), is("_http._tcp.local.")); + } + + @Test + public void testCreateResult() throws Exception { + when(serviceInfo.getName()).thenReturn("enigma2"); + when(enigma2HttpClient.get("http://192.168.10.3/web/about")) + .thenReturn("2020-01-11"); + when(serviceInfo.getInet4Addresses()) + .thenReturn(new Inet4Address[] { (Inet4Address) InetAddress.getAllByName("192.168.10.3")[0] }); + DiscoveryResult discoveryResult = enigma2DiscoveryParticipant.createResult(requireNonNull(serviceInfo)); + assertThat(discoveryResult, is(notNullValue())); + assertThat(discoveryResult.getLabel(), is("enigma2")); + assertThat(discoveryResult.getThingUID(), + is(new ThingUID(Enigma2BindingConstants.THING_TYPE_DEVICE, "192_168_10_3"))); + assertThat(discoveryResult.getProperties(), is(notNullValue())); + assertThat(discoveryResult.getProperties(), hasEntry(Enigma2BindingConstants.CONFIG_HOST, "192.168.10.3")); + assertThat(discoveryResult.getProperties(), + hasEntry(Enigma2BindingConstants.CONFIG_REFRESH, 5)); + assertThat(discoveryResult.getProperties(), + hasEntry(Enigma2BindingConstants.CONFIG_TIMEOUT, 5)); + } + + @Test + public void testCreateResultNotFound() throws Exception { + when(enigma2HttpClient.get("http://192.168.10.3/web/about")).thenReturn("any"); + when(serviceInfo.getInet4Addresses()) + .thenReturn(new Inet4Address[] { (Inet4Address) InetAddress.getAllByName("192.168.10.3")[0] }); + assertThat(enigma2DiscoveryParticipant.createResult(requireNonNull(serviceInfo)), is(nullValue())); + } + + @Test + public void testGetThingUID() throws Exception { + when(serviceInfo.getInet4Addresses()) + .thenReturn(new Inet4Address[] { (Inet4Address) InetAddress.getAllByName("192.168.10.3")[0] }); + assertThat(enigma2DiscoveryParticipant.getThingUID(requireNonNull(serviceInfo)), + is(new ThingUID(Enigma2BindingConstants.THING_TYPE_DEVICE, "192_168_10_3"))); + } + + @Test + public void testGetThingUIDTwoAddresses() throws Exception { + when(serviceInfo.getName()).thenReturn("enigma2"); + Inet4Address[] addresses = { (Inet4Address) InetAddress.getAllByName("192.168.10.3")[0], + (Inet4Address) InetAddress.getAllByName("192.168.10.4")[0] }; + when(serviceInfo.getInet4Addresses()).thenReturn(addresses); + assertThat(enigma2DiscoveryParticipant.getThingUID(requireNonNull(serviceInfo)), + is(new ThingUID(Enigma2BindingConstants.THING_TYPE_DEVICE, "192_168_10_3"))); + } +} diff --git a/bundles/org.openhab.binding.enocean/pom.xml b/bundles/org.openhab.binding.enocean/pom.xml index e6413abc03169..a8805b7297c1b 100644 --- a/bundles/org.openhab.binding.enocean/pom.xml +++ b/bundles/org.openhab.binding.enocean/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.enocean diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelDimmerConfig.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelDimmerConfig.java index 0aa71f74b3121..799bf9a09691d 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelDimmerConfig.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelDimmerConfig.java @@ -21,5 +21,4 @@ public class EnOceanChannelDimmerConfig { public int rampingTime = 0; public boolean eltakoDimmer = true; public boolean storeValue = false; - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/discovery/EnOceanDeviceDiscoveryService.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/discovery/EnOceanDeviceDiscoveryService.java index ca66eef1c15f5..230b1c53bde0e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/discovery/EnOceanDeviceDiscoveryService.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/discovery/EnOceanDeviceDiscoveryService.java @@ -171,5 +171,4 @@ public long getSenderIdToListenTo() { // we just want teach in msg, so return zero here return 0; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/discovery/EnOceanUsbSerialDiscoveryParticipant.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/discovery/EnOceanUsbSerialDiscoveryParticipant.java index 91637068a45e4..cb5db2d3230c5 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/discovery/EnOceanUsbSerialDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/discovery/EnOceanUsbSerialDiscoveryParticipant.java @@ -98,5 +98,4 @@ private boolean isEnoceanUSB300Dongle(UsbSerialDeviceInformation deviceInformati return ENOCEAN_USB300_DONGLE_DEFAULT_LABEL; } } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_01.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_01.java index b9a28c3c718e0..252d201c24378 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_01.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_01.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 0; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_02.java index 0d0023b8b6955..e8b4000c8f157 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_02.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 10; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_03.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_03.java index b7b5d6e36e846..30a35f2b8c6f0 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_03.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_03.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 20; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_04.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_04.java index 619e99b0af669..7b018287f2e9f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_04.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_04.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 30; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_05.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_05.java index 1e18e383713ca..2c7d3a2a1f38b 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_05.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_05.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 40; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_06.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_06.java index f22c9c4584cdb..90d6e8ecf3b77 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_06.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_06.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 50; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_07.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_07.java index 4393637b90d20..c52d4b59941ca 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_07.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_07.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 60; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_08.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_08.java index 7145e9a9765fa..c0837e3e6be8e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_08.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_08.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 70; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_09.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_09.java index 8debb668e6670..6144407470924 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_09.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_09.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 80; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_0A.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_0A.java index a539cd3125574..bd3f1b8b5389f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_0A.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_0A.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 90; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_0B.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_0B.java index 90882522951a8..10bdf1c0ce03a 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_0B.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_0B.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 100; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_10.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_10.java index f21872e76f677..ddd55fe1b3a6a 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_10.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_10.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 20; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_11.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_11.java index 4ae2ede806b93..64decd61f92f1 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_11.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_11.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 30; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_12.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_12.java index 7a759904f649b..6ddc5f7b4f0d0 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_12.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_12.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 40; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_13.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_13.java index 45ee90ecccc5c..3e77bc762d016 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_13.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_13.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 50; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_14.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_14.java index 77d44784163f1..65b37a382a74c 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_14.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_14.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 60; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_15.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_15.java index fccab8005bc7a..d8b1b07237c3a 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_15.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_15.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 70; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_16.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_16.java index ed14044705e29..27beab7d3bb3e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_16.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_16.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 80; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_17.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_17.java index dfa7e7bb1b922..2225139b35f97 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_17.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_17.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 90; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_18.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_18.java index a9248f046b193..2e1bbfdc6ec21 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_18.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_18.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 100; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_19.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_19.java index 29d59b49d325d..4d8a7d5a5fae7 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_19.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_19.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 110; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_1A.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_1A.java index 0a92c7fbd2d5b..638af83ece122 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_1A.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_1A.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 120; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_1B.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_1B.java index fdfb87152335a..a23a118d3a48a 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_1B.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_1B.java @@ -33,5 +33,4 @@ protected double getScaledMin() { protected double getScaledMax() { return 130; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_20.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_20.java index b8e14b9b5d718..b5433a01d7f78 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_20.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_20.java @@ -48,5 +48,4 @@ protected double getUnscaledMax() { protected int getUnscaledTemperatureValue() { return getDB_1Value() + ((getDB_2Value() & 0b11) << 8); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_30.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_30.java index 827e53d237008..e69d5ffb2964e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_30.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_02/A5_02_30.java @@ -48,5 +48,4 @@ protected double getUnscaledMax() { protected int getUnscaledTemperatureValue() { return getDB_1Value() + ((getDB_2Value() & 0b11) << 8); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_07/A5_07_01.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_07/A5_07_01.java index b62e2c160b66b..4cc3cc691706c 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_07/A5_07_01.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_07/A5_07_01.java @@ -47,5 +47,4 @@ protected State getSupplyVoltage() { return getSupplyVoltage(getDB_3Value()); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_07/A5_07_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_07/A5_07_02.java index 723043bb31034..f782d5b13c62e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_07/A5_07_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_07/A5_07_02.java @@ -41,5 +41,4 @@ protected State getMotion() { protected State getSupplyVoltage() { return getSupplyVoltage(getDB_3Value()); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_08/A5_08_03.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_08/A5_08_03.java index 996375da6812f..acc137c006b16 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_08/A5_08_03.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_08/A5_08_03.java @@ -43,5 +43,4 @@ protected double getScaledIlluminationMin() { protected double getScaledIlluminationMax() { return 1530; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_20/A5_20_04.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_20/A5_20_04.java index 6f82dc4dfc897..0b82eadc691b2 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_20/A5_20_04.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/A5_20/A5_20_04.java @@ -1,267 +1,267 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.enocean.internal.eep.A5_20; - -import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*; - -import java.util.function.Function; - -import javax.measure.quantity.Temperature; - -import org.eclipse.smarthome.config.core.Configuration; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.QuantityType; -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.UnDefType; -import org.openhab.binding.enocean.internal.messages.ERP1Message; - -/** - * Heating radiator valve actuating drive with feed and room temperature measurement, local set point control and - * display - * - * @author Dominik Vorreiter - Initial contribution - */ -public class A5_20_04 extends A5_20 { - - public A5_20_04() { - super(); - } - - public A5_20_04(ERP1Message packet) { - super(packet); - } - - @Override - protected String convertToEventImpl(String channelId, String channelTypeId, String lastEvent, - Configuration config) { - switch (channelId) { - case CHANNEL_STATUS_REQUEST_EVENT: - return getStatusRequestEvent(); - } - - return null; - } - - private String getStatusRequestEvent() { - return Boolean.valueOf(getBit(getDB_0Value(), 6)).toString(); - // return getBit(getDB_0Value(), 6) ? "triggered" : null; - } - - private byte getPos(Function getCurrentStateFunc) { - State current = getCurrentStateFunc.apply(CHANNEL_VALVE_POSITION); - - if ((current != null) && (current instanceof DecimalType)) { - DecimalType state = current.as(DecimalType.class); - - if (state != null) { - return state.byteValue(); - } - } - - return 25; // 25 % - } - - private byte getTsp(Function getCurrentStateFunc) { - State current = getCurrentStateFunc.apply(CHANNEL_TEMPERATURE_SETPOINT); - - double value = 20.0; // 20 °C - - if ((current != null) && (current instanceof QuantityType)) { - @SuppressWarnings("unchecked") - QuantityType raw = current.as(QuantityType.class); - - if (raw != null) { - QuantityType celsius = raw.toUnit(SIUnits.CELSIUS); - - if (celsius != null) { - value = celsius.doubleValue(); - } - } - } - - return (byte) ((value - 10.0) * (255.0 / 20.0)); - } - - private byte getMc(Function getCurrentStateFunc) { - State current = getCurrentStateFunc.apply(CHANNEL_MEASUREMENT_CONTROL); - - if ((current != null) && (current instanceof OnOffType)) { - OnOffType state = current.as(OnOffType.class); - - if (state != null) { - return (byte) (state.equals(OnOffType.ON) ? 0x00 : 0x40); - } - } - - return 0x00; // on - } - - private byte getWuc(Function getCurrentStateFunc) { - State current = getCurrentStateFunc.apply(CHANNEL_WAKEUPCYCLE); - - if ((current != null) && (current instanceof DecimalType)) { - DecimalType state = current.as(DecimalType.class); - - if (state != null) { - return (byte) (state.byteValue() & 0x3F); - } - } - - return 0x13; // 19 = 600 sec = 10 min - } - - private byte getDso(Function getCurrentStateFunc) { - State current = getCurrentStateFunc.apply(CHANNEL_DISPLAY_ORIENTATION); - - if ((current != null) && (current instanceof DecimalType)) { - DecimalType state = current.as(DecimalType.class); - - if (state != null) { - return (byte) (((state.byteValue() / 90) << 4) & 0x30); - } - } - - return 0x00; // 0° - } - - private byte getBlc(Function getCurrentStateFunc) { - State current = getCurrentStateFunc.apply(CHANNEL_BUTTON_LOCK); - - if ((current != null) && (current instanceof OnOffType)) { - OnOffType state = current.as(OnOffType.class); - - if (state != null) { - return (byte) (state.equals(OnOffType.ON) ? 0x04 : 0x00); - } - } - - return 0x00; // unlocked - } - - private byte getSer(Function getCurrentStateFunc) { - State current = getCurrentStateFunc.apply(CHANNEL_SERVICECOMMAND); - - if ((current != null) && (current instanceof DecimalType)) { - DecimalType state = current.as(DecimalType.class); - - if (state != null) { - return (byte) (state.byteValue() & 0x03); - } - } - - return 0x00; // 0 = no change - } - - @Override - protected void convertFromCommandImpl(String channelId, String channelTypeId, Command command, - Function getCurrentStateFunc, Configuration config) { - if (CHANNEL_SEND_COMMAND.equals(channelId) && (command.equals(OnOffType.ON))) { - byte db3 = getPos(getCurrentStateFunc); - byte db2 = getTsp(getCurrentStateFunc); - byte db1 = (byte) (0x00 | getMc(getCurrentStateFunc) | getWuc(getCurrentStateFunc)); - byte db0 = (byte) (0x00 | getDso(getCurrentStateFunc) | TeachInBit | getBlc(getCurrentStateFunc) - | getSer(getCurrentStateFunc)); - - setData(db3, db2, db1, db0); - - return; - } - } - - @Override - protected State convertToStateImpl(String channelId, String channelTypeId, - Function getCurrentStateFunc, Configuration config) { - switch (channelId) { - case CHANNEL_VALVE_POSITION: - return getValvePosition(); - case CHANNEL_BUTTON_LOCK: - return getButtonLock(); - case CHANNEL_TEMPERATURE_SETPOINT: - return getTemperatureSetpoint(); - case CHANNEL_TEMPERATURE: - return getTemperature(); - case CHANNEL_FEED_TEMPERATURE: - return getFeedTemperature(); - case CHANNEL_MEASUREMENT_CONTROL: - return getMeasurementControl(); - case CHANNEL_FAILURE_CODE: - return getFailureCode(); - } - - return UnDefType.UNDEF; - } - - private State getTemperature() { - boolean fl = getBit(getDB_0Value(), 0); - boolean mst = getBit(getDB_0Value(), 7); - - if (fl || mst) { - return UnDefType.UNDEF; - } - - double value = getDB_1Value() * (20.0 / 255.0) + 10.0; - - return new QuantityType<>(value, SIUnits.CELSIUS); - } - - private State getFailureCode() { - boolean fl = getBit(getDB_0Value(), 0); - - if (!fl) { - return new QuantityType<>(-1, SmartHomeUnits.ONE); - } - - return new QuantityType<>(getDB_1Value(), SmartHomeUnits.ONE); - } - - private State getMeasurementControl() { - return getBit(getDB_0Value(), 7) ? OnOffType.OFF : OnOffType.ON; - } - - private State getFeedTemperature() { - boolean ts = getBit(getDB_0Value(), 1); - boolean mst = getBit(getDB_0Value(), 7); - - if (ts || mst) { - return UnDefType.UNDEF; - } - - double value = getDB_2Value() * (60.0 / 255.0) + 20.0; - - return new QuantityType<>(value, SIUnits.CELSIUS); - } - - private State getTemperatureSetpoint() { - boolean ts = getBit(getDB_0Value(), 1); - - if (!ts) { - return UnDefType.UNDEF; - } - - double value = getDB_2Value() * (20.0 / 255.0) + 10.0; - - return new QuantityType<>(value, SIUnits.CELSIUS); - } - - private State getButtonLock() { - return getBit(getDB_0Value(), 2) ? OnOffType.ON : OnOffType.OFF; - } - - private State getValvePosition() { - return new QuantityType<>(getDB_3Value(), SmartHomeUnits.PERCENT); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.enocean.internal.eep.A5_20; + +import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*; + +import java.util.function.Function; + +import javax.measure.quantity.Temperature; + +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.unit.SIUnits; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.enocean.internal.messages.ERP1Message; + +/** + * Heating radiator valve actuating drive with feed and room temperature measurement, local set point control and + * display + * + * @author Dominik Vorreiter - Initial contribution + */ +public class A5_20_04 extends A5_20 { + + public A5_20_04() { + super(); + } + + public A5_20_04(ERP1Message packet) { + super(packet); + } + + @Override + protected String convertToEventImpl(String channelId, String channelTypeId, String lastEvent, + Configuration config) { + switch (channelId) { + case CHANNEL_STATUS_REQUEST_EVENT: + return getStatusRequestEvent(); + } + + return null; + } + + private String getStatusRequestEvent() { + return Boolean.valueOf(getBit(getDB_0Value(), 6)).toString(); + // return getBit(getDB_0Value(), 6) ? "triggered" : null; + } + + private byte getPos(Function getCurrentStateFunc) { + State current = getCurrentStateFunc.apply(CHANNEL_VALVE_POSITION); + + if ((current != null) && (current instanceof DecimalType)) { + DecimalType state = current.as(DecimalType.class); + + if (state != null) { + return state.byteValue(); + } + } + + return 25; // 25 % + } + + private byte getTsp(Function getCurrentStateFunc) { + State current = getCurrentStateFunc.apply(CHANNEL_TEMPERATURE_SETPOINT); + + double value = 20.0; // 20 °C + + if ((current != null) && (current instanceof QuantityType)) { + @SuppressWarnings("unchecked") + QuantityType raw = current.as(QuantityType.class); + + if (raw != null) { + QuantityType celsius = raw.toUnit(SIUnits.CELSIUS); + + if (celsius != null) { + value = celsius.doubleValue(); + } + } + } + + return (byte) ((value - 10.0) * (255.0 / 20.0)); + } + + private byte getMc(Function getCurrentStateFunc) { + State current = getCurrentStateFunc.apply(CHANNEL_MEASUREMENT_CONTROL); + + if ((current != null) && (current instanceof OnOffType)) { + OnOffType state = current.as(OnOffType.class); + + if (state != null) { + return (byte) (state.equals(OnOffType.ON) ? 0x00 : 0x40); + } + } + + return 0x00; // on + } + + private byte getWuc(Function getCurrentStateFunc) { + State current = getCurrentStateFunc.apply(CHANNEL_WAKEUPCYCLE); + + if ((current != null) && (current instanceof DecimalType)) { + DecimalType state = current.as(DecimalType.class); + + if (state != null) { + return (byte) (state.byteValue() & 0x3F); + } + } + + return 0x13; // 19 = 600 sec = 10 min + } + + private byte getDso(Function getCurrentStateFunc) { + State current = getCurrentStateFunc.apply(CHANNEL_DISPLAY_ORIENTATION); + + if ((current != null) && (current instanceof DecimalType)) { + DecimalType state = current.as(DecimalType.class); + + if (state != null) { + return (byte) (((state.byteValue() / 90) << 4) & 0x30); + } + } + + return 0x00; // 0° + } + + private byte getBlc(Function getCurrentStateFunc) { + State current = getCurrentStateFunc.apply(CHANNEL_BUTTON_LOCK); + + if ((current != null) && (current instanceof OnOffType)) { + OnOffType state = current.as(OnOffType.class); + + if (state != null) { + return (byte) (state.equals(OnOffType.ON) ? 0x04 : 0x00); + } + } + + return 0x00; // unlocked + } + + private byte getSer(Function getCurrentStateFunc) { + State current = getCurrentStateFunc.apply(CHANNEL_SERVICECOMMAND); + + if ((current != null) && (current instanceof DecimalType)) { + DecimalType state = current.as(DecimalType.class); + + if (state != null) { + return (byte) (state.byteValue() & 0x03); + } + } + + return 0x00; // 0 = no change + } + + @Override + protected void convertFromCommandImpl(String channelId, String channelTypeId, Command command, + Function getCurrentStateFunc, Configuration config) { + if (CHANNEL_SEND_COMMAND.equals(channelId) && (command.equals(OnOffType.ON))) { + byte db3 = getPos(getCurrentStateFunc); + byte db2 = getTsp(getCurrentStateFunc); + byte db1 = (byte) (0x00 | getMc(getCurrentStateFunc) | getWuc(getCurrentStateFunc)); + byte db0 = (byte) (0x00 | getDso(getCurrentStateFunc) | TeachInBit | getBlc(getCurrentStateFunc) + | getSer(getCurrentStateFunc)); + + setData(db3, db2, db1, db0); + + return; + } + } + + @Override + protected State convertToStateImpl(String channelId, String channelTypeId, + Function getCurrentStateFunc, Configuration config) { + switch (channelId) { + case CHANNEL_VALVE_POSITION: + return getValvePosition(); + case CHANNEL_BUTTON_LOCK: + return getButtonLock(); + case CHANNEL_TEMPERATURE_SETPOINT: + return getTemperatureSetpoint(); + case CHANNEL_TEMPERATURE: + return getTemperature(); + case CHANNEL_FEED_TEMPERATURE: + return getFeedTemperature(); + case CHANNEL_MEASUREMENT_CONTROL: + return getMeasurementControl(); + case CHANNEL_FAILURE_CODE: + return getFailureCode(); + } + + return UnDefType.UNDEF; + } + + private State getTemperature() { + boolean fl = getBit(getDB_0Value(), 0); + boolean mst = getBit(getDB_0Value(), 7); + + if (fl || mst) { + return UnDefType.UNDEF; + } + + double value = getDB_1Value() * (20.0 / 255.0) + 10.0; + + return new QuantityType<>(value, SIUnits.CELSIUS); + } + + private State getFailureCode() { + boolean fl = getBit(getDB_0Value(), 0); + + if (!fl) { + return new QuantityType<>(-1, SmartHomeUnits.ONE); + } + + return new QuantityType<>(getDB_1Value(), SmartHomeUnits.ONE); + } + + private State getMeasurementControl() { + return getBit(getDB_0Value(), 7) ? OnOffType.OFF : OnOffType.ON; + } + + private State getFeedTemperature() { + boolean ts = getBit(getDB_0Value(), 1); + boolean mst = getBit(getDB_0Value(), 7); + + if (ts || mst) { + return UnDefType.UNDEF; + } + + double value = getDB_2Value() * (60.0 / 255.0) + 20.0; + + return new QuantityType<>(value, SIUnits.CELSIUS); + } + + private State getTemperatureSetpoint() { + boolean ts = getBit(getDB_0Value(), 1); + + if (!ts) { + return UnDefType.UNDEF; + } + + double value = getDB_2Value() * (20.0 / 255.0) + 10.0; + + return new QuantityType<>(value, SIUnits.CELSIUS); + } + + private State getButtonLock() { + return getBit(getDB_0Value(), 2) ? OnOffType.ON : OnOffType.OFF; + } + + private State getValvePosition() { + return new QuantityType<>(getDB_3Value(), SmartHomeUnits.PERCENT); + } +} diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_4BSMessage.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_4BSMessage.java index 443ff4b4cdd53..9523114cc69e1 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_4BSMessage.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_4BSMessage.java @@ -103,6 +103,5 @@ protected void teachInQueryImpl(Configuration config) { } catch (Exception e) { } } - } } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_SIGMessage.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_SIGMessage.java index 7527cc53bd73d..d0725be465f4b 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_SIGMessage.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_SIGMessage.java @@ -46,5 +46,4 @@ protected int getDataLength() { protected boolean validateData(byte[] bytes) { return true; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_VLDMessage.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_VLDMessage.java index 4e5d275d59732..ade094a27f71f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_VLDMessage.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/Base/_VLDMessage.java @@ -44,5 +44,4 @@ protected int getDataLength() { protected boolean validateData(byte[] bytes) { return true; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D0/D0_06.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D0/D0_06.java index 36ab70456d469..74efc18739e69 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D0/D0_06.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D0/D0_06.java @@ -39,7 +39,8 @@ public D0_06(ERP1Message packet) { } @Override - public State convertToStateImpl(String channelId, String channelTypeId, Function getCurrentStateFunc, Configuration config) { + public State convertToStateImpl(String channelId, String channelTypeId, Function getCurrentStateFunc, + Configuration config) { if (CHANNEL_BATTERY_LEVEL.equals(channelId)) { return new QuantityType<>(bytes[1] & 0xFF, SmartHomeUnits.PERCENT); } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01.java index 1347b683f9ce1..1ef11cb50e7fa 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01.java @@ -29,8 +29,8 @@ import org.eclipse.smarthome.core.types.UnDefType; import org.eclipse.smarthome.core.util.HexUtils; import org.openhab.binding.enocean.internal.config.EnOceanChannelDimmerConfig; -import org.openhab.binding.enocean.internal.eep.EEPHelper; import org.openhab.binding.enocean.internal.eep.Base._VLDMessage; +import org.openhab.binding.enocean.internal.eep.EEPHelper; import org.openhab.binding.enocean.internal.messages.ERP1Message; /** @@ -251,5 +251,4 @@ protected State convertToStateImpl(String channelId, String channelTypeId, return UnDefType.UNDEF; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_00.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_00.java index 8fc9e113a04c3..45cf517380fb0 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_00.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_00.java @@ -27,5 +27,4 @@ public D2_01_00() { public D2_01_00(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_01.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_01.java index 64ed22a2a75c8..50864af82402e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_01.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_01.java @@ -27,5 +27,4 @@ public D2_01_01() { public D2_01_01(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_02.java index 82306de24d914..65e00194bec70 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_02.java @@ -27,5 +27,4 @@ public D2_01_02() { public D2_01_02(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_03.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_03.java index 0cd96f699488f..11f57c15464fa 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_03.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_03.java @@ -27,5 +27,4 @@ public D2_01_03() { public D2_01_03(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_04.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_04.java index 05acb9b7f68d1..a282b64e5c25f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_04.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_04.java @@ -27,5 +27,4 @@ public D2_01_04() { public D2_01_04(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_05.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_05.java index 254aee2169934..ce2b8418756db 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_05.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_05.java @@ -27,5 +27,4 @@ public D2_01_05() { public D2_01_05(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_06.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_06.java index 9145f8f7540dd..73420a607ec79 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_06.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_06.java @@ -27,5 +27,4 @@ public D2_01_06() { public D2_01_06(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_07.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_07.java index 1a7e345670db5..f9c880f7cdc5b 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_07.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_07.java @@ -27,5 +27,4 @@ public D2_01_07() { public D2_01_07(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_08.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_08.java index 48b746cd60d74..9871dcef3ce4a 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_08.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_08.java @@ -27,5 +27,4 @@ public D2_01_08() { public D2_01_08(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_09.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_09.java index e89f0878175ad..26c2bced9ac01 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_09.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_09.java @@ -27,5 +27,4 @@ public D2_01_09() { public D2_01_09(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0A.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0A.java index cac7af5f12f7a..faba8019465cc 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0A.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0A.java @@ -27,5 +27,4 @@ public D2_01_0A() { public D2_01_0A(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0B.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0B.java index c67752898c918..e4c1fec7d12ab 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0B.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0B.java @@ -27,5 +27,4 @@ public D2_01_0B() { public D2_01_0B(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0C.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0C.java index 6a486bb51247d..16b9025726d3a 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0C.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0C.java @@ -27,5 +27,4 @@ public D2_01_0C() { public D2_01_0C(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0D.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0D.java index cd664fbb12a59..7bb8e24ac42db 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0D.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0D.java @@ -27,5 +27,4 @@ public D2_01_0D() { public D2_01_0D(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0E.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0E.java index 428a7f7d610b9..4fb66ef8ea5d5 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0E.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0E.java @@ -27,5 +27,4 @@ public D2_01_0E() { public D2_01_0E(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0F.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0F.java index 4f3b495b0f54d..a7b9fff59d241 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0F.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_0F.java @@ -27,5 +27,4 @@ public D2_01_0F() { public D2_01_0F(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_11.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_11.java index f9ff8462a3d1c..b89b1572cda35 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_11.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_11.java @@ -27,5 +27,4 @@ public D2_01_11() { public D2_01_11(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_12.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_12.java index a6db08fea8319..5507e383b4f60 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_12.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_12.java @@ -27,5 +27,4 @@ public D2_01_12() { public D2_01_12(ERP1Message packet) { super(packet); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_12_NodON.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_12_NodON.java index 3f0f4abf163fe..8636e7d6a8f4e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_12_NodON.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_01/D2_01_12_NodON.java @@ -61,5 +61,4 @@ protected void convertFromCommandImpl(String channelId, String channelTypeId, Co super.convertFromCommandImpl(channelId, channelTypeId, command, getCurrentStateFunc, config); } } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_05/D2_05_00.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_05/D2_05_00.java index 746b01d4ea9ca..8ffda5261d449 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_05/D2_05_00.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_05/D2_05_00.java @@ -123,5 +123,4 @@ protected State convertToStateImpl(String channelId, String channelTypeId, return UnDefType.UNDEF; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPFactory.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPFactory.java index 75694835e14df..e0a260b26c713 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPFactory.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPFactory.java @@ -182,7 +182,6 @@ public static EEP buildEEPFromTeachInERP1(ERP1Message msg) { } return null; - } public static EEP buildResponseEEPFromTeachInERP1(ERP1Message msg, byte[] senderId) { diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java index 33320ff005d60..5923182c71ba0 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java @@ -644,5 +644,4 @@ public static EEPType getType(RORG rorg, int func, int type, int manufId) { return fallback; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_10/F6_10_00_EltakoFPE.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_10/F6_10_00_EltakoFPE.java index c9d8b41d59fb7..4c1f6dfc1597e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_10/F6_10_00_EltakoFPE.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_10/F6_10_00_EltakoFPE.java @@ -61,5 +61,4 @@ protected boolean validateData(byte[] bytes) { // FPE just sends 0b00010000 or 0b00000000 value, so we apply mask 0b11101111 return super.validateData(bytes) && ((bytes[0] & (byte) 0xEF) == (byte) 0x00); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/BasePacket.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/BasePacket.java index 0b45e9fcef9ad..51d5d5f00e256 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/BasePacket.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/BasePacket.java @@ -61,7 +61,6 @@ public static ESPPacketType getPacketType(byte packetType) { throw new InvalidParameterException("Unknown packetType value"); } - } protected ESPPacketType packetType; diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/BaseResponse.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/BaseResponse.java index 8c82af85e2aa7..3fe2f88056093 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/BaseResponse.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/BaseResponse.java @@ -24,5 +24,4 @@ public BaseResponse(Response response) { super(response.getPayload().length + response.getOptionalPayload().length, 0, Helper.concatAll(response.getPayload(), response.getOptionalPayload())); } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/RDBaseIdResponse.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/RDBaseIdResponse.java index 391fc11400850..074ed5a680036 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/RDBaseIdResponse.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/RDBaseIdResponse.java @@ -48,5 +48,4 @@ public final byte[] getBaseId() { public int getRemainingWriteCycles() { return remainingWriteCycles; } - } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/Response.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/Response.java index 0c978bc31970e..db78bed5ec8ec 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/Response.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/messages/Response.java @@ -52,7 +52,6 @@ public static ResponseType getResponsetype(byte value) { throw new InvalidParameterException("Unknown response type"); } - } protected ResponseType responseType; diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/transceiver/EnOceanTransceiver.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/transceiver/EnOceanTransceiver.java index b3fde1a517b3f..44f217d51625f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/transceiver/EnOceanTransceiver.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/transceiver/EnOceanTransceiver.java @@ -25,7 +25,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.core.util.HexUtils; import org.eclipse.smarthome.io.transport.serial.PortInUseException; import org.eclipse.smarthome.io.transport.serial.SerialPort; @@ -219,11 +218,19 @@ public void ShutDown() { if (outputStream != null) { logger.debug("Closing serial output stream"); - IOUtils.closeQuietly(outputStream); + try { + outputStream.close(); + } catch (IOException e) { + logger.debug("Error while closing the output stream: {}", e.getMessage()); + } } if (inputStream != null) { logger.debug("Closeing serial input stream"); - IOUtils.closeQuietly(inputStream); + try { + inputStream.close(); + } catch (IOException e) { + logger.debug("Error while closing the input stream: {}", e.getMessage()); + } } if (serialPort != null) { diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/AutomatedMeterSensor.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/AutomatedMeterSensor.xml index 0b5d021a11210..78f557e8083a9 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/AutomatedMeterSensor.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/AutomatedMeterSensor.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/CentralCommand.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/CentralCommand.xml index 462fd8bc01d1d..7115374ab58f8 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/CentralCommand.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/CentralCommand.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/ClassicDevice.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/ClassicDevice.xml index b336bc74907c5..6d24ab2084156 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/ClassicDevice.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/ClassicDevice.xml @@ -7,16 +7,16 @@ - + This thing lets you control classic EnOcean devices by rocker switch messages (EEP: F6-02) - - - + + + @@ -59,7 +59,7 @@ Switch The virtual rocker switch channel allows to send rocker msg. - + @@ -67,7 +67,7 @@ Rollershutter This channels allows to control a rollershutter through rocker msg. - + @@ -92,14 +92,14 @@ Switch - + Rollershutter - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Contact.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Contact.xml index 2c23157cedf1d..57f6069ea4945 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Contact.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Contact.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/EnvironmentalSensor.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/EnvironmentalSensor.xml index 7702f77686219..aae17def9b664 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/EnvironmentalSensor.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/EnvironmentalSensor.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/GenericThing.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/GenericThing.xml index 2aef6e42d4a73..2fa60566e40e8 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/GenericThing.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/GenericThing.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/LightSensor.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/LightSensor.xml index 05bfd99bab576..632067232aeb4 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/LightSensor.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/LightSensor.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/LightTemperatureOccupancySensor.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/LightTemperatureOccupancySensor.xml index 74de547b4a19e..c67a1fbdc3918 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/LightTemperatureOccupancySensor.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/LightTemperatureOccupancySensor.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MeasurementSwitch.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MeasurementSwitch.xml index bade521d09fb6..0f095d5ed6e18 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MeasurementSwitch.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MeasurementSwitch.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MechanicalHandle.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MechanicalHandle.xml index 149da406da336..95f18fad67553 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MechanicalHandle.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MechanicalHandle.xml @@ -7,7 +7,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MultiFunctionSmokeDetector.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MultiFunctionSmokeDetector.xml index da81e9cf363ac..3b367bf202237 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MultiFunctionSmokeDetector.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/MultiFunctionSmokeDetector.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/OccupancySensor.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/OccupancySensor.xml index a492bb656e217..c6d093c2cc3b2 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/OccupancySensor.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/OccupancySensor.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/PushButton.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/PushButton.xml index 1dbe16399da83..d743aece64f20 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/PushButton.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/PushButton.xml @@ -7,7 +7,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/RockerSwitch.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/RockerSwitch.xml index 0a18015846934..505f02c2bbf92 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/RockerSwitch.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/RockerSwitch.xml @@ -7,7 +7,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Rollershutter.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Rollershutter.xml index a1079a5ddc02d..486ceebf0e2e4 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Rollershutter.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Rollershutter.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/RoomOperatingPanel.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/RoomOperatingPanel.xml index b5fa15b83670a..e9829d5dc836f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/RoomOperatingPanel.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/RoomOperatingPanel.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/TemperatureHumiditySensor.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/TemperatureHumiditySensor.xml index 60a1783272c75..a057604fcfac4 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/TemperatureHumiditySensor.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/TemperatureHumiditySensor.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/TemperatureSensor.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/TemperatureSensor.xml index 137f888b1b28b..5e233edca17f8 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/TemperatureSensor.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/TemperatureSensor.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Thermostat.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Thermostat.xml index 2954d0fc25abc..2be75d8e93033 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Thermostat.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/Thermostat.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/bridge.xml index 905d45853138a..afa99f504c7f8 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/bridge.xml @@ -10,8 +10,8 @@ The EnOcean gateway connects to an ESP3 device. - - + + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/channels.xml index 7b0b16723a605..c5af9e109201c 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/channels.xml @@ -92,7 +92,7 @@ Current temperature in degree Celsius Temperature - + @@ -100,14 +100,14 @@ Relative humidity level in percentages Humidity - + Number linear set point - + @@ -129,7 +129,7 @@ Occupancy button pressed or released. Switch - + @@ -162,14 +162,14 @@ Number:Power Instant power consumption in Watts - + Number:Energy Used energy in Kilowatt hours - + @@ -183,14 +183,14 @@ Number:ElectricPotential Voltage of the battery - + Number:ElectricPotential ? - + @@ -218,21 +218,21 @@ Number Received Signal Strength Indication - + Number Number of repeaters involved in the transmission of the telegram - + DateTime Date and time the last telegram was received - + @@ -240,49 +240,49 @@ Vibration alarm state. Switch - + Number:Illuminance Illumination in lux - + Number:Illuminance Illumination in lux - + Number:Illuminance Illumination in lux - + Number:Illuminance Illumination in lux - + Number:Duration Automatically switch to off - + Number:Duration Delay switch off by radio for given seconds - + @@ -317,33 +317,33 @@ Blind Angle Blinds - + Number:VolumetricFlowRate - + Number:Volume - + Number Counter - + Number Current - + @@ -351,7 +351,7 @@ Rain indicator Switch - + @@ -359,7 +359,7 @@ Indicates the actual percent position of the valve. thermostat - + @@ -395,14 +395,14 @@ Number:Temperature Desired temperature - + Number:Temperature Water temperature in the radiator input - + @@ -410,7 +410,7 @@ Failure code thermostat - + @@ -418,7 +418,7 @@ Defines the cyclic wake-up time. The time corresponding to the number has to be looked up. thermostat - + @@ -440,7 +440,7 @@ trigger Is triggered when the actuator wakes up from sleep and asks for the current status. - + @@ -454,49 +454,49 @@ Switch Smoke detection sensor state. - + Switch Sensor activated fault mode. - + Switch Sensor maintenance status. - + Switch Sensor analysis status: humidity out of range - + Switch Sensor analysis status: temperature out of range - + Number:Time Time since last maintenance was done. - + Number:Time Countdown time until product end of life. - + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/gernericChannels.xml b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/gernericChannels.xml index 4aad1b40fb5e5..2744f18b8989c 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/gernericChannels.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/ESH-INF/thing/gernericChannels.xml @@ -10,7 +10,7 @@ The switch channel allows to switch something on and off. Switch - + @@ -19,7 +19,7 @@ Rollershutter Blinds - + @@ -28,26 +28,26 @@ Dimmer DimmableLight - + Number Number - + String - + Color - + @@ -56,7 +56,7 @@ The teach in channel allows to send a teach in msg. Switch - + diff --git a/bundles/org.openhab.binding.enturno/pom.xml b/bundles/org.openhab.binding.enturno/pom.xml index 6ef08629a0e98..4fbf34305054b 100644 --- a/bundles/org.openhab.binding.enturno/pom.xml +++ b/bundles/org.openhab.binding.enturno/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.enturno diff --git a/bundles/org.openhab.binding.enturno/src/main/feature/feature.xml b/bundles/org.openhab.binding.enturno/src/main/feature/feature.xml index e96c75b636c35..dd05f2d025b20 100644 --- a/bundles/org.openhab.binding.enturno/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.enturno/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.enturno/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.enturno/${project.version} + diff --git a/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/EnturNoBindingConstants.java b/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/EnturNoBindingConstants.java index a00cc3e0bcef6..f29d47d2dd005 100644 --- a/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/EnturNoBindingConstants.java +++ b/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/EnturNoBindingConstants.java @@ -52,5 +52,4 @@ public class EnturNoBindingConstants { public static final String ESTIMATED_FLAG_04 = "estimatedFlag04"; public static final String ESTIMATED_FLAG_05 = "estimatedFlag05"; public static final String CHANNEL_FRONT_DISPLAY = "frontDisplayText"; - } diff --git a/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/EnturNoHandlerFactory.java b/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/EnturNoHandlerFactory.java index fca5dbbb470aa..68d27da986877 100644 --- a/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/EnturNoHandlerFactory.java +++ b/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/EnturNoHandlerFactory.java @@ -12,6 +12,11 @@ */ package org.openhab.binding.enturno.internal; +import static org.openhab.binding.enturno.internal.EnturNoBindingConstants.LINESTOP; + +import java.util.Collections; +import java.util.Set; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; @@ -24,11 +29,6 @@ import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; -import java.util.Collections; -import java.util.Set; - -import static org.openhab.binding.enturno.internal.EnturNoBindingConstants.LINESTOP; - /** * The {@link EnturNoHandlerFactory} is responsible for creating things and thing * handlers. diff --git a/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/connection/EnturNoConnection.java b/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/connection/EnturNoConnection.java index e760367040cb2..5a62be6f22af7 100644 --- a/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/connection/EnturNoConnection.java +++ b/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/connection/EnturNoConnection.java @@ -94,8 +94,7 @@ public EnturNoConnection(EnturNoHandler handler, HttpClient httpClient) { * @throws EnturCommunicationException * @throws EnturConfigurationException */ - public synchronized List getEnturTimeTable(@Nullable String stopPlaceId, - @Nullable String lineCode) + public synchronized List getEnturTimeTable(@Nullable String stopPlaceId, @Nullable String lineCode) throws JsonSyntaxException, EnturConfigurationException, EnturCommunicationException { if (StringUtils.isBlank(stopPlaceId)) { throw new EnturConfigurationException("Stop place id cannot be empty or null"); diff --git a/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/model/estimated/EstimatedCalls.java b/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/model/estimated/EstimatedCalls.java index 914a45a064f69..2bd12fb616c65 100644 --- a/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/model/estimated/EstimatedCalls.java +++ b/bundles/org.openhab.binding.enturno/src/main/java/org/openhab/binding/enturno/internal/model/estimated/EstimatedCalls.java @@ -40,5 +40,3 @@ public class EstimatedCalls { public String expectedArrivalTime; } - - diff --git a/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/config/config.xml index 9562bef322702..a385182e9c859 100644 --- a/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/config/config.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd"> diff --git a/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/thing/channel-types.xml index 33e058367755c..b1c65996fdef3 100644 --- a/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/thing/channel-types.xml @@ -1,17 +1,17 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> This is a stop place. - - - + + + @@ -19,18 +19,18 @@ This is the data for public transport line direction. - - - - - - - - - - - - + + + + + + + + + + + + @@ -40,49 +40,49 @@ Time of departure. Time - + String Code (usually number) of the public transport line. - + String Whether departure time is calculated/estimated or as in printed timetable (true/false). - + String Front display usually shows direction of the line. - + String Id of the stop place. - + String Name of the stop place. - + String Bus/Tramway/Plane etc. - + diff --git a/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/thing/thing-types.xml index b4b21a70d133d..16f551c0104d7 100644 --- a/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.enturno/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,10 +7,11 @@ - Provides real-time (estimated) departure timetable for chosen public transport line and stop in Norway. Data provided by Entur.no API. + Provides real-time (estimated) departure timetable for chosen public transport line and stop in Norway. + Data provided by Entur.no API. - + This is the real-time table for direction nr 1. @@ -21,7 +22,7 @@ - + diff --git a/bundles/org.openhab.binding.etherrain/pom.xml b/bundles/org.openhab.binding.etherrain/pom.xml index 57bd154e7b2c9..698b8f0a86865 100644 --- a/bundles/org.openhab.binding.etherrain/pom.xml +++ b/bundles/org.openhab.binding.etherrain/pom.xml @@ -1,15 +1,17 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.etherrain - + openHAB Add-ons :: Bundles :: EtherRain Binding diff --git a/bundles/org.openhab.binding.etherrain/src/main/feature/feature.xml b/bundles/org.openhab.binding.etherrain/src/main/feature/feature.xml index 0cae84bb84f1a..d33b762515cd8 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.etherrain/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.etherrain/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.etherrain/${project.version} + diff --git a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/EtherRainBindingConstants.java b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/EtherRainBindingConstants.java index b8442dd630327..389bb9d18b5d5 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/EtherRainBindingConstants.java +++ b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/EtherRainBindingConstants.java @@ -59,5 +59,4 @@ public class EtherRainBindingConstants { public static final String CHANNEL_ID_START_DELAY = "startdelay"; public static final String CHANNEL_ID_EXECUTE = "execute"; public static final String CHANNEL_ID_CLEAR = "clear"; - } diff --git a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainCommandResult.java b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainCommandResult.java index 5daf03e06a79f..d5bde659148f0 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainCommandResult.java +++ b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainCommandResult.java @@ -36,5 +36,4 @@ public enum EtherRainCommandResult { public String getResult() { return result; } - } diff --git a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainCommandStatus.java b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainCommandStatus.java index 727d98327866f..e196a6715c49c 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainCommandStatus.java +++ b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainCommandStatus.java @@ -35,5 +35,4 @@ public enum EtherRainCommandStatus { public String getStatus() { return status; } - } diff --git a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainOperatingStatus.java b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainOperatingStatus.java index c26f0638e8778..48cbf3aa62d4f 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainOperatingStatus.java +++ b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainOperatingStatus.java @@ -35,5 +35,4 @@ public enum EtherRainOperatingStatus { public String getStatus() { return status; } - } diff --git a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainUdpResponse.java b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainUdpResponse.java index 155e8b7cc1ce5..944cbf6536b6d 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainUdpResponse.java +++ b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/api/EtherRainUdpResponse.java @@ -70,5 +70,4 @@ public String getUnqiueName() { public String getAdditionalParameters() { return additionalParameters; } - } diff --git a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/config/EtherRainConfiguration.java b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/config/EtherRainConfiguration.java index 007adb4532b39..7e3c1d6fe6f45 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/config/EtherRainConfiguration.java +++ b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/config/EtherRainConfiguration.java @@ -71,5 +71,4 @@ public class EtherRainConfiguration { public int zoneOnTime6 = 0; public int zoneOnTime7 = 0; public int zoneOnTime8 = 0; - } diff --git a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/discovery/EtherrainDiscoveryService.java b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/discovery/EtherrainDiscoveryService.java index 96b7efe1c8cea..0afd1705a2989 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/discovery/EtherrainDiscoveryService.java +++ b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/discovery/EtherrainDiscoveryService.java @@ -64,6 +64,5 @@ protected void startScan() { logger.debug("Nothing responded to request"); } } - } } diff --git a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/handler/EtherRainHandler.java b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/handler/EtherRainHandler.java index 3d0063ab3d7b6..c259f2f4e0c4f 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/handler/EtherRainHandler.java +++ b/bundles/org.openhab.binding.etherrain/src/main/java/org/openhab/binding/etherrain/internal/handler/EtherRainHandler.java @@ -212,5 +212,4 @@ public void initialize() { public void dispose() { stopUpdateJob(); } - } diff --git a/bundles/org.openhab.binding.etherrain/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.etherrain/src/main/resources/ESH-INF/binding/binding.xml index 5d4e4a7a68786..42f343a7f3c7e 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.etherrain/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,5 @@ - EtherRain Binding diff --git a/bundles/org.openhab.binding.etherrain/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.etherrain/src/main/resources/ESH-INF/thing/thing-types.xml index 3b8161b143e7a..d1a09199b9a76 100644 --- a/bundles/org.openhab.binding.etherrain/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.etherrain/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,6 @@ - @@ -11,12 +9,12 @@ This is a stand alone EtherRain device that allows sprinkler control - - - + + + - - + + @@ -103,7 +101,7 @@ Status of the last command given to the Etherrain Water - + @@ -111,7 +109,7 @@ Current operating status of the Etherrain Water - + @@ -119,7 +117,7 @@ Result of operating status Water - + @@ -127,7 +125,7 @@ Provides feedback on whether the EtherRain device has detected rain or not Sensor - + @@ -142,7 +140,7 @@ Number of the last zone that was operating Number - + @@ -152,4 +150,4 @@ Switch - \ No newline at end of file + diff --git a/bundles/org.openhab.binding.evohome/pom.xml b/bundles/org.openhab.binding.evohome/pom.xml index 994cdacd53778..246a03a79d214 100644 --- a/bundles/org.openhab.binding.evohome/pom.xml +++ b/bundles/org.openhab.binding.evohome/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.evohome diff --git a/bundles/org.openhab.binding.evohome/src/main/feature/feature.xml b/bundles/org.openhab.binding.evohome/src/main/feature/feature.xml index 2f4ac3e249090..00d544b2317d3 100644 --- a/bundles/org.openhab.binding.evohome/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.evohome/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - mvn:org.openhab.addons.bundles/org.openhab.binding.evohome/${project.version} - + + openhab-runtime-base + openhab-transport-http + mvn:org.openhab.addons.bundles/org.openhab.binding.evohome/${project.version} + diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/EvohomeHandlerFactory.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/EvohomeHandlerFactory.java index db54d34f3f75f..65621adf0e8d5 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/EvohomeHandlerFactory.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/EvohomeHandlerFactory.java @@ -105,5 +105,4 @@ protected void setHttpClientFactory(HttpClientFactory httpClientFactory) { protected void unsetHttpClientFactory(HttpClientFactory httpClientFactory) { this.httpClient = null; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/RunnableWithTimeout.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/RunnableWithTimeout.java index fb1309e1eae31..7f17c3cfb7cd5 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/RunnableWithTimeout.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/RunnableWithTimeout.java @@ -23,5 +23,4 @@ public interface RunnableWithTimeout { public abstract void run() throws TimeoutException; - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/EvohomeApiClient.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/EvohomeApiClient.java index 60efa794a3013..7d0ff20b3714b 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/EvohomeApiClient.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/EvohomeApiClient.java @@ -257,5 +257,4 @@ private void updateAuthentication() { } } } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/EvohomeApiConstants.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/EvohomeApiConstants.java index f43dcffaeffd3..fab7aa3c46f08 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/EvohomeApiConstants.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/EvohomeApiConstants.java @@ -23,14 +23,13 @@ public class EvohomeApiConstants { public static final String URL_V2_BASE = "https://tccna.honeywell.com/WebAPI/emea/api/v1/"; - public static final String URL_V2_ACCOUNT = "userAccount"; + public static final String URL_V2_ACCOUNT = "userAccount"; public static final String URL_V2_INSTALLATION_INFO = "location/installationInfo?userId=%s&includeTemperatureControlSystems=True";// {userId} - public static final String URL_V2_LOCATION = "location/%s/installationInfo?includeTemperatureControlSystems=True"; // {locationId} - public static final String URL_V2_GATEWAY = "gateway"; - public static final String URL_V2_HOT_WATER = "domesticHotWater/%s/state"; // {hardwareId} - public static final String URL_V2_SCHEDULE = "%s/%s/schedule"; // {zone_type}, {zoneId} - public static final String URL_V2_HEAT_SETPOINT = "temperatureZone/%s/heatSetpoint"; // {zoneId} - public static final String URL_V2_LOCATION_STATUS = "location/%s/status?includeTemperatureControlSystems=True"; // {locationId} - public static final String URL_V2_MODE = "temperatureControlSystem/%s/mode"; // {systemId} - + public static final String URL_V2_LOCATION = "location/%s/installationInfo?includeTemperatureControlSystems=True"; // {locationId} + public static final String URL_V2_GATEWAY = "gateway"; + public static final String URL_V2_HOT_WATER = "domesticHotWater/%s/state"; // {hardwareId} + public static final String URL_V2_SCHEDULE = "%s/%s/schedule"; // {zone_type}, {zoneId} + public static final String URL_V2_HEAT_SETPOINT = "temperatureZone/%s/heatSetpoint"; // {zoneId} + public static final String URL_V2_LOCATION_STATUS = "location/%s/status?includeTemperatureControlSystems=True"; // {locationId} + public static final String URL_V2_MODE = "temperatureControlSystem/%s/mode"; // {systemId} } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/HeatSetPoint.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/HeatSetPoint.java index f43f3ea56a802..7bc4f05ea681c 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/HeatSetPoint.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/HeatSetPoint.java @@ -51,5 +51,4 @@ public class HeatSetPoint { @SerializedName("timeUntil") private String timeUntil; - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/HeatSetPointBuilder.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/HeatSetPointBuilder.java index 09da0c6c5d952..2bb4a13adaeaa 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/HeatSetPointBuilder.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/HeatSetPointBuilder.java @@ -51,5 +51,4 @@ public HeatSetPointBuilder setCancelSetPoint() { cancelSetPoint = true; return this; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/Mode.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/Mode.java index f03fc85565fe5..27ae53ac8b379 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/Mode.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/Mode.java @@ -42,5 +42,4 @@ public class Mode { @SerializedName("permanent") private boolean permanent; - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/ModeBuilder.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/ModeBuilder.java index af99fa388de45..27d5dd3ba0338 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/ModeBuilder.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/ModeBuilder.java @@ -46,5 +46,4 @@ public ModeBuilder setMode(String mode) { this.mode = mode; return this; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/RequestBuilder.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/RequestBuilder.java index 077be44198997..f1a4406f7747a 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/RequestBuilder.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/RequestBuilder.java @@ -21,5 +21,4 @@ public interface RequestBuilder { public T build(); - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/TimedRequestBuilder.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/TimedRequestBuilder.java index 7e1ef8dac3435..613158d1bb9b6 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/TimedRequestBuilder.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/request/TimedRequestBuilder.java @@ -47,5 +47,4 @@ protected int getMonth() { protected int getDay() { return day; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Authentication.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Authentication.java index 868649038fa86..98a412a0d46bc 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Authentication.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Authentication.java @@ -59,5 +59,4 @@ public void setSystemTime(long systemTime) { public long getSystemTime() { return systemTime; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Gateway.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Gateway.java index bdc9a5a05d9a7..b01944ddfeb04 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Gateway.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Gateway.java @@ -37,5 +37,4 @@ public GatewayInfo getGatewayInfo() { public List getTemperatureControlSystems() { return temperatureControlSystems; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/GatewayStatus.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/GatewayStatus.java index 2c8e8000e2b72..ba089c1d2dd5e 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/GatewayStatus.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/GatewayStatus.java @@ -44,5 +44,4 @@ public boolean hasActiveFaults() { public ActiveFault getActiveFault(int index) { return activeFaults.get(index); } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/HeatSetpointCapabilities.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/HeatSetpointCapabilities.java index 9bf7e024b1a1f..96587cba27cd2 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/HeatSetpointCapabilities.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/HeatSetpointCapabilities.java @@ -41,5 +41,4 @@ public class HeatSetpointCapabilities { @SerializedName("timingResolution") private String timingResolution; - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/HeatSetpointStatus.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/HeatSetpointStatus.java index f5877f1a5aef7..0719966d0f0c1 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/HeatSetpointStatus.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/HeatSetpointStatus.java @@ -35,5 +35,4 @@ public double getTargetTemperature() { public String getSetpointMode() { return setpointMode; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationInfo.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationInfo.java index 396a28f05d940..2e7c876a4c726 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationInfo.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationInfo.java @@ -59,5 +59,4 @@ public String getLocationId() { public String getName() { return name; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationOwner.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationOwner.java index 52d41d64836c9..e1202445a81a6 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationOwner.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationOwner.java @@ -33,5 +33,4 @@ public class LocationOwner { @SerializedName("lastname") private String lastName; - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationStatus.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationStatus.java index c17340831e509..cb220f8eadd43 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationStatus.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/LocationStatus.java @@ -39,5 +39,4 @@ public LocationStatus() { public List getGateways() { return gateways; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Mode.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Mode.java index a00cedbea49ca..f1480715bc96e 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Mode.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Mode.java @@ -39,5 +39,4 @@ public class Mode { @SerializedName("timingResolution") private String timingResolution; - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/ScheduleCapabilities.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/ScheduleCapabilities.java index b6b9af7989042..e9b1f705e2ca1 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/ScheduleCapabilities.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/ScheduleCapabilities.java @@ -33,5 +33,4 @@ public class ScheduleCapabilities { @SerializedName("timingResolution") private String timingResolution; - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/SystemModeStatus.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/SystemModeStatus.java index 8a27d62df482b..5d9f35710fbcd 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/SystemModeStatus.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/SystemModeStatus.java @@ -31,5 +31,4 @@ public class SystemModeStatus { public String getMode() { return mode; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureControlSystem.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureControlSystem.java index 89f6ba049baa4..5efddd57e127c 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureControlSystem.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureControlSystem.java @@ -43,5 +43,4 @@ public String getSystemId() { public List getZones() { return zones; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureControlSystemStatus.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureControlSystemStatus.java index 6baffbc00072f..f0d651083f338 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureControlSystemStatus.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureControlSystemStatus.java @@ -47,5 +47,4 @@ public SystemModeStatus getMode() { public List getZones() { return zones; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureStatus.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureStatus.java index 5ecc7d23f995a..4939f1bac9441 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureStatus.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TemperatureStatus.java @@ -31,5 +31,4 @@ public class TemperatureStatus { public double getTemperature() { return temperature; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TimeZone.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TimeZone.java index 376e4f91c98ad..f7262202011ad 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TimeZone.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/TimeZone.java @@ -36,5 +36,4 @@ public class TimeZone { @SerializedName("supportsDaylightSaving") private boolean supportsDaylightSaving; - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/UserAccount.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/UserAccount.java index b4f3828e725af..d2ebb48ebfcab 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/UserAccount.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/UserAccount.java @@ -52,5 +52,4 @@ public class UserAccount { public String getUserId() { return userId; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Zone.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Zone.java index 2f08f3dd7923a..97397ddcd2993 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Zone.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/Zone.java @@ -47,5 +47,4 @@ public String getZoneId() { public String getName() { return name; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/ZoneStatus.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/ZoneStatus.java index 1bf6a056c5bfd..e3afa792d7f6a 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/ZoneStatus.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/api/models/v2/response/ZoneStatus.java @@ -58,5 +58,4 @@ public boolean hasActiveFaults() { public ActiveFault getActiveFault(int index) { return activeFaults.get(index); } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/discovery/EvohomeDiscoveryService.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/discovery/EvohomeDiscoveryService.java index 0325f53a2efb6..6fc1bcd7d47bd 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/discovery/EvohomeDiscoveryService.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/discovery/EvohomeDiscoveryService.java @@ -130,5 +130,4 @@ private void addDiscoveredThing(ThingUID thingUID, Map propertie .withBridge(bridgeUID).withLabel(displayLabel).build(); thingDiscovered(discoveryResult); } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/AccountStatusListener.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/AccountStatusListener.java index 7d27203e76f13..f9012d2985e5b 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/AccountStatusListener.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/AccountStatusListener.java @@ -28,5 +28,4 @@ public interface AccountStatusListener { * @param status The new status of the account thing */ public void accountStatusChanged(ThingStatus status); - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/BaseEvohomeHandler.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/BaseEvohomeHandler.java index 6f70227dc7938..23e060372d0e4 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/BaseEvohomeHandler.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/BaseEvohomeHandler.java @@ -136,5 +136,4 @@ private void checkConfig() { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Id not configured"); } } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeAccountBridgeHandler.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeAccountBridgeHandler.java index 4a3008791a312..43f785d64715f 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeAccountBridgeHandler.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeAccountBridgeHandler.java @@ -275,5 +275,4 @@ private void updateThings() { } } } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeHeatingZoneHandler.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeHeatingZoneHandler.java index b71895fe4cc9b..644e590633d08 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeHeatingZoneHandler.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeHeatingZoneHandler.java @@ -102,5 +102,4 @@ private boolean handleActiveFaults(ZoneStatus zoneStatus) { } return false; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeTemperatureControlSystemHandler.java b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeTemperatureControlSystemHandler.java index b9c16488471e0..22caa04f7efb6 100644 --- a/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeTemperatureControlSystemHandler.java +++ b/bundles/org.openhab.binding.evohome/src/main/java/org/openhab/binding/evohome/internal/handler/EvohomeTemperatureControlSystemHandler.java @@ -76,5 +76,4 @@ private boolean handleActiveFaults(GatewayStatus gatewayStatus) { } return false; } - } diff --git a/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/binding/binding.xml index e7d59f10f7cb9..9713915143ba1 100644 --- a/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,7 @@ - + evohome Binding The evohome binding controls the Honeywell evohome system. Jasper van Zuijlen diff --git a/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/bridge.xml index 9251ecaab5d07..fe0e59ed535f6 100644 --- a/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,9 +1,13 @@ - + - The evohome account is used to connect to your Total Connect Comfort (TCC) using your TCC username and password. + The evohome account is used to connect to your Total Connect Comfort (TCC) using your TCC username and + password. diff --git a/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/channels.xml index bd782b257338f..c7b8c7e2538f3 100644 --- a/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/channels.xml @@ -1,5 +1,8 @@ - + String @@ -29,7 +32,7 @@ Gets or sets the set point of this zone (0 cancels the override). heating - + String diff --git a/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/thing-types.xml index 50cd2ce9c156b..57eb85be349f9 100644 --- a/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.evohome/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,13 +1,16 @@ - + - + This represents the evohome control display. - + @@ -22,16 +25,16 @@ - + This represents the evohome Heating Zone. - - - + + + - + ID of the zone diff --git a/bundles/org.openhab.binding.exec/pom.xml b/bundles/org.openhab.binding.exec/pom.xml index 838f361563db6..8829345fcf602 100644 --- a/bundles/org.openhab.binding.exec/pom.xml +++ b/bundles/org.openhab.binding.exec/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.exec diff --git a/bundles/org.openhab.binding.exec/src/main/feature/feature.xml b/bundles/org.openhab.binding.exec/src/main/feature/feature.xml index c4352dbe55c8d..19de0c221a998 100644 --- a/bundles/org.openhab.binding.exec/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.exec/src/main/feature/feature.xml @@ -1,6 +1,5 @@ - + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features diff --git a/bundles/org.openhab.binding.exec/src/main/java/org/openhab/binding/exec/internal/ExecHandlerFactory.java b/bundles/org.openhab.binding.exec/src/main/java/org/openhab/binding/exec/internal/ExecHandlerFactory.java index 6bd853a3c5794..2a6b06d5d058f 100644 --- a/bundles/org.openhab.binding.exec/src/main/java/org/openhab/binding/exec/internal/ExecHandlerFactory.java +++ b/bundles/org.openhab.binding.exec/src/main/java/org/openhab/binding/exec/internal/ExecHandlerFactory.java @@ -12,6 +12,11 @@ */ package org.openhab.binding.exec.internal; +import static org.openhab.binding.exec.internal.ExecBindingConstants.THING_COMMAND; + +import java.util.Collections; +import java.util.Set; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Thing; @@ -26,11 +31,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Collections; -import java.util.Set; - -import static org.openhab.binding.exec.internal.ExecBindingConstants.THING_COMMAND; - /** * The {@link ExecHandlerFactory} is responsible for creating things and thing * handlers. diff --git a/bundles/org.openhab.binding.exec/src/main/java/org/openhab/binding/exec/internal/handler/ExecHandler.java b/bundles/org.openhab.binding.exec/src/main/java/org/openhab/binding/exec/internal/handler/ExecHandler.java index 2c43f64e3e455..1940a9a669165 100644 --- a/bundles/org.openhab.binding.exec/src/main/java/org/openhab/binding/exec/internal/handler/ExecHandler.java +++ b/bundles/org.openhab.binding.exec/src/main/java/org/openhab/binding/exec/internal/handler/ExecHandler.java @@ -12,6 +12,22 @@ */ package org.openhab.binding.exec.internal.handler; +import static org.openhab.binding.exec.internal.ExecBindingConstants.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigDecimal; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.Calendar; +import java.util.IllegalFormatException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -34,22 +50,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.math.BigDecimal; -import java.time.ZonedDateTime; -import java.util.Arrays; -import java.util.Calendar; -import java.util.IllegalFormatException; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -import static org.openhab.binding.exec.internal.ExecBindingConstants.*; - /** * The {@link ExecHandler} is responsible for handling commands, which are * sent to one of the channels. @@ -127,8 +127,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void initialize() { if (executionJob == null || executionJob.isCancelled()) { - if ((getConfig().get(INTERVAL)) != null && ((BigDecimal) getConfig().get(INTERVAL)) - .intValue() > 0) { + if ((getConfig().get(INTERVAL)) != null && ((BigDecimal) getConfig().get(INTERVAL)).intValue() > 0) { int pollingInterval = ((BigDecimal) getConfig().get(INTERVAL)).intValue(); executionJob = scheduler.scheduleWithFixedDelay(this::execute, 0, pollingInterval, TimeUnit.SECONDS); } @@ -309,8 +308,8 @@ public void execute() { String transformationType = parts[0]; String transformationFunction = parts[1]; - TransformationService transformationService = TransformationHelper - .getTransformationService(bundleContext, transformationType); + TransformationService transformationService = TransformationHelper.getTransformationService(bundleContext, + transformationType); if (transformationService != null) { transformedResponse = transformationService.transform(transformationFunction, response); } else { @@ -341,8 +340,8 @@ protected String[] splitTransformationConfig(String transformation) { Matcher matcher = EXTRACT_FUNCTION_PATTERN.matcher(transformation); if (!matcher.matches()) { - throw new IllegalArgumentException( - "given transformation function '" + transformation + "' does not follow the expected pattern '()'"); + throw new IllegalArgumentException("given transformation function '" + transformation + + "' does not follow the expected pattern '()'"); } matcher.reset(); @@ -394,7 +393,12 @@ protected String[] createCmdArray(String[] shell, String cOption, String command * @author Constantin Piber (for Memin) - Initial contribution */ public enum OS { - WINDOWS, LINUX, MAC, SOLARIS, UNKNOWN, NOT_SET + WINDOWS, + LINUX, + MAC, + SOLARIS, + UNKNOWN, + NOT_SET } private static OS os = OS.NOT_SET; @@ -420,5 +424,4 @@ public static OS getOperatingSystemType() { public static String getOperatingSystemName() { return System.getProperty("os.name"); } - } diff --git a/bundles/org.openhab.binding.exec/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.exec/src/main/resources/ESH-INF/thing/thing-types.xml index 656911205cb29..ebcaad830ab8e 100644 --- a/bundles/org.openhab.binding.exec/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.exec/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,11 +9,11 @@ The Command encapsulates a shell command to be executed - - - - - + + + + + diff --git a/bundles/org.openhab.binding.feed/pom.xml b/bundles/org.openhab.binding.feed/pom.xml index 386b3dee840e8..8708f7ca719cb 100644 --- a/bundles/org.openhab.binding.feed/pom.xml +++ b/bundles/org.openhab.binding.feed/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.feed diff --git a/bundles/org.openhab.binding.feed/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.feed/src/main/resources/ESH-INF/binding/binding.xml index 8520f5ff17764..3a48a8fd272d6 100644 --- a/bundles/org.openhab.binding.feed/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.feed/src/main/resources/ESH-INF/binding/binding.xml @@ -5,7 +5,8 @@ Feed Binding The Feed Binding downloads Feed data from URL, - displays information about the feed (number of Entries, last published date, author, feed title and description, last entry) + displays information about the feed (number of Entries, last + published date, author, feed title and description, last entry) and tracks for changes in the Feed at intervals. Svilen Valkanov diff --git a/bundles/org.openhab.binding.feed/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.feed/src/main/resources/ESH-INF/thing/thing-types.xml index eaa35eb3e9113..2c64a443ef22c 100644 --- a/bundles/org.openhab.binding.feed/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.feed/src/main/resources/ESH-INF/thing/thing-types.xml @@ -5,7 +5,8 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -15,14 +16,14 @@ Provides information about a feed. - - - - - - - - + + + + + + + + @@ -47,56 +48,56 @@ String Contains the title of the last feed entry. - + String Contains the description of last feed entry. - + DateTime Contains the published date of the last feed entry. - + String The name of the feed author, if author is present - + String The title of the feed - + String Description of the feed - + DateTime The last update date of the feed - + Number Number of entries in the feed - + diff --git a/bundles/org.openhab.binding.feican/pom.xml b/bundles/org.openhab.binding.feican/pom.xml index d99a99a635da6..804a2ee78aced 100644 --- a/bundles/org.openhab.binding.feican/pom.xml +++ b/bundles/org.openhab.binding.feican/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.feican diff --git a/bundles/org.openhab.binding.feican/src/main/feature/feature.xml b/bundles/org.openhab.binding.feican/src/main/feature/feature.xml index 6b3a8d4d7c71e..75483e2dc03e0 100644 --- a/bundles/org.openhab.binding.feican/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.feican/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.feican/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.feican/${project.version} + diff --git a/bundles/org.openhab.binding.feican/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.feican/src/main/resources/ESH-INF/binding/binding.xml index c732af7bbdae0..96a399d1a3499 100644 --- a/bundles/org.openhab.binding.feican/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.feican/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Feican Binding This is the binding for Feican light bulbs. diff --git a/bundles/org.openhab.binding.feican/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.feican/src/main/resources/ESH-INF/thing/thing-types.xml index 8ff76807784ac..3203300435982 100644 --- a/bundles/org.openhab.binding.feican/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.feican/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,18 +1,18 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> A dimmable light with changeable colors. - - - - + + + + diff --git a/bundles/org.openhab.binding.folding/pom.xml b/bundles/org.openhab.binding.folding/pom.xml index 368354ed8a297..ba951caca6c38 100644 --- a/bundles/org.openhab.binding.folding/pom.xml +++ b/bundles/org.openhab.binding.folding/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.folding diff --git a/bundles/org.openhab.binding.folding/src/main/feature/feature.xml b/bundles/org.openhab.binding.folding/src/main/feature/feature.xml index 54b659f02ebfb..86b128e1a319b 100644 --- a/bundles/org.openhab.binding.folding/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.folding/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.folding/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.folding/${project.version} + diff --git a/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/FoldingBindingConstants.java b/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/FoldingBindingConstants.java index e68e30d7df871..8f84d8f296888 100644 --- a/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/FoldingBindingConstants.java +++ b/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/FoldingBindingConstants.java @@ -34,5 +34,4 @@ public class FoldingBindingConstants { // List of all Channel ids public static final String CHANNEL_STATUS = "status"; - } diff --git a/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/discovery/FoldingDiscoveryProxy.java b/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/discovery/FoldingDiscoveryProxy.java index 1a8b75469110b..f5714bd41c78f 100644 --- a/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/discovery/FoldingDiscoveryProxy.java +++ b/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/discovery/FoldingDiscoveryProxy.java @@ -44,5 +44,4 @@ public void newSlot(ThingUID bridgeUID, String host, String id, String descripti discoveryService.newSlot(bridgeUID, host, id, description); } } - } diff --git a/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/handler/SlotHandler.java b/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/handler/SlotHandler.java index 1505c3726113c..b8af4fcdf4649 100644 --- a/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/handler/SlotHandler.java +++ b/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/handler/SlotHandler.java @@ -87,5 +87,4 @@ public void refreshed(SlotInfo si) { updateState(getThing().getChannel("run").getUID(), run ? OnOffType.ON : OnOffType.OFF); updateState(getThing().getChannel("description").getUID(), new StringType(si.description)); } - } diff --git a/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/handler/SlotInfo.java b/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/handler/SlotInfo.java index 658545aec2d99..1c691915d8360 100644 --- a/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/handler/SlotInfo.java +++ b/bundles/org.openhab.binding.folding/src/main/java/org/openhab/binding/folding/internal/handler/SlotInfo.java @@ -27,5 +27,4 @@ public class SlotInfo { public String id, status, description, reason; public Map options; boolean idle; - } diff --git a/bundles/org.openhab.binding.folding/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.folding/src/main/resources/ESH-INF/binding/binding.xml index 57447bf47da4d..40056c74c8830 100644 --- a/bundles/org.openhab.binding.folding/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.folding/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Folding@home diff --git a/bundles/org.openhab.binding.folding/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.folding/src/main/resources/ESH-INF/thing/thing-types.xml index 35b2c35406f9e..19c5612c27569 100644 --- a/bundles/org.openhab.binding.folding/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.folding/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -8,8 +9,8 @@ Folding@home client daemon (represented as bridge). - - + + @@ -49,17 +50,17 @@ - + Folding client compute slot. - - - - + + + + @@ -75,13 +76,13 @@ String Description of the Folding@home slot. - + String Current status - + diff --git a/bundles/org.openhab.binding.foobot/pom.xml b/bundles/org.openhab.binding.foobot/pom.xml index 5eb6e429cfe46..27e5660ef6ad5 100644 --- a/bundles/org.openhab.binding.foobot/pom.xml +++ b/bundles/org.openhab.binding.foobot/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.foobot diff --git a/bundles/org.openhab.binding.foobot/src/main/feature/feature.xml b/bundles/org.openhab.binding.foobot/src/main/feature/feature.xml index c28c56fe50eef..efeb0c4b46366 100644 --- a/bundles/org.openhab.binding.foobot/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.foobot/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.foobot/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.foobot/${project.version} + diff --git a/bundles/org.openhab.binding.foobot/src/main/java/org/openhab/binding/foobot/internal/handler/FoobotDeviceHandler.java b/bundles/org.openhab.binding.foobot/src/main/java/org/openhab/binding/foobot/internal/handler/FoobotDeviceHandler.java index f2e6db6ce7de4..bd58bf6bcf40a 100644 --- a/bundles/org.openhab.binding.foobot/src/main/java/org/openhab/binding/foobot/internal/handler/FoobotDeviceHandler.java +++ b/bundles/org.openhab.binding.foobot/src/main/java/org/openhab/binding/foobot/internal/handler/FoobotDeviceHandler.java @@ -217,5 +217,4 @@ protected State sensorDataToState(final String channelId, final FoobotJsonData d ? (FoobotAccountHandler) getBridge().getHandler() : null; } - } diff --git a/bundles/org.openhab.binding.foobot/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.foobot/src/main/resources/ESH-INF/binding/binding.xml index 6e75bf30e17fa..0878247245f36 100644 --- a/bundles/org.openhab.binding.foobot/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.foobot/src/main/resources/ESH-INF/binding/binding.xml @@ -4,6 +4,7 @@ xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd"> Foobot - Foobot binding allow users to connect to their foobots in home or office and get real-time updates on the Air Quality. + Foobot binding allow users to connect to their foobots in home or office and get real-time updates on the + Air Quality. Divya Chauhan and George Katsis diff --git a/bundles/org.openhab.binding.foobot/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.foobot/src/main/resources/ESH-INF/thing/thing-types.xml index 052aa4e76714b..7e352fac1b590 100644 --- a/bundles/org.openhab.binding.foobot/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.foobot/src/main/resources/ESH-INF/thing/thing-types.xml @@ -10,7 +10,7 @@ Your Foobot account. - + @@ -36,20 +36,20 @@ - + A Foobot device. - - - - - - - + + + + + + + uuid @@ -66,52 +66,52 @@ DateTime The last time the sensor data was uploaded to Foobot - + Number:Density Particulate Matter Level - + Number:Temperature Temperature Temperature - + Number:Dimensionless Humidity Level Humidity - + Number:Dimensionless Carbon dioxide Level CarbonDioxide - + Number:Dimensionless Volatile Organic Compounds Level - + Number:Dimensionless Global Pollution Index Level - + Number The remaining number of calls that can be made to the api today - + diff --git a/bundles/org.openhab.binding.freebox/pom.xml b/bundles/org.openhab.binding.freebox/pom.xml index 3c7b382e23e02..c40b94117be79 100644 --- a/bundles/org.openhab.binding.freebox/pom.xml +++ b/bundles/org.openhab.binding.freebox/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.freebox diff --git a/bundles/org.openhab.binding.freebox/src/main/feature/feature.xml b/bundles/org.openhab.binding.freebox/src/main/feature/feature.xml index 7e6834d806c5c..f6f6bb849088e 100644 --- a/bundles/org.openhab.binding.freebox/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.freebox/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - mvn:org.openhab.addons.bundles/org.openhab.binding.freebox/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + mvn:org.openhab.addons.bundles/org.openhab.binding.freebox/${project.version} + diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/FreeboxAirPlayAudioSink.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/FreeboxAirPlayAudioSink.java index d3398a6391f89..1f7cfab4b8f6c 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/FreeboxAirPlayAudioSink.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/FreeboxAirPlayAudioSink.java @@ -173,5 +173,4 @@ public PercentType getVolume() { public void setVolume(PercentType volume) { throw new UnsupportedOperationException("Volume can not be set"); } - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/FreeboxHandlerFactory.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/FreeboxHandlerFactory.java index 65f9df94cafcb..ff742b211df7e 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/FreeboxHandlerFactory.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/FreeboxHandlerFactory.java @@ -21,6 +21,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.config.discovery.DiscoveryService; @@ -40,6 +41,7 @@ import org.openhab.binding.freebox.internal.handler.FreeboxThingHandler; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; @@ -52,25 +54,32 @@ * @author Gaël L'hopital - Initial contribution * @author Laurent Garnier - several thing types and handlers + discovery service */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.freebox") public class FreeboxHandlerFactory extends BaseThingHandlerFactory { - private final Logger logger = LoggerFactory.getLogger(FreeboxHandlerFactory.class); + private static final Set SUPPORTED_THING_TYPES_UIDS = Stream + .concat(FreeboxBindingConstants.SUPPORTED_BRIDGE_TYPES_UIDS.stream(), + FreeboxBindingConstants.SUPPORTED_THING_TYPES_UIDS.stream()) + .collect(Collectors.toSet()); - private Map> discoveryServiceRegs = new HashMap<>(); + private final Logger logger = LoggerFactory.getLogger(FreeboxHandlerFactory.class); - private AudioHTTPServer audioHTTPServer; - private NetworkAddressService networkAddressService; + private final Map> discoveryServiceRegs = new HashMap<>(); + private final Map> audioSinkRegistrations = new ConcurrentHashMap<>(); - private Map> audioSinkRegistrations = new ConcurrentHashMap<>(); + private final AudioHTTPServer audioHTTPServer; + private final NetworkAddressService networkAddressService; // url (scheme+server+port) to use for playing notification sounds private @Nullable String callbackUrl; - private static final Set SUPPORTED_THING_TYPES_UIDS = Stream - .concat(FreeboxBindingConstants.SUPPORTED_BRIDGE_TYPES_UIDS.stream(), - FreeboxBindingConstants.SUPPORTED_THING_TYPES_UIDS.stream()) - .collect(Collectors.toSet()); + @Activate + public FreeboxHandlerFactory(final @Reference AudioHTTPServer audioHTTPServer, + final @Reference NetworkAddressService networkAddressService) { + this.audioHTTPServer = audioHTTPServer; + this.networkAddressService = networkAddressService; + } @Override protected void activate(ComponentContext componentContext) { @@ -85,8 +94,8 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID, - ThingUID bridgeUID) { + public @Nullable Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, + @Nullable ThingUID thingUID, @Nullable ThingUID bridgeUID) { if (thingTypeUID.equals(FreeboxBindingConstants.FREEBOX_BRIDGE_TYPE_SERVER)) { return super.createThing(thingTypeUID, configuration, thingUID, null); } else if (FreeboxBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { @@ -103,7 +112,7 @@ public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(FreeboxBindingConstants.FREEBOX_BRIDGE_TYPE_SERVER)) { @@ -166,7 +175,7 @@ private synchronized void unregisterAudioSink(Thing thing) { } } - private String createCallbackUrl() { + private @Nullable String createCallbackUrl() { if (callbackUrl != null) { return callbackUrl; } else { @@ -186,23 +195,4 @@ private String createCallbackUrl() { return "http://" + ipAddress + ":" + port; } } - - @Reference - protected void setAudioHTTPServer(AudioHTTPServer audioHTTPServer) { - this.audioHTTPServer = audioHTTPServer; - } - - protected void unsetAudioHTTPServer(AudioHTTPServer audioHTTPServer) { - this.audioHTTPServer = null; - } - - @Reference - protected void setNetworkAddressService(NetworkAddressService networkAddressService) { - this.networkAddressService = networkAddressService; - } - - protected void unsetNetworkAddressService(NetworkAddressService networkAddressService) { - this.networkAddressService = null; - } - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/api/FreeboxApiManager.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/api/FreeboxApiManager.java index 06b4934ba681c..928b1e77d93af 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/api/FreeboxApiManager.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/api/FreeboxApiManager.java @@ -28,8 +28,7 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import org.apache.commons.codec.binary.Hex; -import org.apache.commons.lang.StringUtils; +import org.eclipse.smarthome.core.util.HexUtils; import org.eclipse.smarthome.io.net.http.HttpUtil; import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaConfig; import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaConfigResponse; @@ -133,7 +132,7 @@ public boolean authorize(boolean useHttps, String fqdn, String apiBaseUrl, Strin boolean granted = false; try { String token = appToken; - if (StringUtils.isEmpty(token)) { + if (token == null || token.isEmpty()) { FreeboxAuthorizeRequest request = new FreeboxAuthorizeRequest(appId, appName, appVersion, deviceName); FreeboxAuthorizeResult response = executePostUrl("login/authorize/", gson.toJson(request), FreeboxAuthorizeResponse.class, false); @@ -351,7 +350,7 @@ public void playMedia(String url, String airPlayName, String airPlayPassword) th FreeboxAirMediaReceiverRequest request = new FreeboxAirMediaReceiverRequest(); request.setStartAction(); request.setVideoMediaType(); - if (StringUtils.isNotEmpty(airPlayPassword)) { + if (airPlayPassword != null && !airPlayPassword.isEmpty()) { request.setPassword(airPlayPassword); } request.setMedia(url); @@ -363,7 +362,7 @@ public void stopMedia(String airPlayName, String airPlayPassword) throws Freebox FreeboxAirMediaReceiverRequest request = new FreeboxAirMediaReceiverRequest(); request.setStopAction(); request.setVideoMediaType(); - if (StringUtils.isNotEmpty(airPlayPassword)) { + if (airPlayPassword != null && !airPlayPassword.isEmpty()) { request.setPassword(airPlayPassword); } executePostUrl("airmedia/receivers/" + encodeUrl(airPlayName) + "/", gson.toJson(request), @@ -480,7 +479,7 @@ private String encodeUrl(String url) throws FreeboxException { } } - private static String hmacSha1(String key, String value) throws FreeboxException { + public static String hmacSha1(String key, String value) throws FreeboxException { try { // Get an hmac_sha1 key from the raw key bytes byte[] keyBytes = key.getBytes(); @@ -493,14 +492,10 @@ private static String hmacSha1(String key, String value) throws FreeboxException // Compute the hmac on input data bytes byte[] rawHmac = mac.doFinal(value.getBytes()); - // Convert raw bytes to Hex - byte[] hexBytes = new Hex().encode(rawHmac); - - // Covert array of Hex bytes to a String - return new String(hexBytes, StandardCharsets.UTF_8); + // Convert raw bytes to a String + return HexUtils.bytesToHex(rawHmac).toLowerCase(); } catch (IllegalArgumentException | NoSuchAlgorithmException | InvalidKeyException | IllegalStateException e) { throw new FreeboxException("Computing the hmac-sha1 of the challenge and the app token failed", e); } } - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/api/model/FreeboxResponse.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/api/model/FreeboxResponse.java index bb3521bc9274c..533c94477ec15 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/api/model/FreeboxResponse.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/api/model/FreeboxResponse.java @@ -69,5 +69,4 @@ public String getMissingRight() { public T getResult() { return result; } - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxAirPlayDeviceConfiguration.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxAirPlayDeviceConfiguration.java index ab2284eb42610..d1f2e79755afc 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxAirPlayDeviceConfiguration.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxAirPlayDeviceConfiguration.java @@ -27,5 +27,4 @@ public class FreeboxAirPlayDeviceConfiguration { public String name; public String password; public Boolean acceptAllMp3; - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxNetDeviceConfiguration.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxNetDeviceConfiguration.java index b6e603c21207f..f6256a2c99a75 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxNetDeviceConfiguration.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxNetDeviceConfiguration.java @@ -24,5 +24,4 @@ public class FreeboxNetDeviceConfiguration { public static final String MAC_ADDRESS = "macAddress"; public String macAddress; - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxNetInterfaceConfiguration.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxNetInterfaceConfiguration.java index d6e0338fae1f1..2836ef9e0263a 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxNetInterfaceConfiguration.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxNetInterfaceConfiguration.java @@ -24,5 +24,4 @@ public class FreeboxNetInterfaceConfiguration { public static final String IP_ADDRESS = "ipAddress"; public String ipAddress; - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxPhoneConfiguration.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxPhoneConfiguration.java index 33a22d21709a7..ea37d3aac164a 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxPhoneConfiguration.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxPhoneConfiguration.java @@ -25,5 +25,4 @@ public class FreeboxPhoneConfiguration { public Integer refreshPhoneInterval; public Integer refreshPhoneCallsInterval; - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxServerConfiguration.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxServerConfiguration.java index 0e7171ccbe09d..b649eb41a876e 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxServerConfiguration.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/config/FreeboxServerConfiguration.java @@ -38,5 +38,4 @@ public class FreeboxServerConfiguration { public Boolean discoverNetDevice; public Boolean discoverNetInterface; public Boolean discoverAirPlayReceiver; - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/discovery/FreeboxDiscoveryService.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/discovery/FreeboxDiscoveryService.java index 787a6487a855a..37fa1b15deaca 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/discovery/FreeboxDiscoveryService.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/discovery/FreeboxDiscoveryService.java @@ -16,7 +16,6 @@ import java.util.List; import java.util.Map; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; @@ -149,16 +148,18 @@ public void onDataFetched(ThingUID bridge, List lanHosts, // Network devices for (FreeboxLanHost host : lanHosts) { String mac = host.getMAC(); - if (StringUtils.isNotEmpty(mac)) { + String primaryName = host.getPrimaryName(); + String vendorName = host.getVendorName(); + if (mac != null && !mac.isEmpty()) { if (discoverNetDevice) { String uid = mac.replaceAll("[^A-Za-z0-9_]", "_"); thingUID = new ThingUID(FreeboxBindingConstants.FREEBOX_THING_TYPE_NET_DEVICE, bridge, uid); - String name = StringUtils.isEmpty(host.getPrimaryName()) ? ("Freebox Network Device " + mac) - : host.getPrimaryName(); + String name = (primaryName == null || primaryName.isEmpty()) ? ("Freebox Network Device " + mac) + : primaryName; logger.trace("Adding new Freebox Network Device {} to inbox", thingUID); Map properties = new HashMap<>(1); - if (StringUtils.isNotEmpty(host.getVendorName())) { - properties.put(Thing.PROPERTY_VENDOR, host.getVendorName()); + if (vendorName != null && !vendorName.isEmpty()) { + properties.put(Thing.PROPERTY_VENDOR, vendorName); } properties.put(FreeboxNetDeviceConfiguration.MAC_ADDRESS, mac); discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) @@ -170,18 +171,18 @@ public void onDataFetched(ThingUID bridge, List lanHosts, if (host.getL3Connectivities() != null && discoverNetInterface) { for (FreeboxLanHostL3Connectivity l3 : host.getL3Connectivities()) { String addr = l3.getAddr(); - if (StringUtils.isNotEmpty(addr)) { + if (addr != null && !addr.isEmpty()) { String uid = addr.replaceAll("[^A-Za-z0-9_]", "_"); thingUID = new ThingUID(FreeboxBindingConstants.FREEBOX_THING_TYPE_NET_INTERFACE, bridge, uid); String name = addr; - if (StringUtils.isNotEmpty(host.getPrimaryName())) { - name += " (" + (host.getPrimaryName() + ")"); + if (primaryName != null && !primaryName.isEmpty()) { + name += " (" + (primaryName + ")"); } logger.trace("Adding new Freebox Network Interface {} to inbox", thingUID); Map properties = new HashMap<>(1); - if (StringUtils.isNotEmpty(host.getVendorName())) { - properties.put(Thing.PROPERTY_VENDOR, host.getVendorName()); + if (vendorName != null && !vendorName.isEmpty()) { + properties.put(Thing.PROPERTY_VENDOR, vendorName); } properties.put(FreeboxNetInterfaceConfiguration.IP_ADDRESS, addr); discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) @@ -203,7 +204,7 @@ public void onDataFetched(ThingUID bridge, List lanHosts, // The Freebox API allows pushing media only to receivers with photo or video capabilities // but not to receivers with only audio capability; so receivers without video capability // are ignored by the discovery - if (StringUtils.isNotEmpty(name) && videoCapable) { + if (name != null && !name.isEmpty() && videoCapable) { String uid = name.replaceAll("[^A-Za-z0-9_]", "_"); thingUID = new ThingUID(FreeboxBindingConstants.FREEBOX_THING_TYPE_AIRPLAY, bridge, uid); logger.trace("Adding new Freebox AirPlay Device {} to inbox", thingUID); @@ -216,5 +217,4 @@ public void onDataFetched(ThingUID bridge, List lanHosts, } } } - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/discovery/FreeboxServerDiscoveryParticipant.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/discovery/FreeboxServerDiscoveryParticipant.java index 63cdf5ce14eb4..12458065bb3bb 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/discovery/FreeboxServerDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/discovery/FreeboxServerDiscoveryParticipant.java @@ -92,5 +92,4 @@ public DiscoveryResult createResult(ServiceInfo service) { } return result; } - } diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/handler/FreeboxHandler.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/handler/FreeboxHandler.java index b733894789f01..d9fd8604c383b 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/handler/FreeboxHandler.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/handler/FreeboxHandler.java @@ -22,7 +22,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType; import org.eclipse.smarthome.core.library.types.OnOffType; @@ -150,7 +149,7 @@ public void initialize() { dataListener.applyConfig(configDiscovery); } - if (StringUtils.isNotEmpty(configuration.fqdn)) { + if (configuration.fqdn != null && !configuration.fqdn.isEmpty()) { updateStatus(ThingStatus.UNKNOWN); logger.debug("Binding will schedule a job to establish a connection..."); @@ -207,44 +206,47 @@ private void authorize() { if (!httpsRequestOk) { result = apiManager.checkApi(fqdn, false); } + String apiBaseUrl = result == null ? null : result.getApiBaseUrl(); + String apiVersion = result == null ? null : result.getApiVersion(); + String deviceType = result == null ? null : result.getDeviceType(); + String apiDomain = result == null ? null : result.getApiDomain(); + Integer httpsPort = result == null ? null : result.getHttpsPort(); boolean useHttps = false; String errorMsg = null; if (result == null) { errorMsg = "Can't connect to " + fqdn; - } else if (StringUtils.isEmpty(result.getApiBaseUrl())) { + } else if (apiBaseUrl == null || apiBaseUrl.isEmpty()) { errorMsg = fqdn + " does not deliver any API base URL"; - } else if (StringUtils.isEmpty(result.getApiVersion())) { + } else if (apiVersion == null || apiVersion.isEmpty()) { errorMsg = fqdn + " does not deliver any API version"; } else if (Boolean.TRUE.equals(result.isHttpsAvailable()) && !Boolean.TRUE.equals(configuration.useOnlyHttp)) { - if (result.getHttpsPort() == null || StringUtils.isEmpty(result.getApiDomain())) { + if (httpsPort == null || apiDomain == null || apiDomain.isEmpty()) { if (httpsRequestOk) { useHttps = true; } else { logger.debug("{} does not deliver API domain or HTTPS port; use HTTP API", fqdn); } - } else if (apiManager.checkApi(String.format("%s:%d", result.getApiDomain(), result.getHttpsPort()), - true) != null) { + } else if (apiManager.checkApi(String.format("%s:%d", apiDomain, httpsPort), true) != null) { useHttps = true; - fqdn = String.format("%s:%d", result.getApiDomain(), result.getHttpsPort()); + fqdn = String.format("%s:%d", apiDomain, httpsPort); } } if (errorMsg != null) { logger.debug("Thing {}: bad configuration: {}", getThing().getUID(), errorMsg); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMsg); - } else if (!apiManager.authorize(useHttps, fqdn, result.getApiBaseUrl(), result.getApiVersion(), - configuration.appToken)) { - if (StringUtils.isEmpty(configuration.appToken)) { + } else if (!apiManager.authorize(useHttps, fqdn, apiBaseUrl, apiVersion, configuration.appToken)) { + if (configuration.appToken == null || configuration.appToken.isEmpty()) { errorMsg = "App token not set in the thing configuration"; } else { errorMsg = "Check your app token in the thing configuration; opening session with " + fqdn + " using " - + (useHttps ? "HTTPS" : "HTTP") + " API version " + result.getApiVersion() + " failed"; + + (useHttps ? "HTTPS" : "HTTP") + " API version " + apiVersion + " failed"; } logger.debug("Thing {}: {}", getThing().getUID(), errorMsg); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMsg); } else { logger.debug("Thing {}: session opened with {} using {} API version {}", getThing().getUID(), fqdn, - (useHttps ? "HTTPS" : "HTTP"), result.getApiVersion()); + (useHttps ? "HTTPS" : "HTTP"), apiVersion); if (globalJob == null || globalJob.isCancelled()) { long pollingInterval = getConfigAs(FreeboxServerConfiguration.class).refreshInterval; logger.debug("Scheduling server state update every {} seconds...", pollingInterval); @@ -260,14 +262,14 @@ private void authorize() { } Map properties = editProperties(); - if (result != null && StringUtils.isNotEmpty(result.getApiBaseUrl())) { - properties.put(API_BASE_URL, result.getApiBaseUrl()); + if (apiBaseUrl != null && !apiBaseUrl.isEmpty()) { + properties.put(API_BASE_URL, apiBaseUrl); } - if (result != null && StringUtils.isNotEmpty(result.getApiVersion())) { - properties.put(API_VERSION, result.getApiVersion()); + if (apiVersion != null && !apiVersion.isEmpty()) { + properties.put(API_VERSION, apiVersion); } - if (result != null && StringUtils.isNotEmpty(result.getDeviceType())) { - properties.put(Thing.PROPERTY_HARDWARE_VERSION, result.getDeviceType()); + if (deviceType != null && !deviceType.isEmpty()) { + properties.put(Thing.PROPERTY_HARDWARE_VERSION, deviceType); } updateProperties(properties); } @@ -308,11 +310,13 @@ public boolean unregisterDataListener(FreeboxDataListener dataListener) { private boolean fetchConnectionStatus() { try { FreeboxConnectionStatus connectionStatus = apiManager.getConnectionStatus(); - if (StringUtils.isNotEmpty(connectionStatus.getState())) { - updateChannelStringState(LINESTATUS, connectionStatus.getState()); + String state = connectionStatus.getState(); + if (state != null && !state.isEmpty()) { + updateChannelStringState(LINESTATUS, state); } - if (StringUtils.isNotEmpty(connectionStatus.getIpv4())) { - updateChannelStringState(IPV4, connectionStatus.getIpv4()); + String ipv4 = connectionStatus.getIpv4(); + if (ipv4 != null && !ipv4.isEmpty()) { + updateChannelStringState(IPV4, ipv4); } updateChannelDecimalState(RATEUP, connectionStatus.getRateUp()); updateChannelDecimalState(RATEDOWN, connectionStatus.getRateDown()); @@ -328,7 +332,7 @@ private boolean fetchConnectionStatus() { private boolean fetchxDslStatus() { try { String status = apiManager.getxDslStatus(); - if (StringUtils.isNotEmpty(status)) { + if (status != null && !status.isEmpty()) { updateChannelStringState(XDSLSTATUS, status); } return true; @@ -422,18 +426,22 @@ private boolean fetchSystemConfig() { try { FreeboxSystemConfig config = apiManager.getSystemConfig(); Map properties = editProperties(); - if (StringUtils.isNotEmpty(config.getSerial())) { - properties.put(Thing.PROPERTY_SERIAL_NUMBER, config.getSerial()); + String value = config.getSerial(); + if (value != null && !value.isEmpty()) { + properties.put(Thing.PROPERTY_SERIAL_NUMBER, value); } - if (StringUtils.isNotEmpty(config.getBoardName())) { - properties.put(Thing.PROPERTY_HARDWARE_VERSION, config.getBoardName()); + value = config.getBoardName(); + if (value != null && !value.isEmpty()) { + properties.put(Thing.PROPERTY_HARDWARE_VERSION, value); } - if (StringUtils.isNotEmpty(config.getFirmwareVersion())) { - properties.put(Thing.PROPERTY_FIRMWARE_VERSION, config.getFirmwareVersion()); - updateChannelStringState(FWVERSION, config.getFirmwareVersion()); + value = config.getFirmwareVersion(); + if (value != null && !value.isEmpty()) { + properties.put(Thing.PROPERTY_FIRMWARE_VERSION, value); + updateChannelStringState(FWVERSION, value); } - if (StringUtils.isNotEmpty(config.getMac())) { - properties.put(Thing.PROPERTY_MAC_ADDRESS, config.getMac()); + value = config.getMac(); + if (value != null && !value.isEmpty()) { + properties.put(Thing.PROPERTY_MAC_ADDRESS, value); } updateProperties(properties); diff --git a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/handler/FreeboxThingHandler.java b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/handler/FreeboxThingHandler.java index 0246b722cad75..7cca08f818089 100644 --- a/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/handler/FreeboxThingHandler.java +++ b/bundles/org.openhab.binding.freebox/src/main/java/org/openhab/binding/freebox/internal/handler/FreeboxThingHandler.java @@ -418,6 +418,5 @@ public int compare(FreeboxCallEntry call1, FreeboxCallEntry call2) { } return result; } - } } diff --git a/bundles/org.openhab.binding.freebox/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.freebox/src/main/resources/ESH-INF/binding/binding.xml index 499f7acff0dec..af3c469c155f7 100644 --- a/bundles/org.openhab.binding.freebox/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.freebox/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Freebox Binding The Freebox binding requests your Freebox Server for various operational informations. diff --git a/bundles/org.openhab.binding.freebox/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.freebox/src/main/resources/ESH-INF/thing/thing-types.xml index c7729cbe16cd4..796f31b7282f8 100644 --- a/bundles/org.openhab.binding.freebox/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.freebox/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,31 +9,31 @@ Provides various informations regarding the status of the Freebox Server - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -51,11 +51,12 @@ + password Token generated by the Freebox server false - + The refresh interval in seconds which is used to poll given Freebox Server 30 @@ -107,29 +108,29 @@ - + Provides various informations regarding the phone state and the phone calls - - - - - + + + + + - + The refresh interval in seconds which is used to poll given Freebox Server for phone state 2 false - + The refresh interval in seconds which is used to poll given Freebox Server for phone calls 60 @@ -141,14 +142,14 @@ - + Provides network device reachability - + @@ -164,14 +165,14 @@ - + Provides network interface reachability - + @@ -187,15 +188,15 @@ - + Provides media control from one AirPlay device - - + + @@ -225,8 +226,8 @@ The phone state - - + + @@ -234,11 +235,11 @@ The last phone call - - - - - + + + + + @@ -246,10 +247,10 @@ The last accepted phone call - - - - + + + + @@ -257,10 +258,10 @@ The last missed phone call - - - - + + + + @@ -268,10 +269,10 @@ The last outgoing phone call - - - - + + + + @@ -279,14 +280,14 @@ String Version of the Freebox Server Firmware - + Number Time since last reboot of the Freebox Server - + @@ -294,7 +295,7 @@ Has the Freebox server have restarted during the last poll period Alarm - + @@ -309,7 +310,7 @@ Actual measured CPU Marvell temperature of the Freebox Server Temperature - + @@ -317,7 +318,7 @@ Actual measured CPU Broadcom (xDSL) temperature of the Freebox Server Temperature - + @@ -325,14 +326,14 @@ Actual measured switch temperature of the Freebox Server Temperature - + Number Actual measured fan speed (rpm) of the Freebox Server - + @@ -340,7 +341,7 @@ Brightness level of the screen in percent DimmableLight - + @@ -410,56 +411,56 @@ String Status of the xDSL line - + - + Switch Status of the Fiber Optic line - + String Status of network line connexion - + String Public IP Address of the Freebox Server - + Number Current upload rate in byte/s - + Number Current download rate in byte/s - + Number Total uploaded bytes since last connection - + Number Total downloaded bytes since last connection - + @@ -467,7 +468,7 @@ Indicates whether the phone is on hook Switch - + @@ -475,42 +476,42 @@ Is the phone ringing Alarm - + String Called number for outgoing calls. Caller number for incoming calls - + String Called number - + String Caller number - + Number Call duration in seconds - + DateTime Call creation timestamp - + @@ -530,21 +531,21 @@ String Called name for outgoing calls. Caller name for incoming calls - + String Called name - + String Caller name - + @@ -552,7 +553,7 @@ Indicates whether the network device is reachable Switch - + diff --git a/bundles/org.openhab.binding.freebox/src/test/java/org/openhab/binding/freebox/internal/api/FreeboxApiManagerTest.java b/bundles/org.openhab.binding.freebox/src/test/java/org/openhab/binding/freebox/internal/api/FreeboxApiManagerTest.java new file mode 100644 index 0000000000000..e5de49ad2eb03 --- /dev/null +++ b/bundles/org.openhab.binding.freebox/src/test/java/org/openhab/binding/freebox/internal/api/FreeboxApiManagerTest.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.freebox.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author Laurent Garnier - Initial contribution + */ +@NonNullByDefault +public class FreeboxApiManagerTest { + + @Test + public void hmacSha1Test() throws Exception { + String expected = "25dad1bb5604321f12b755cc9d755d1480cf7989"; + String actual = FreeboxApiManager.hmacSha1("Token1234", "Challenge"); + Assert.assertEquals(expected, actual); + } +} diff --git a/bundles/org.openhab.binding.fronius/pom.xml b/bundles/org.openhab.binding.fronius/pom.xml index 45d26276e5dd7..777c3e9c6fcd1 100644 --- a/bundles/org.openhab.binding.fronius/pom.xml +++ b/bundles/org.openhab.binding.fronius/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.fronius diff --git a/bundles/org.openhab.binding.fronius/src/main/feature/feature.xml b/bundles/org.openhab.binding.fronius/src/main/feature/feature.xml index c9781cd4a4632..36830dc5ad572 100644 --- a/bundles/org.openhab.binding.fronius/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.fronius/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.fronius/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.fronius/${project.version} + diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBaseDeviceConfiguration.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBaseDeviceConfiguration.java index a89fc54d6ab0b..4ec788eb5c26c 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBaseDeviceConfiguration.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBaseDeviceConfiguration.java @@ -20,5 +20,4 @@ */ public class FroniusBaseDeviceConfiguration { public Integer deviceId; - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java index 838a0f929263e..67448fed0e4a5 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/FroniusBindingConstants.java @@ -50,5 +50,4 @@ public class FroniusBindingConstants { // List of all Urls public static final String INVERTER_REALTIME_DATA_URL = "http://%IP%/solar_api/v1/GetInverterRealtimeData.cgi?Scope=Device&DeviceId=%DEVICEID%&DataCollection=CommonInverterData"; public static final String POWERFLOW_REALTIME_DATA = "http://%IP%/solar_api/v1/GetPowerFlowRealtimeData.fcgi"; - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/BaseFroniusResponse.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/BaseFroniusResponse.java index 145bd8ba7066c..b9884c5313b98 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/BaseFroniusResponse.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/BaseFroniusResponse.java @@ -33,5 +33,4 @@ public Head getHead() { public void setHead(Head head) { this.head = head; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/DeviceStatus.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/DeviceStatus.java index 0bc296f3e09e6..7c720e7823bf8 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/DeviceStatus.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/DeviceStatus.java @@ -81,5 +81,4 @@ public boolean isStateToReset() { public void setStateToReset(boolean stateToReset) { this.stateToReset = stateToReset; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/Head.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/Head.java index ece9903d6a43a..60abf3ac9c92a 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/Head.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/Head.java @@ -65,5 +65,4 @@ public String getTimestamp() { public void setTimestamp(String timestamp) { this.timestamp = timestamp; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/HeadRequestArguments.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/HeadRequestArguments.java index 9c41e60b42814..9ee0a19819400 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/HeadRequestArguments.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/HeadRequestArguments.java @@ -73,5 +73,4 @@ public String getScope() { public void setScope(String scope) { this.scope = scope; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/HeadStatus.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/HeadStatus.java index 3566c63c709ff..f7f783e6f9793 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/HeadStatus.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/HeadStatus.java @@ -57,5 +57,4 @@ public String getUserMessage() { public void setUserMessage(String userMessage) { this.userMessage = userMessage; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeBody.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeBody.java index f663ac9034282..20db8ec341240 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeBody.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeBody.java @@ -34,5 +34,4 @@ public InverterRealtimeBodyData getData() { public void setData(InverterRealtimeBodyData data) { this.data = data; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeBodyData.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeBodyData.java index 52090e54f045b..120883386d2bc 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeBodyData.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeBodyData.java @@ -125,5 +125,4 @@ public ValueUnit getUdc() { public void setUdc(ValueUnit udc) { this.udc = udc; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeResponse.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeResponse.java index 0ad4aa2bd94b4..9accacb73d710 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeResponse.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/InverterRealtimeResponse.java @@ -35,5 +35,4 @@ public InverterRealtimeBody getBody() { public void setBody(InverterRealtimeBody body) { this.body = body; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeBodyData.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeBodyData.java index df6557c32d84d..da22f8c5d1456 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeBodyData.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeBodyData.java @@ -52,5 +52,4 @@ public PowerFlowRealtimeSite getSite() { public void setSite(PowerFlowRealtimeSite site) { this.site = site; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeInverter.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeInverter.java index f518b8610567c..6dd590ebbfa70 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeInverter.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeInverter.java @@ -72,5 +72,4 @@ public double geteTotal() { public void seteTotal(double eTotal) { this.eTotal = eTotal; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeResponse.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeResponse.java index d55dda5eeaa89..78c527f74a709 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeResponse.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeResponse.java @@ -34,5 +34,4 @@ public PowerFlowRealtimeBody getBody() { public void setBody(PowerFlowRealtimeBody body) { this.body = body; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeSite.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeSite.java index 3d99d700cc51d..23508b118093c 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeSite.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/PowerFlowRealtimeSite.java @@ -135,5 +135,4 @@ public String getMeterLocation() { public void setMeterLocation(String meterLocation) { this.meterLocation = meterLocation; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/ValueUnit.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/ValueUnit.java index 7f0de200c9dcd..a1ef83f879473 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/ValueUnit.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/api/ValueUnit.java @@ -47,5 +47,4 @@ public void setUnit(String unit) { this.setValue(KilowattConverter.convertTo(this.getValue(), this.getUnit(), unit)); this.unit = unit; } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java index 5e3229b3ee24c..0ca41e2d14d1d 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBaseThingHandler.java @@ -149,5 +149,4 @@ protected void updateChannel(String channelId) { * @param bridgeConfiguration the connected bridge configuration */ public abstract void refresh(FroniusBridgeConfiguration bridgeConfiguration); - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBridgeHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBridgeHandler.java index aa3733107c8b7..185f237d93312 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBridgeHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusBridgeHandler.java @@ -119,5 +119,4 @@ private void startAutomaticRefresh(FroniusBridgeConfiguration config) { refreshJob = scheduler.scheduleWithFixedDelay(runnable, 0, delay, TimeUnit.SECONDS); } } - } diff --git a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java index 7e16223e329c2..434c9ed441045 100644 --- a/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java +++ b/bundles/org.openhab.binding.fronius/src/main/java/org/openhab/binding/fronius/internal/handler/FroniusSymoInverterHandler.java @@ -1,220 +1,219 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.fronius.internal.handler; - -import java.io.IOException; - -import org.apache.commons.lang.StringUtils; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.io.net.http.HttpUtil; -import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration; -import org.openhab.binding.fronius.internal.FroniusBindingConstants; -import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; -import org.openhab.binding.fronius.internal.api.BaseFroniusResponse; -import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse; -import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse; -import org.openhab.binding.fronius.internal.api.ValueUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; - -/** - * The {@link FroniusSymoInverterHandler} is responsible for updating the data, which are - * sent to one of the channels. - * - * @author Thomas Rokohl - Initial contribution - * @author Peter Schraffl - Added device status and error status channels - */ -public class FroniusSymoInverterHandler extends FroniusBaseThingHandler { - - private static final int API_TIMEOUT = 5000; - private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class); - private InverterRealtimeResponse inverterRealtimeResponse; - private PowerFlowRealtimeResponse powerFlowResponse; - private FroniusBaseDeviceConfiguration config; - private final Gson gson; - - public FroniusSymoInverterHandler(Thing thing) { - super(thing); - gson = new Gson(); - } - - @Override - protected String getDescription() { - return "Fronius Symo Inverter"; - } - - @Override - public void refresh(FroniusBridgeConfiguration bridgeConfiguration) { - updateData(bridgeConfiguration, config); - updateChannels(); - } - - @Override - public void initialize() { - config = getConfigAs(FroniusBaseDeviceConfiguration.class); - super.initialize(); - } - - /** - * Update the channel from the last data retrieved - * - * @param channelId the id identifying the channel to be updated - * @return the last retrieved data - */ - @Override - protected Object getValue(String channelId) { - String[] fields = StringUtils.split(channelId, "#"); - - String fieldName = fields[0]; - - if (inverterRealtimeResponse == null) { - return null; - } - switch (fieldName) { - case FroniusBindingConstants.InverterDataChannelDayEnergy: - ValueUnit day = inverterRealtimeResponse.getBody().getData().getDayEnergy(); - if (day != null) { - day.setUnit("kWh"); - } - return day; - case FroniusBindingConstants.InverterDataChannelPac: - return inverterRealtimeResponse.getBody().getData().getPac(); - case FroniusBindingConstants.InverterDataChannelTotal: - ValueUnit total = inverterRealtimeResponse.getBody().getData().getTotalEnergy(); - if (total != null) { - total.setUnit("MWh"); - } - return total; - case FroniusBindingConstants.InverterDataChannelYear: - ValueUnit year = inverterRealtimeResponse.getBody().getData().getYearEnergy(); - if (year != null) { - year.setUnit("MWh"); - } - return year; - case FroniusBindingConstants.InverterDataChannelFac: - return inverterRealtimeResponse.getBody().getData().getFac(); - case FroniusBindingConstants.InverterDataChannelIac: - return inverterRealtimeResponse.getBody().getData().getIac(); - case FroniusBindingConstants.InverterDataChannelIdc: - return inverterRealtimeResponse.getBody().getData().getIdc(); - case FroniusBindingConstants.InverterDataChannelUac: - return inverterRealtimeResponse.getBody().getData().getUac(); - case FroniusBindingConstants.InverterDataChannelUdc: - return inverterRealtimeResponse.getBody().getData().getUdc(); - case FroniusBindingConstants.InverterDataChannelDeviceStatusErrorCode: - return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getErrorCode(); - case FroniusBindingConstants.InverterDataChannelDeviceStatusStatusCode: - return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode(); - } - if (powerFlowResponse == null) { - return null; - } - switch (fieldName) { - case FroniusBindingConstants.PowerFlowpGrid: - return powerFlowResponse.getBody().getData().getSite().getPgrid(); - case FroniusBindingConstants.PowerFlowpLoad: - return powerFlowResponse.getBody().getData().getSite().getPload(); - case FroniusBindingConstants.PowerFlowpAkku: - return powerFlowResponse.getBody().getData().getSite().getPakku(); - } - - return null; - } - - /** - * Get new data - */ - private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) { - inverterRealtimeResponse = getRealtimeData(bridgeConfiguration.hostname, config.deviceId); - powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname); - } - - /** - * - * @param type response class type - * @param url to request - * @return the object representation of the json response - */ - private T collectDataFormUrl(Class type, String url) { - T result = null; - boolean resultOk = false; - String errorMsg = null; - - try { - logger.debug("URL = {}", url); - String response = HttpUtil.executeUrl("GET", url, API_TIMEOUT); - - if (response != null) { - logger.debug("aqiResponse = {}", response); - result = gson.fromJson(response, type); - } - - if (result == null) { - errorMsg = "no data returned"; - } else { - if (result.getHead().getStatus().getCode() == 0) { - resultOk = true; - } else { - errorMsg = result.getHead().getStatus().getReason(); - } - } - if (!resultOk) { - logger.debug("Error in fronius response: {}", errorMsg); - } - } catch (JsonSyntaxException e) { - errorMsg = "Configuration is incorrect"; - logger.debug("Error running fronius request: {}", errorMsg); - } catch (IOException | IllegalStateException e) { - logger.debug("Error running fronius request: {}", e.getMessage()); - } - - // Update the thing status - if (resultOk) { - updateStatus(ThingStatus.ONLINE); - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errorMsg); - } - return resultOk ? result : null; - } - - /** - * Make the PowerFlowRealtimeDataRequest - * - * @param ip address of the device - * @return {PowerFlowRealtimeResponse} the object representation of the json response - */ - private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) { - String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%", StringUtils.trimToEmpty(ip)); - return collectDataFormUrl(PowerFlowRealtimeResponse.class, location); - } - - /** - * Make the InverterRealtimeDataRequest - * - * @param ip address of the device - * @param deviceId of the device - * @return {InverterRealtimeResponse} the object representation of the json response - */ - private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) { - String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%", - StringUtils.trimToEmpty(ip)); - location = location.replace("%DEVICEID%", Integer.toString(deviceId)); - return collectDataFormUrl(InverterRealtimeResponse.class, location); - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.fronius.internal.handler; + +import java.io.IOException; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.io.net.http.HttpUtil; +import org.openhab.binding.fronius.internal.FroniusBaseDeviceConfiguration; +import org.openhab.binding.fronius.internal.FroniusBindingConstants; +import org.openhab.binding.fronius.internal.FroniusBridgeConfiguration; +import org.openhab.binding.fronius.internal.api.BaseFroniusResponse; +import org.openhab.binding.fronius.internal.api.InverterRealtimeResponse; +import org.openhab.binding.fronius.internal.api.PowerFlowRealtimeResponse; +import org.openhab.binding.fronius.internal.api.ValueUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +/** + * The {@link FroniusSymoInverterHandler} is responsible for updating the data, which are + * sent to one of the channels. + * + * @author Thomas Rokohl - Initial contribution + * @author Peter Schraffl - Added device status and error status channels + */ +public class FroniusSymoInverterHandler extends FroniusBaseThingHandler { + + private static final int API_TIMEOUT = 5000; + private final Logger logger = LoggerFactory.getLogger(FroniusSymoInverterHandler.class); + private InverterRealtimeResponse inverterRealtimeResponse; + private PowerFlowRealtimeResponse powerFlowResponse; + private FroniusBaseDeviceConfiguration config; + private final Gson gson; + + public FroniusSymoInverterHandler(Thing thing) { + super(thing); + gson = new Gson(); + } + + @Override + protected String getDescription() { + return "Fronius Symo Inverter"; + } + + @Override + public void refresh(FroniusBridgeConfiguration bridgeConfiguration) { + updateData(bridgeConfiguration, config); + updateChannels(); + } + + @Override + public void initialize() { + config = getConfigAs(FroniusBaseDeviceConfiguration.class); + super.initialize(); + } + + /** + * Update the channel from the last data retrieved + * + * @param channelId the id identifying the channel to be updated + * @return the last retrieved data + */ + @Override + protected Object getValue(String channelId) { + String[] fields = StringUtils.split(channelId, "#"); + + String fieldName = fields[0]; + + if (inverterRealtimeResponse == null) { + return null; + } + switch (fieldName) { + case FroniusBindingConstants.InverterDataChannelDayEnergy: + ValueUnit day = inverterRealtimeResponse.getBody().getData().getDayEnergy(); + if (day != null) { + day.setUnit("kWh"); + } + return day; + case FroniusBindingConstants.InverterDataChannelPac: + return inverterRealtimeResponse.getBody().getData().getPac(); + case FroniusBindingConstants.InverterDataChannelTotal: + ValueUnit total = inverterRealtimeResponse.getBody().getData().getTotalEnergy(); + if (total != null) { + total.setUnit("MWh"); + } + return total; + case FroniusBindingConstants.InverterDataChannelYear: + ValueUnit year = inverterRealtimeResponse.getBody().getData().getYearEnergy(); + if (year != null) { + year.setUnit("MWh"); + } + return year; + case FroniusBindingConstants.InverterDataChannelFac: + return inverterRealtimeResponse.getBody().getData().getFac(); + case FroniusBindingConstants.InverterDataChannelIac: + return inverterRealtimeResponse.getBody().getData().getIac(); + case FroniusBindingConstants.InverterDataChannelIdc: + return inverterRealtimeResponse.getBody().getData().getIdc(); + case FroniusBindingConstants.InverterDataChannelUac: + return inverterRealtimeResponse.getBody().getData().getUac(); + case FroniusBindingConstants.InverterDataChannelUdc: + return inverterRealtimeResponse.getBody().getData().getUdc(); + case FroniusBindingConstants.InverterDataChannelDeviceStatusErrorCode: + return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getErrorCode(); + case FroniusBindingConstants.InverterDataChannelDeviceStatusStatusCode: + return inverterRealtimeResponse.getBody().getData().getDeviceStatus().getStatusCode(); + } + if (powerFlowResponse == null) { + return null; + } + switch (fieldName) { + case FroniusBindingConstants.PowerFlowpGrid: + return powerFlowResponse.getBody().getData().getSite().getPgrid(); + case FroniusBindingConstants.PowerFlowpLoad: + return powerFlowResponse.getBody().getData().getSite().getPload(); + case FroniusBindingConstants.PowerFlowpAkku: + return powerFlowResponse.getBody().getData().getSite().getPakku(); + } + + return null; + } + + /** + * Get new data + */ + private void updateData(FroniusBridgeConfiguration bridgeConfiguration, FroniusBaseDeviceConfiguration config) { + inverterRealtimeResponse = getRealtimeData(bridgeConfiguration.hostname, config.deviceId); + powerFlowResponse = getPowerFlowRealtime(bridgeConfiguration.hostname); + } + + /** + * + * @param type response class type + * @param url to request + * @return the object representation of the json response + */ + private T collectDataFormUrl(Class type, String url) { + T result = null; + boolean resultOk = false; + String errorMsg = null; + + try { + logger.debug("URL = {}", url); + String response = HttpUtil.executeUrl("GET", url, API_TIMEOUT); + + if (response != null) { + logger.debug("aqiResponse = {}", response); + result = gson.fromJson(response, type); + } + + if (result == null) { + errorMsg = "no data returned"; + } else { + if (result.getHead().getStatus().getCode() == 0) { + resultOk = true; + } else { + errorMsg = result.getHead().getStatus().getReason(); + } + } + if (!resultOk) { + logger.debug("Error in fronius response: {}", errorMsg); + } + } catch (JsonSyntaxException e) { + errorMsg = "Configuration is incorrect"; + logger.debug("Error running fronius request: {}", errorMsg); + } catch (IOException | IllegalStateException e) { + logger.debug("Error running fronius request: {}", e.getMessage()); + } + + // Update the thing status + if (resultOk) { + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, errorMsg); + } + return resultOk ? result : null; + } + + /** + * Make the PowerFlowRealtimeDataRequest + * + * @param ip address of the device + * @return {PowerFlowRealtimeResponse} the object representation of the json response + */ + private PowerFlowRealtimeResponse getPowerFlowRealtime(String ip) { + String location = FroniusBindingConstants.POWERFLOW_REALTIME_DATA.replace("%IP%", StringUtils.trimToEmpty(ip)); + return collectDataFormUrl(PowerFlowRealtimeResponse.class, location); + } + + /** + * Make the InverterRealtimeDataRequest + * + * @param ip address of the device + * @param deviceId of the device + * @return {InverterRealtimeResponse} the object representation of the json response + */ + private InverterRealtimeResponse getRealtimeData(String ip, int deviceId) { + String location = FroniusBindingConstants.INVERTER_REALTIME_DATA_URL.replace("%IP%", + StringUtils.trimToEmpty(ip)); + location = location.replace("%DEVICEID%", Integer.toString(deviceId)); + return collectDataFormUrl(InverterRealtimeResponse.class, location); + } +} diff --git a/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/binding/binding.xml index 62e8da4ebbdea..719d631847204 100644 --- a/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Fronius Binding Binding for Fronius inverters. diff --git a/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/thing/bridge.xml index 48c8eead643ee..c07d802cb7559 100644 --- a/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/thing/thing-types.xml index de95c3158c0a0..b110b20f71319 100644 --- a/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.fronius/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,31 +1,32 @@ - - + Fronius Symo power inverter - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.fsinternetradio/pom.xml b/bundles/org.openhab.binding.fsinternetradio/pom.xml index 1c7a8c76fddaf..da8a3f4d2c41c 100644 --- a/bundles/org.openhab.binding.fsinternetradio/pom.xml +++ b/bundles/org.openhab.binding.fsinternetradio/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.fsinternetradio diff --git a/bundles/org.openhab.binding.fsinternetradio/src/main/feature/feature.xml b/bundles/org.openhab.binding.fsinternetradio/src/main/feature/feature.xml index 63adff40a183b..002229147e784 100644 --- a/bundles/org.openhab.binding.fsinternetradio/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.fsinternetradio/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.fsinternetradio/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.fsinternetradio/${project.version} + diff --git a/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/handler/FSInternetRadioHandler.java b/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/handler/FSInternetRadioHandler.java index 225f8deafa1ef..111ccfd659fff 100644 --- a/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/handler/FSInternetRadioHandler.java +++ b/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/handler/FSInternetRadioHandler.java @@ -164,7 +164,6 @@ public void run() { } } }); - } @Override diff --git a/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/radio/FrontierSiliconRadio.java b/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/radio/FrontierSiliconRadio.java index 788990a9981bc..dd945f044b1dd 100644 --- a/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/radio/FrontierSiliconRadio.java +++ b/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/radio/FrontierSiliconRadio.java @@ -238,5 +238,4 @@ public void setMuted(boolean muted) throws IOException { final String params = "value=" + (muted ? "1" : "0"); conn.doRequest(REQUEST_SET_MUTE, params); } - } diff --git a/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/radio/FrontierSiliconRadioConnection.java b/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/radio/FrontierSiliconRadioConnection.java index 0828aa023b2bf..985b2f93343bb 100644 --- a/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/radio/FrontierSiliconRadioConnection.java +++ b/bundles/org.openhab.binding.fsinternetradio/src/main/java/org/openhab/binding/fsinternetradio/internal/radio/FrontierSiliconRadioConnection.java @@ -202,5 +202,4 @@ public FrontierSiliconRadioApiResult doRequest(String requestString, String para isLoggedIn = false; // 3 tries failed. log in again next time, maybe our session went invalid (radio restarted?) return null; } - } diff --git a/bundles/org.openhab.binding.fsinternetradio/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.fsinternetradio/src/main/resources/ESH-INF/thing/thing-types.xml index 239a1bfb10144..248851517ac6b 100644 --- a/bundles/org.openhab.binding.fsinternetradio/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.fsinternetradio/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ An internet radio device based on the Frontier Silicon chipset. - - - - - - - - + + + + + + + + @@ -63,14 +64,14 @@ Volume (min=0, max=32). SoundVolume - + Dimmer Volume (in percent). SoundVolume - + Switch @@ -81,19 +82,19 @@ String The name of the current radio station or track. - + String Additional information e.g. of the current radio station. - + Number The radio mode, e.g. FM radio, internet radio, AUX, etc. - + diff --git a/bundles/org.openhab.binding.fsinternetradio/src/test/java/org/openhab/binding/fsinternetradio/test/FSInternetRadioHandlerJavaTest.java b/bundles/org.openhab.binding.fsinternetradio/src/test/java/org/openhab/binding/fsinternetradio/test/FSInternetRadioHandlerJavaTest.java index fb793c68b3de2..eee16674717f9 100644 --- a/bundles/org.openhab.binding.fsinternetradio/src/test/java/org/openhab/binding/fsinternetradio/test/FSInternetRadioHandlerJavaTest.java +++ b/bundles/org.openhab.binding.fsinternetradio/src/test/java/org/openhab/binding/fsinternetradio/test/FSInternetRadioHandlerJavaTest.java @@ -892,6 +892,5 @@ private void verifyCommunicationError(String exceptionMessage) { assertThat(status.getStatus(), is(ThingStatus.OFFLINE)); assertThat(status.getStatusDetail(), is(ThingStatusDetail.COMMUNICATION_ERROR)); assertThat(status.getDescription().contains(exceptionMessage), is(true)); - } } diff --git a/bundles/org.openhab.binding.ftpupload/pom.xml b/bundles/org.openhab.binding.ftpupload/pom.xml index 26ef395b9a6db..abcc6576730e8 100644 --- a/bundles/org.openhab.binding.ftpupload/pom.xml +++ b/bundles/org.openhab.binding.ftpupload/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.ftpupload diff --git a/bundles/org.openhab.binding.ftpupload/src/main/feature/feature.xml b/bundles/org.openhab.binding.ftpupload/src/main/feature/feature.xml index a15509a16a36e..bf944a4a12169 100644 --- a/bundles/org.openhab.binding.ftpupload/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.ftpupload/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.ftpupload/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.ftpupload/${project.version} + diff --git a/bundles/org.openhab.binding.ftpupload/src/main/java/org/openhab/binding/ftpupload/internal/ftp/FtpServerEventListener.java b/bundles/org.openhab.binding.ftpupload/src/main/java/org/openhab/binding/ftpupload/internal/ftp/FtpServerEventListener.java index 1682ea8a8c47f..6abd8d9ca32be 100644 --- a/bundles/org.openhab.binding.ftpupload/src/main/java/org/openhab/binding/ftpupload/internal/ftp/FtpServerEventListener.java +++ b/bundles/org.openhab.binding.ftpupload/src/main/java/org/openhab/binding/ftpupload/internal/ftp/FtpServerEventListener.java @@ -29,5 +29,4 @@ public interface FtpServerEventListener { * @param data Received raw data. */ void fileReceived(@NonNull String userName, @NonNull String filename, byte[] data); - } diff --git a/bundles/org.openhab.binding.ftpupload/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.ftpupload/src/main/resources/ESH-INF/binding/binding.xml index 628757333b6ae..364549c36d5fb 100644 --- a/bundles/org.openhab.binding.ftpupload/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.ftpupload/src/main/resources/ESH-INF/binding/binding.xml @@ -15,7 +15,8 @@ - The number of seconds before an inactive client is disconnected. If this value is set to 0, the idle time is disabled. + The number of seconds before an inactive client is disconnected. If this value is set to 0, the idle + time is disabled. 60 diff --git a/bundles/org.openhab.binding.ftpupload/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.ftpupload/src/main/resources/ESH-INF/thing/thing-types.xml index fec284b614b69..5c6599446fefc 100644 --- a/bundles/org.openhab.binding.ftpupload/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.ftpupload/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,8 +9,8 @@ Receive image files via FTP. - - + + diff --git a/bundles/org.openhab.binding.gardena/pom.xml b/bundles/org.openhab.binding.gardena/pom.xml index 994a9723e7fb9..30a1abc9d6c3a 100644 --- a/bundles/org.openhab.binding.gardena/pom.xml +++ b/bundles/org.openhab.binding.gardena/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.gardena diff --git a/bundles/org.openhab.binding.gardena/src/main/feature/feature.xml b/bundles/org.openhab.binding.gardena/src/main/feature/feature.xml index 0f2f9bf9d3b24..c6c5e18be7177 100644 --- a/bundles/org.openhab.binding.gardena/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.gardena/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.gardena/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.gardena/${project.version} + diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/GardenaSmartEventListener.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/GardenaSmartEventListener.java index 65d89daf8cebc..224502c0c9eba 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/GardenaSmartEventListener.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/GardenaSmartEventListener.java @@ -45,5 +45,4 @@ public interface GardenaSmartEventListener { * Called when the connection is resumed to Gardena Smart Home. */ public void onConnectionResumed(); - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfig.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfig.java index ba6697cedb795..6a8e3795ebdf8 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfig.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfig.java @@ -129,5 +129,4 @@ public String toString() { .append("sessionTimeout", sessionTimeout).append("connectionTimeout", connectionTimeout) .append("refresh", refresh).toString(); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfigDataWrapper.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfigDataWrapper.java index 513f97741c815..2f3c8fbf34cd0 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfigDataWrapper.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfigDataWrapper.java @@ -33,5 +33,4 @@ public GardenaConfigDataWrapper() { public GardenaConfigDataWrapper(GardenaConfig config) { this.config = config; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfigWrapper.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfigWrapper.java index cdede76ef35ad..be0ded0fb8fc9 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfigWrapper.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/config/GardenaConfigWrapper.java @@ -29,5 +29,4 @@ public GardenaConfigWrapper() { public GardenaConfigWrapper(GardenaConfig config) { this.dataWrapper = new GardenaConfigDataWrapper(config); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/discovery/GardenaDeviceDiscoveryService.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/discovery/GardenaDeviceDiscoveryService.java index a01dd62a91ec0..eec484f991593 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/discovery/GardenaDeviceDiscoveryService.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/discovery/GardenaDeviceDiscoveryService.java @@ -173,5 +173,4 @@ public void deviceRemoved(Device device) { ThingUID thingUID = UidUtils.generateThingUID(device, accountHandler.getThing()); thingRemoved(thingUID); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/exception/GardenaDeviceNotFoundException.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/exception/GardenaDeviceNotFoundException.java index 2f8f269cf3951..1cf9ec03d9f61 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/exception/GardenaDeviceNotFoundException.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/exception/GardenaDeviceNotFoundException.java @@ -25,5 +25,4 @@ public class GardenaDeviceNotFoundException extends GardenaException { public GardenaDeviceNotFoundException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/AccountHandlerNotAvailableException.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/AccountHandlerNotAvailableException.java index 4a6ac681a7705..fc7d183b9cf89 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/AccountHandlerNotAvailableException.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/AccountHandlerNotAvailableException.java @@ -24,5 +24,4 @@ public class AccountHandlerNotAvailableException extends Exception { public AccountHandlerNotAvailableException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/GardenaAccountHandler.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/GardenaAccountHandler.java index 9b0d73e151da3..ff0a42bdc79e1 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/GardenaAccountHandler.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/GardenaAccountHandler.java @@ -142,7 +142,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void onDeviceUpdated(Device device) { for (ThingUID thingUID : UidUtils.getThingUIDs(device, getThing())) { - Thing gardenaThing = getThingByUID(thingUID); + Thing gardenaThing = getThing().getThing(thingUID); try { GardenaThingHandler gardenaThingHandler = (GardenaThingHandler) gardenaThing.getHandler(); gardenaThingHandler.updateProperties(device); @@ -185,5 +185,4 @@ public void onConnectionLost() { public void onConnectionResumed() { updateStatus(ThingStatus.ONLINE); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/GardenaThingHandler.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/GardenaThingHandler.java index b9418c3cbbb59..1479431f8fce9 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/GardenaThingHandler.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/handler/GardenaThingHandler.java @@ -367,5 +367,4 @@ private GardenaSmart getGardenaSmart() throws AccountHandlerNotAvailableExceptio return ((GardenaAccountHandler) getBridge().getHandler()).getGardenaSmart(); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Device.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Device.java index 7da08bc8135a3..7a39a93ed3e5f 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Device.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Device.java @@ -144,5 +144,4 @@ public boolean equals(Object obj) { Device comp = (Device) obj; return new EqualsBuilder().append(comp.getId(), id).isEquals(); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Devices.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Devices.java index 7cc7e076cf369..332cacc5d5726 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Devices.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Devices.java @@ -30,5 +30,4 @@ public class Devices { public List getDevices() { return devices; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Error.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Error.java index 515ff56833a99..c8f5e1c970fa6 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Error.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Error.java @@ -60,5 +60,4 @@ public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("id", id).append("status", status) .append("title", title).append("detail", detail).toString(); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Errors.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Errors.java index d7b1c8276ab1e..13fd38ca2c6e9 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Errors.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Errors.java @@ -42,5 +42,4 @@ public String toString() { } return tsb.toString(); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Location.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Location.java index 5b22575fe08d2..404cf21168441 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Location.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Location.java @@ -66,5 +66,4 @@ public boolean equals(Object obj) { Location comp = (Location) obj; return new EqualsBuilder().append(comp.getId(), id).isEquals(); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Locations.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Locations.java index 445c9359267d4..41c023f8c1b5b 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Locations.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Locations.java @@ -30,5 +30,4 @@ public class Locations { public List getLocations() { return locations; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Property.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Property.java index 24f78d20a3896..98fd07a0f7d8a 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Property.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Property.java @@ -114,5 +114,4 @@ public Ability getAbility() { public void setAbility(Ability ability) { this.ability = ability; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/PropertyValue.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/PropertyValue.java index d32007cdbc83e..12af1aa3284d7 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/PropertyValue.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/PropertyValue.java @@ -40,5 +40,4 @@ public String getValue() { public void setValue(String value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/ScheduledEvent.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/ScheduledEvent.java index 01badf5d3c387..d7e20e251cd69 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/ScheduledEvent.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/ScheduledEvent.java @@ -72,5 +72,4 @@ public String getWeekday() { public Recurrence getRecurrence() { return recurrence; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Session.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Session.java index 5f4e41017118b..f860f1554e4db 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Session.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/Session.java @@ -51,5 +51,4 @@ public long getCreated() { public SessionAttributes getSessionAttributes() { return sessionAttributes; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/SessionWrapper.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/SessionWrapper.java index 31ea53c06cbec..f4f74ac873615 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/SessionWrapper.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/SessionWrapper.java @@ -43,5 +43,4 @@ public Session getSession() { public void setSession(Session session) { this.session = session; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/Command.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/Command.java index 14ea5cfb8f1a8..26e46adbdcc61 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/Command.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/Command.java @@ -91,5 +91,4 @@ public void setManualOverride(String manualOverride) { this.manualOverride = manualOverride; } } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/MowerParkUntilFurtherNoticeCommand.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/MowerParkUntilFurtherNoticeCommand.java index c770aa54f2485..338e000c0f73b 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/MowerParkUntilFurtherNoticeCommand.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/MowerParkUntilFurtherNoticeCommand.java @@ -23,5 +23,4 @@ public class MowerParkUntilFurtherNoticeCommand extends Command { public MowerParkUntilFurtherNoticeCommand() { super(COMMAND); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/MowerParkUntilNextTimerCommand.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/MowerParkUntilNextTimerCommand.java index 2126f9e2b9e5a..03e768f1978eb 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/MowerParkUntilNextTimerCommand.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/MowerParkUntilNextTimerCommand.java @@ -24,5 +24,4 @@ public class MowerParkUntilNextTimerCommand extends Command { public MowerParkUntilNextTimerCommand() { super(COMMAND); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/SettingCommand.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/SettingCommand.java index 12746eafc2ea1..5602d67e8e485 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/SettingCommand.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/SettingCommand.java @@ -55,5 +55,4 @@ public String getDeviceId() { public void setDeviceId(String deviceId) { this.deviceId = deviceId; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/SettingCommandWrapper.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/SettingCommandWrapper.java index 89ac8cec41a21..ac815e1c996ea 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/SettingCommandWrapper.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/command/SettingCommandWrapper.java @@ -33,5 +33,4 @@ public SettingCommandWrapper(SettingCommand command) { public SettingCommand getCommand() { return command; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/deser/PropertyValueDeserializer.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/deser/PropertyValueDeserializer.java index 4c33f24b7f6d0..8c61bdcff89f7 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/deser/PropertyValueDeserializer.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/deser/PropertyValueDeserializer.java @@ -67,5 +67,4 @@ public PropertyValue deserialize(JsonElement element, Type type, JsonDeserializa return new PropertyValue(element.getAsString()); } } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/property/StringProperty.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/property/StringProperty.java index 73300c6fd2024..9f2986566e656 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/property/StringProperty.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/model/property/StringProperty.java @@ -32,5 +32,4 @@ public StringProperty(String name, String value) { public String getValue() { return value; } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/util/DateUtils.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/util/DateUtils.java index 07329adb3048b..5d99e43ee2a69 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/util/DateUtils.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/util/DateUtils.java @@ -58,7 +58,6 @@ public static Date parseToDate(String text) { } else { return null; } - } /** @@ -72,6 +71,5 @@ public static Calendar parseToCalendar(String text) { return cal; } return null; - } } diff --git a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/util/UidUtils.java b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/util/UidUtils.java index 5c3469f87c857..e09a0c7448523 100644 --- a/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/util/UidUtils.java +++ b/bundles/org.openhab.binding.gardena/src/main/java/org/openhab/binding/gardena/internal/util/UidUtils.java @@ -67,5 +67,4 @@ public static String getGardenaDeviceId(Thing thing) { return thing.getUID().getId(); } - } diff --git a/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/binding/binding.xml index eac09f1efff56..60fe257dcc494 100644 --- a/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Gardena Smart Home Binding This is the binding for Gardena Smart Home. diff --git a/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/thing/bridge.xml index d4746f5961cc6..b8a91ead4ca31 100644 --- a/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/thing/thing-types.xml index a7d6d31d1fdb6..bd99aa0f2aea2 100644 --- a/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.gardena/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,28 +7,28 @@ - + A Gardena Smart Sileno mower - - - - - - + + + + + + - - - - - - + + + + + + @@ -36,7 +36,7 @@ Information about the device - + @@ -44,8 +44,8 @@ Information about the rechargeable battery - - + + @@ -53,8 +53,8 @@ Information about the radio link - - + + @@ -62,17 +62,17 @@ Information about the robotic mower - - - - - - - - - - - + + + + + + + + + + + @@ -80,7 +80,7 @@ Number Mowing time in minutes - + @@ -111,28 +111,28 @@ DateTime Last time the device was online - + Switch Battery Charging - + Number Radio Link Quality - + String The mower is controlled manually - + @@ -269,30 +269,30 @@ DateTime Timestamp of the next start - + DateTime Override End Time - + Number Temperature - + Information about the firmware - - - + + + @@ -300,31 +300,31 @@ String The firmware status - + Number Firmware upload in progress - + String Available firmware version - + Statistics about the robotic mower - - - - + + + + @@ -332,54 +332,54 @@ Number The cutting time - + Number The charging cycles - + Number The number of collisions - + Number Running time - + - + Represents a Gardena Smart Watering Computer - - - - - + + + + + - - - - - - + + + + + + @@ -387,8 +387,8 @@ Information about the battery - - + + @@ -396,9 +396,9 @@ Information about the watering outlet - - - + + + @@ -409,7 +409,7 @@ - + @@ -451,7 +451,7 @@ Number The time the valve is open when you press the button on the device - + @@ -470,29 +470,29 @@ - + Represents a Gardena Smart Sensor - - - - - - - + + + + + + + - - - - - - + + + + + + @@ -510,7 +510,7 @@ The humidity - + @@ -518,7 +518,7 @@ The brightness - + @@ -526,46 +526,46 @@ Number The humidity - + Number The brightness - + - + Represents a Gardena Smart Pressure Pump - - - - - - - - - + + + + + + + + + - - - - - - + + + + + + @@ -602,10 +602,10 @@ The outlet temperature - - - - + + + + @@ -613,30 +613,30 @@ Number The minimum outlet temperature - + Number The maximum outlet temperature - + The pump - - - - - - - - - - + + + + + + + + + + @@ -644,42 +644,42 @@ Number The error counter - + Number The error counter one - + Number The error counter two - + Number The error counter three - + Number The error counter Four - + Number The operating days - + @@ -698,7 +698,7 @@ Switch Pump - + @@ -732,8 +732,8 @@ The outlet pressure - - + + @@ -741,24 +741,24 @@ Number The outlet pressure - + Number The maximum outlet pressure - + The flow - - - - + + + + @@ -766,21 +766,21 @@ Number The flow rate - + Number The flow since last reset - + Number The total flow - + @@ -800,8 +800,8 @@ Manual Watering - - + + @@ -834,16 +834,16 @@ Number The last manual override timer - + Manual Watering - - - + + + @@ -851,14 +851,14 @@ DateTime The scheduled watering end - + DateTime The scheduled watering next start - + @@ -878,26 +878,26 @@ - + A Gardena Smart Power Plug - - - - + + + + - - - - - - + + + + + + @@ -905,8 +905,8 @@ Power - - + + @@ -951,30 +951,30 @@ - + A Gardena Smart Irrigation Control - - + + - - - + + + - + - - - - - - + + + + + + @@ -1037,9 +1037,9 @@ The irrigation control - - - + + + The error for valve 0 @@ -1075,14 +1075,14 @@ String The connected valves - + String The valves master config - + @@ -1103,7 +1103,7 @@ String - + @@ -1164,7 +1164,7 @@ DateTime - + diff --git a/bundles/org.openhab.binding.globalcache/pom.xml b/bundles/org.openhab.binding.globalcache/pom.xml index 71e114ff8dfe7..df8743760466e 100644 --- a/bundles/org.openhab.binding.globalcache/pom.xml +++ b/bundles/org.openhab.binding.globalcache/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.globalcache diff --git a/bundles/org.openhab.binding.globalcache/src/main/feature/feature.xml b/bundles/org.openhab.binding.globalcache/src/main/feature/feature.xml index 02ab6a22b4ffd..e1dffc118d07d 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - file:${basedirRoot}/bundles/org.openhab.transform.map/target/feature/feature.xml + file:${basedirRoot}/bundles/org.openhab.transform.map/target/feature/feature.xml - - openhab-runtime-base - openhab-transformation-map - mvn:org.openhab.addons.bundles/org.openhab.binding.globalcache/${project.version} - + + openhab-runtime-base + openhab-transformation-map + mvn:org.openhab.addons.bundles/org.openhab.binding.globalcache/${project.version} + diff --git a/bundles/org.openhab.binding.globalcache/src/main/java/org/openhab/binding/globalcache/internal/GlobalCacheHandlerFactory.java b/bundles/org.openhab.binding.globalcache/src/main/java/org/openhab/binding/globalcache/internal/GlobalCacheHandlerFactory.java index 71512b198790f..d450f6a63f6f7 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/java/org/openhab/binding/globalcache/internal/GlobalCacheHandlerFactory.java +++ b/bundles/org.openhab.binding.globalcache/src/main/java/org/openhab/binding/globalcache/internal/GlobalCacheHandlerFactory.java @@ -14,6 +14,8 @@ import static org.openhab.binding.globalcache.internal.GlobalCacheBindingConstants.SUPPORTED_THING_TYPES_UIDS; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.net.NetworkAddressService; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; @@ -21,6 +23,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.openhab.binding.globalcache.internal.handler.GlobalCacheHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -29,9 +32,16 @@ * * @author Mark Hilbush - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.globalcache") public class GlobalCacheHandlerFactory extends BaseThingHandlerFactory { - private NetworkAddressService networkAddressService; + + private final NetworkAddressService networkAddressService; + + @Activate + public GlobalCacheHandlerFactory(@Reference NetworkAddressService networkAddressService) { + this.networkAddressService = networkAddressService; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -39,22 +49,12 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { return new GlobalCacheHandler(thing, networkAddressService.getPrimaryIpv4HostAddress()); } - return null; } - - @Reference - protected void setNetworkAddressService(NetworkAddressService networkAddressService) { - this.networkAddressService = networkAddressService; - } - - protected void unsetNetworkAddressService(NetworkAddressService networkAddressService) { - this.networkAddressService = null; - } } diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/binding/binding.xml index f256fe8468ca9..6acf8063de5f1 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/binding/binding.xml @@ -1,11 +1,11 @@ - + GlobalCache Binding - Binding for GlobalCache iTach and GC-100 devices supporting infrared, serial, and contact closure interfaces. + Binding for GlobalCache iTach and GC-100 devices supporting infrared, serial, and contact closure + interfaces. Mark Hilbush diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channel-types.xml index 9bbe57a5bf5a3..fe29f9139bd17 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channel-types.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channels.xml index bde501d185e67..f9bba9a3a8216 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/channels.xml @@ -1,5 +1,6 @@ - @@ -77,7 +78,7 @@ - Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug. + Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug. 1 1 @@ -125,7 +126,7 @@ - Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug. + Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug. 2 1 @@ -158,7 +159,7 @@ - Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug. + Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug. 4 1 @@ -191,7 +192,7 @@ - Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug. + Infrared emitter on connector 1. Connector 1 is the connector closest to the power plug. 5 1 diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/gc-100-06.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/gc-100-06.xml index ea0ef0af9760e..6ec0d84bf8197 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/gc-100-06.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/gc-100-06.xml @@ -1,5 +1,6 @@ - @@ -10,8 +11,8 @@ GC-100-06 Infrared and Serial Device - - + + diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/gc-100-12.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/gc-100-12.xml index f2f5b343601c2..4b35b7c8e7b83 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/gc-100-12.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/gc-100-12.xml @@ -1,5 +1,6 @@ - @@ -10,11 +11,11 @@ GC-100-12 Infrared, Serial, and Contact Closure Device - - - - - + + + + + diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-cc.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-cc.xml index 9de50aae4808d..78bf77df3facf 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-cc.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-cc.xml @@ -1,5 +1,6 @@ - @@ -10,7 +11,7 @@ iTach Contact Closure Device (WF2CC or IP2CC) - + diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-flex.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-flex.xml index 2efa75a831d58..d8a7103387957 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-flex.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-flex.xml @@ -1,5 +1,6 @@ - @@ -10,9 +11,9 @@ iTach Flex Device - - - + + + diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-ir.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-ir.xml index 3a2733e6ba026..1a541fb4ba62b 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-ir.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-ir.xml @@ -1,5 +1,6 @@ - @@ -10,7 +11,7 @@ iTach Infrared Device (WF2IR or IP2IR) - + diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-sl.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-sl.xml index 708f7a06aece9..abb1f396746b3 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-sl.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/itach-sl.xml @@ -1,5 +1,6 @@ - @@ -10,7 +11,7 @@ iTach Serial Device (WF2SL or IP2SL) - + diff --git a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/zmote.xml b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/zmote.xml index c4507e501a661..e61ddf9db891b 100644 --- a/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/zmote.xml +++ b/bundles/org.openhab.binding.globalcache/src/main/resources/ESH-INF/thing/zmote.xml @@ -1,5 +1,6 @@ - @@ -10,7 +11,7 @@ Zmote Infrared Device - + diff --git a/bundles/org.openhab.binding.goecharger/pom.xml b/bundles/org.openhab.binding.goecharger/pom.xml index 78274e789c226..2b724511c1683 100644 --- a/bundles/org.openhab.binding.goecharger/pom.xml +++ b/bundles/org.openhab.binding.goecharger/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.goecharger diff --git a/bundles/org.openhab.binding.goecharger/src/main/java/org/openhab/binding/goecharger/internal/handler/GoEChargerHandler.java b/bundles/org.openhab.binding.goecharger/src/main/java/org/openhab/binding/goecharger/internal/handler/GoEChargerHandler.java index fa064320ded1e..d493fb6f471ab 100755 --- a/bundles/org.openhab.binding.goecharger/src/main/java/org/openhab/binding/goecharger/internal/handler/GoEChargerHandler.java +++ b/bundles/org.openhab.binding.goecharger/src/main/java/org/openhab/binding/goecharger/internal/handler/GoEChargerHandler.java @@ -412,7 +412,6 @@ private void refresh() { } catch (InterruptedException | TimeoutException | ExecutionException e) { updateChannelsAndStatus(null, e.getMessage()); } - } private void startAutomaticRefresh() { diff --git a/bundles/org.openhab.binding.goecharger/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.goecharger/src/main/resources/ESH-INF/thing/thing-types.xml index b62027c388950..ca60f326f25bc 100755 --- a/bundles/org.openhab.binding.goecharger/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.goecharger/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,27 +9,27 @@ Go-eCharger thing that represents the wallbox configuration and readings - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + @@ -63,7 +63,7 @@ Number:ElectricCurrent Maximum current per phase allowed to use for charging - + String @@ -95,102 +95,102 @@ Number:ElectricPotential Voltage on L1 - + Number:ElectricPotential Voltage on L2 - + Number:ElectricPotential Voltage on L3 - + Number:ElectricCurrent Current on L1 - + Number:ElectricCurrent Current on L2 - + Number:ElectricCurrent Current on L3 - + Number:Power Power on L1 - + Number:Power Power on L2 - + Number:Power Power on L3 - + Number Amount of phases currently used for charging - + Number:Energy Wallbox stops charging after defined value, deactivate with value 0 - + Number:Energy Amount of energy that has been charged in this session - + Number:Energy Amount of energy that has been charged since installation - + Switch If true charging is allowed - + Number:ElectricCurrent Specifies the max amps that can be charged with that cable - + Number:Temperature Temperature of the Go-eCharger - + String Firmware Version - + diff --git a/bundles/org.openhab.binding.gpstracker/pom.xml b/bundles/org.openhab.binding.gpstracker/pom.xml index 331dd32705e21..1d87caa955b58 100644 --- a/bundles/org.openhab.binding.gpstracker/pom.xml +++ b/bundles/org.openhab.binding.gpstracker/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.gpstracker diff --git a/bundles/org.openhab.binding.gpstracker/src/main/feature/feature.xml b/bundles/org.openhab.binding.gpstracker/src/main/feature/feature.xml index a36535e11f1f7..97563ed01e6c1 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.gpstracker/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.gpstracker/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.gpstracker/${project.version} + diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/GPSTrackerBindingConstants.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/GPSTrackerBindingConstants.java index 3c8e2cfc3d027..53fc06aebde02 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/GPSTrackerBindingConstants.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/GPSTrackerBindingConstants.java @@ -12,14 +12,13 @@ */ package org.openhab.binding.gpstracker.internal; - -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; - import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; + /** * Binding constants * @@ -31,7 +30,7 @@ public abstract class GPSTrackerBindingConstants { private static final String THING_TYPE = "tracker"; public static final ThingTypeUID THING_TYPE_TRACKER = new ThingTypeUID(BINDING_ID, THING_TYPE); - //channels + // channels public static final String CHANNEL_REGION_TRIGGER = "regionTrigger"; public static final String CHANNEL_LAST_REPORT = "lastReport"; public static final String CHANNEL_LAST_LOCATION = "lastLocation"; @@ -39,7 +38,7 @@ public abstract class GPSTrackerBindingConstants { private static final String CHANNEL_REGION_DISTANCE = "regionDistance"; public static final String CHANNEL_GPS_ACCURACY = "gpsAccuracy"; - //system distance channel + // system distance channel public static final String CHANNEL_DISTANCE_SYSTEM_ID = "distanceSystem"; public static final String CHANNEL_DISTANCE_SYSTEM_NAME = "System"; public static final Integer CHANNEL_DISTANCE_SYSTEM_RADIUS = 100; @@ -47,5 +46,6 @@ public abstract class GPSTrackerBindingConstants { public static final ChannelTypeUID CHANNEL_TYPE_DISTANCE = new ChannelTypeUID(BINDING_ID, CHANNEL_REGION_DISTANCE); public static final ChannelTypeUID CHANNEL_TYPE_REGION = new ChannelTypeUID(BINDING_ID, CHANNEL_REGION_TRIGGER); - public static final Set SUPPORTED_THING_TYPES_UIDS = Stream.of(THING_TYPE_TRACKER).collect(Collectors.toSet()); + public static final Set SUPPORTED_THING_TYPES_UIDS = Stream.of(THING_TYPE_TRACKER) + .collect(Collectors.toSet()); } diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/GPSTrackerHandlerFactory.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/GPSTrackerHandlerFactory.java index c95054e7c618e..d0d7aafd3dfaf 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/GPSTrackerHandlerFactory.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/GPSTrackerHandlerFactory.java @@ -12,6 +12,13 @@ */ package org.openhab.binding.gpstracker.internal; +import static org.openhab.binding.gpstracker.internal.GPSTrackerBindingConstants.CONFIG_PID; + +import java.net.URI; +import java.util.*; + +import javax.servlet.ServletException; + import org.eclipse.smarthome.config.core.ConfigOptionProvider; import org.eclipse.smarthome.config.core.ParameterOption; import org.eclipse.smarthome.core.i18n.LocationProvider; @@ -36,18 +43,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.servlet.ServletException; -import java.net.URI; -import java.util.*; - -import static org.openhab.binding.gpstracker.internal.GPSTrackerBindingConstants.CONFIG_PID; - /** * Main component * * @author Gabor Bicskei - Initial contribution */ -@Component(configurationPid = CONFIG_PID, service = {ThingHandlerFactory.class, ConfigOptionProvider.class}) +@Component(configurationPid = CONFIG_PID, service = { ThingHandlerFactory.class, ConfigOptionProvider.class }) public class GPSTrackerHandlerFactory extends BaseThingHandlerFactory implements TrackerRegistry, ConfigOptionProvider { /** * Config URI @@ -127,7 +128,7 @@ protected ThingHandler createHandler(Thing thing) { if (GPSTrackerBindingConstants.THING_TYPE_TRACKER.equals(thingTypeUID) && ConfigHelper.getTrackerId(thing.getConfiguration()) != null) { TrackerHandler trackerHandler = new TrackerHandler(thing, notificationBroker, regions, - locationProvider != null ? locationProvider.getLocation(): null, unitProvider); + locationProvider != null ? locationProvider.getLocation() : null, unitProvider); discoveryService.removeTracker(trackerHandler.getTrackerId()); trackerHandlers.put(trackerHandler.getTrackerId(), trackerHandler); return trackerHandler; @@ -189,7 +190,7 @@ protected void deactivate(ComponentContext componentContext) { public Collection getParameterOptions(URI uri, String param, Locale locale) { if (URI_STR.equals(uri.toString()) && ConfigHelper.CONFIG_REGION_NAME.equals(param)) { Set ret = new HashSet<>(); - regions.forEach(r->ret.add(new ParameterOption(r, r))); + regions.forEach(r -> ret.add(new ParameterOption(r, r))); return ret; } return Collections.emptyList(); diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/config/ConfigHelper.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/config/ConfigHelper.java index 7aac7e187f5ff..3ffcf5e0779ac 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/config/ConfigHelper.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/config/ConfigHelper.java @@ -12,18 +12,18 @@ */ package org.openhab.binding.gpstracker.internal.config; +import java.math.BigDecimal; + import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.core.library.types.PointType; -import java.math.BigDecimal; - /** * The {@link ConfigHelper} class is a configuration helper for channels and profiles. * * @author Gabor Bicskei - Initial contribution */ public class ConfigHelper { - //configuration constants + // configuration constants public static final String CONFIG_TRACKER_ID = "trackerId"; public static final String CONFIG_REGION_NAME = "regionName"; public static final String CONFIG_REGION_RADIUS = "regionRadius"; @@ -33,7 +33,8 @@ public class ConfigHelper { /** * Constructor. */ - private ConfigHelper() {} + private ConfigHelper() { + } public static double getRegionRadius(Configuration config) { return ((BigDecimal) config.get(CONFIG_REGION_RADIUS)).doubleValue(); @@ -41,7 +42,7 @@ public static double getRegionRadius(Configuration config) { public static double getAccuracyThreshold(Configuration config) { Object value = config.get(CONFIG_ACCURACY_THRESHOLD); - return value != null ? ((BigDecimal) value).doubleValue(): 0; + return value != null ? ((BigDecimal) value).doubleValue() : 0; } public static String getRegionName(Configuration config) { @@ -54,6 +55,6 @@ public static String getTrackerId(Configuration config) { public static PointType getRegionCenterLocation(Configuration config) { String location = (String) config.get(CONFIG_REGION_CENTER_LOCATION); - return location != null ? new PointType(location): null; + return location != null ? new PointType(location) : null; } } diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/discovery/TrackerDiscoveryService.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/discovery/TrackerDiscoveryService.java index 6753c511d85fb..a927b7854f8ed 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/discovery/TrackerDiscoveryService.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/discovery/TrackerDiscoveryService.java @@ -12,6 +12,11 @@ */ package org.openhab.binding.gpstracker.internal.discovery; +import java.util.Date; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; @@ -26,11 +31,6 @@ import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Modified; -import java.util.Date; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - /** * The {@link TrackerDiscoveryService} class provides discovery service for the binding to discover trackers. Discovery * process is initiated by the tracker by sending a GPS log record. Based on the tracker id received in thin record an @@ -39,7 +39,8 @@ * @author Gabor Bicskei - Initial contribution */ @NonNullByDefault -@Component(service = { DiscoveryService.class, TrackerDiscoveryService.class }, immediate = true, configurationPid = "discovery.gpstracker") +@Component(service = { DiscoveryService.class, + TrackerDiscoveryService.class }, immediate = true, configurationPid = "discovery.gpstracker") public class TrackerDiscoveryService extends AbstractDiscoveryService { /** * Discovery timeout @@ -96,8 +97,7 @@ private void createDiscoveryResult(String trackerId) { ThingUID id = new ThingUID(GPSTrackerBindingConstants.THING_TYPE_TRACKER, trackerId); DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(id) .withProperty(ConfigHelper.CONFIG_TRACKER_ID, trackerId) - .withThingType(GPSTrackerBindingConstants.THING_TYPE_TRACKER) - .withLabel("GPS Tracker " + trackerId) + .withThingType(GPSTrackerBindingConstants.THING_TYPE_TRACKER).withLabel("GPS Tracker " + trackerId) .build(); this.thingDiscovered(discoveryResult); } diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/handler/TrackerHandler.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/handler/TrackerHandler.java index 58ffe7b603a42..89937b7835af6 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/handler/TrackerHandler.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/handler/TrackerHandler.java @@ -120,11 +120,11 @@ public class TrackerHandler extends BaseThingHandler { /** * Constructor. * - * @param thing Thing. + * @param thing Thing. * @param notificationBroker Notification broker - * @param regions Global region set - * @param sysLocation Location of the system - * @param unitProvider Unit provider + * @param regions Global region set + * @param sysLocation Location of the system + * @param unitProvider Unit provider */ public TrackerHandler(Thing thing, NotificationBroker notificationBroker, Set regions, PointType sysLocation, UnitProvider unitProvider) { @@ -269,7 +269,7 @@ private void updateTriggerChannelsWithTransition(TransitionMessage message) { * Fire trigger event with regionName/enter|leave payload but only if the event differs from the last event. * * @param regionName Region name - * @param event Occurred event + * @param event Occurred event */ private void triggerRegionChannel(@NonNull String regionName, @NonNull String event) { Boolean lastState = lastTriggeredStates.get(regionName); diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/MessageUtil.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/MessageUtil.java index 22c3b9c1df4e0..c8fe210aebf87 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/MessageUtil.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/MessageUtil.java @@ -12,11 +12,11 @@ */ package org.openhab.binding.gpstracker.internal.message; -import com.google.gson.Gson; - import java.util.HashMap; import java.util.Map; +import com.google.gson.Gson; + /** * Message handling utility * @@ -26,9 +26,8 @@ public class MessageUtil { /** * Patterns to identify incoming JSON payload. */ - private static final String[] PATTERNS = new String[]{ - ".*\"_type\"\\s*:\\s*\"transition\".*", //transition - ".*\"_type\"\\s*:\\s*\"location\".*", //location + private static final String[] PATTERNS = new String[] { ".*\"_type\"\\s*:\\s*\"transition\".*", // transition + ".*\"_type\"\\s*:\\s*\"location\".*", // location }; /** diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/NotificationBroker.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/NotificationBroker.java index 9b952c981eb7d..0194ffe6bc988 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/NotificationBroker.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/NotificationBroker.java @@ -38,7 +38,7 @@ public void registerHandler(String trackerId, NotificationHandler handler) { public void sendNotification(LocationMessage msg) { String trackerId = msg.getTrackerId(); - handlers.entrySet().stream().filter(e->!e.getKey().equals(trackerId)) - .forEach(e->e.getValue().handleNotification(msg)); + handlers.entrySet().stream().filter(e -> !e.getKey().equals(trackerId)) + .forEach(e -> e.getValue().handleNotification(msg)); } } diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/NotificationHandler.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/NotificationHandler.java index c6b969f806e98..e2a80e5a67d3d 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/NotificationHandler.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/NotificationHandler.java @@ -30,7 +30,8 @@ public class NotificationHandler { private Map locationNotifications = new HashMap<>(); /** - * TransitionMessage notification to send out to the own tracker. Notifications are saved in order they were received. + * TransitionMessage notification to send out to the own tracker. Notifications are saved in order they were + * received. */ private Map> transitionNotifications = new HashMap<>(); @@ -43,8 +44,8 @@ public void handleNotification(LocationMessage msg) { synchronized (this) { String trackerId = msg.getTrackerId(); if (msg instanceof TransitionMessage) { - List transitionMessages = transitionNotifications - .computeIfAbsent(trackerId, k -> new ArrayList<>()); + List transitionMessages = transitionNotifications.computeIfAbsent(trackerId, + k -> new ArrayList<>()); transitionMessages.add((TransitionMessage) msg); } else { locationNotifications.put(trackerId, msg); diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/TransitionMessage.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/TransitionMessage.java index bbcded91c203e..b4c32e3f8ff79 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/TransitionMessage.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/message/TransitionMessage.java @@ -23,8 +23,8 @@ public class TransitionMessage extends LocationMessage { /** * Event that triggered the transition (iOS,Android/string/required) - * enter The tracker entered the defined geographical region or BLE Beacon range (iOS) - * leave The tracker left the defined geographical region or BLE Beacon range (iOS) + * enter The tracker entered the defined geographical region or BLE Beacon range (iOS) + * leave The tracker left the defined geographical region or BLE Beacon range (iOS) */ @SerializedName("event") String event; diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/profile/GPSTrackerProfileFactory.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/profile/GPSTrackerProfileFactory.java index c95cc1d95b7a5..692baa617a356 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/profile/GPSTrackerProfileFactory.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/profile/GPSTrackerProfileFactory.java @@ -12,6 +12,13 @@ */ package org.openhab.binding.gpstracker.internal.profile; +import static org.openhab.binding.gpstracker.internal.GPSTrackerBindingConstants.CHANNEL_TYPE_REGION; + +import java.util.Collection; +import java.util.Locale; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.CoreItemFactory; @@ -22,13 +29,6 @@ import org.openhab.binding.gpstracker.internal.GPSTrackerBindingConstants; import org.osgi.service.component.annotations.Component; -import java.util.Collection; -import java.util.Locale; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.openhab.binding.gpstracker.internal.GPSTrackerBindingConstants.CHANNEL_TYPE_REGION; - /** * The {@link GPSTrackerProfileFactory} class defines and provides switch profile and its type of this binding. * @@ -40,15 +40,15 @@ public class GPSTrackerProfileFactory implements ProfileFactory, ProfileAdvisor, /** * Profile UID for trigger events */ - static final ProfileTypeUID UID_TRIGGER_SWITCH = new ProfileTypeUID(GPSTrackerBindingConstants.BINDING_ID, "trigger-geofence"); + static final ProfileTypeUID UID_TRIGGER_SWITCH = new ProfileTypeUID(GPSTrackerBindingConstants.BINDING_ID, + "trigger-geofence"); /** * Profile type for trigger events */ - private static final TriggerProfileType TRIGGER_SWITCH_TYPE = ProfileTypeBuilder.newTrigger(UID_TRIGGER_SWITCH, "Geofence") - .withSupportedItemTypes(CoreItemFactory.SWITCH) - .withSupportedChannelTypeUIDs(CHANNEL_TYPE_REGION) - .build(); + private static final TriggerProfileType TRIGGER_SWITCH_TYPE = ProfileTypeBuilder + .newTrigger(UID_TRIGGER_SWITCH, "Geofence").withSupportedItemTypes(CoreItemFactory.SWITCH) + .withSupportedChannelTypeUIDs(CHANNEL_TYPE_REGION).build(); @Override public Collection getSupportedProfileTypeUIDs() { @@ -70,7 +70,8 @@ public Collection getProfileTypes(@Nullable Locale locale) { return getSuggestedProfileTypeUID(channelType.getUID(), itemType); } - private @Nullable ProfileTypeUID getSuggestedProfileTypeUID(@Nullable ChannelTypeUID channelTypeUID, @Nullable String itemType) { + private @Nullable ProfileTypeUID getSuggestedProfileTypeUID(@Nullable ChannelTypeUID channelTypeUID, + @Nullable String itemType) { if (CoreItemFactory.SWITCH.equals(itemType) && CHANNEL_TYPE_REGION.equals(channelTypeUID)) { return UID_TRIGGER_SWITCH; } @@ -78,7 +79,8 @@ public Collection getProfileTypes(@Nullable Locale locale) { } @Override - public @Nullable Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback, ProfileContext profileContext) { + public @Nullable Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback, + ProfileContext profileContext) { if (UID_TRIGGER_SWITCH.equals(profileTypeUID)) { return new GPSTrackerTriggerSwitchProfile(callback, profileContext); } diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/AbstractCallbackServlet.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/AbstractCallbackServlet.java index e7dae2a8a4153..3dbae0d13e9d3 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/AbstractCallbackServlet.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/AbstractCallbackServlet.java @@ -61,7 +61,7 @@ public abstract class AbstractCallbackServlet extends HttpServlet { * Constructor called at binding startup. * * @param discoveryService Discovery service for new trackers. - * @param trackerRegistry Tracker handler registry + * @param trackerRegistry Tracker handler registry */ protected AbstractCallbackServlet(TrackerDiscoveryService discoveryService, TrackerRegistry trackerRegistry) { this.discoveryService = discoveryService; @@ -73,7 +73,7 @@ protected AbstractCallbackServlet(TrackerDiscoveryService discoveryService, Trac /** * Process the HTTP requests from tracker applications * - * @param req HTTP request + * @param req HTTP request * @param resp HTTP response */ @Override diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/gpslogger/GPSLoggerCallbackServlet.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/gpslogger/GPSLoggerCallbackServlet.java index f9d81464829d8..9a610c0f48686 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/gpslogger/GPSLoggerCallbackServlet.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/gpslogger/GPSLoggerCallbackServlet.java @@ -39,7 +39,7 @@ public class GPSLoggerCallbackServlet extends AbstractCallbackServlet { * Constructor called at binding startup. * * @param discoveryService Discovery service for new trackers. - * @param trackerRegistry Tracker registry + * @param trackerRegistry Tracker registry */ public GPSLoggerCallbackServlet(TrackerDiscoveryService discoveryService, TrackerRegistry trackerRegistry) { super(discoveryService, trackerRegistry); diff --git a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/owntracks/OwnTracksCallbackServlet.java b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/owntracks/OwnTracksCallbackServlet.java index 2a2286c500523..e612fbc1e1e3b 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/owntracks/OwnTracksCallbackServlet.java +++ b/bundles/org.openhab.binding.gpstracker/src/main/java/org/openhab/binding/gpstracker/internal/provider/owntracks/OwnTracksCallbackServlet.java @@ -39,7 +39,7 @@ public class OwnTracksCallbackServlet extends AbstractCallbackServlet { * Constructor called at binding startup. * * @param discoveryService Discovery service for new trackers. - * @param trackerRegistry Tracker registry + * @param trackerRegistry Tracker registry */ public OwnTracksCallbackServlet(TrackerDiscoveryService discoveryService, TrackerRegistry trackerRegistry) { super(discoveryService, trackerRegistry); diff --git a/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/config/config.xml index d276d3416aab9..a9d51fa57749e 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/config/config.xml @@ -1,8 +1,8 @@ diff --git a/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/config/profile.xml b/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/config/profile.xml index 71c9c4d9ff8d5..8838603892089 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/config/profile.xml +++ b/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/config/profile.xml @@ -1,8 +1,8 @@ diff --git a/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/thing/tracker.xml b/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/thing/tracker.xml index 50fd6268db072..9221356941657 100644 --- a/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/thing/tracker.xml +++ b/bundles/org.openhab.binding.gpstracker/src/main/resources/ESH-INF/thing/tracker.xml @@ -18,7 +18,7 @@ - + Number:Length @@ -42,7 +42,8 @@ trigger - Trigger channel for entering/leaving regions. Payload is the region name with prefix > for entering and < for leaving. + Trigger channel for entering/leaving regions. Payload is the region name with prefix > for entering + and < for leaving. diff --git a/bundles/org.openhab.binding.groheondus/pom.xml b/bundles/org.openhab.binding.groheondus/pom.xml index 969387d338396..00bfda7d0a809 100644 --- a/bundles/org.openhab.binding.groheondus/pom.xml +++ b/bundles/org.openhab.binding.groheondus/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.groheondus diff --git a/bundles/org.openhab.binding.groheondus/src/main/feature/feature.xml b/bundles/org.openhab.binding.groheondus/src/main/feature/feature.xml index 81aa944f71a05..bcc0aa4659961 100644 --- a/bundles/org.openhab.binding.groheondus/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.groheondus/src/main/feature/feature.xml @@ -1,12 +1,12 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab.tp-jackson - mvn:org.apache.commons/commons-text/1.6 - mvn:org.apache.commons/commons-lang3/3.8.1 - mvn:org.openhab.addons.bundles/org.openhab.binding.groheondus/${project.version} - + + openhab-runtime-base + openhab.tp-jackson + mvn:org.apache.commons/commons-text/1.6 + mvn:org.apache.commons/commons-lang3/3.8.1 + mvn:org.openhab.addons.bundles/org.openhab.binding.groheondus/${project.version} + diff --git a/bundles/org.openhab.binding.groheondus/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.groheondus/src/main/resources/ESH-INF/thing/thing-types.xml index 53173105d8cda..b7fef7a5fb6c8 100644 --- a/bundles/org.openhab.binding.groheondus/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.groheondus/src/main/resources/ESH-INF/thing/thing-types.xml @@ -6,7 +6,8 @@ - This is an interface to the GROHE ONDUS Account as it is used by the app. If username and password are not set, you can configure to use a `refreshToken` to login. Read the README to get more info. + This is an interface to the GROHE ONDUS Account as it is used by the app. If username and password are + not set, you can configure to use a `refreshToken` to login. Read the README to get more info. @@ -25,18 +26,18 @@ - + A SENSE GUARD device - - - - - + + + + + applianceId @@ -56,24 +57,25 @@ - The interval in seconds used to poll the API for new data. Defaults to the configuration of the appliance itself as retrieved from the API, usually 15 minutes. + The interval in seconds used to poll the API for new data. Defaults to the configuration of the + appliance itself as retrieved from the API, usually 15 minutes. - + A SENSE device - - - - + + + + applianceId @@ -112,7 +114,7 @@ Number:Temperature The ambient temperature of the appliance - + Switch @@ -123,19 +125,19 @@ Number:Dimensionless The humidity reported by the device - + Number:Temperature The temperature reported by the device - + Number The amount of water consumed in the given time period. - + diff --git a/bundles/org.openhab.binding.harmonyhub/pom.xml b/bundles/org.openhab.binding.harmonyhub/pom.xml index 2056a5cf145a2..141d90293bd56 100644 --- a/bundles/org.openhab.binding.harmonyhub/pom.xml +++ b/bundles/org.openhab.binding.harmonyhub/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.harmonyhub diff --git a/bundles/org.openhab.binding.harmonyhub/src/main/feature/feature.xml b/bundles/org.openhab.binding.harmonyhub/src/main/feature/feature.xml index 010ee8b9b2bf1..c9bf07622e2a0 100644 --- a/bundles/org.openhab.binding.harmonyhub/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.harmonyhub/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.harmonyhub/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.harmonyhub/${project.version} + diff --git a/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/HarmonyHubBindingConstants.java b/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/HarmonyHubBindingConstants.java index 8f3183385a0b1..477f6e3caf13b 100644 --- a/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/HarmonyHubBindingConstants.java +++ b/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/HarmonyHubBindingConstants.java @@ -45,5 +45,4 @@ public class HarmonyHubBindingConstants { public static final String HUB_PROPERTY_ID = "id"; public static final String HUB_PROPERTY_HOST = "host"; public static final String HUB_PROPERTY_NAME = "name"; - } diff --git a/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/HarmonyHubHandlerFactory.java b/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/HarmonyHubHandlerFactory.java index 4419fea862828..693074075234f 100644 --- a/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/HarmonyHubHandlerFactory.java +++ b/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/HarmonyHubHandlerFactory.java @@ -177,5 +177,4 @@ public void removeChannelTypesForThing(ThingUID uid) { } channelTypes.removeAll(removes); } - } diff --git a/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/handler/HarmonyHubHandler.java b/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/handler/HarmonyHubHandler.java index e5020be0279f3..070ad47bf6c9f 100644 --- a/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/handler/HarmonyHubHandler.java +++ b/bundles/org.openhab.binding.harmonyhub/src/main/java/org/openhab/binding/harmonyhub/internal/handler/HarmonyHubHandler.java @@ -445,5 +445,4 @@ public void addHubStatusListener(HubStatusListener listener) { public void removeHubStatusListener(HubStatusListener listener) { listeners.remove(listener); } - } diff --git a/bundles/org.openhab.binding.harmonyhub/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.harmonyhub/src/main/resources/ESH-INF/binding/binding.xml index a6e461446339e..47e03f0bd832c 100644 --- a/bundles/org.openhab.binding.harmonyhub/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.harmonyhub/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + HarmonyHub Binding The HarmonyHub Binding integrates Logitech Harmony hubs and remotes. diff --git a/bundles/org.openhab.binding.harmonyhub/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.harmonyhub/src/main/resources/ESH-INF/thing/thing-types.xml index 68cc560cffc66..04738360aee0e 100644 --- a/bundles/org.openhab.binding.harmonyhub/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.harmonyhub/src/main/resources/ESH-INF/thing/thing-types.xml @@ -8,7 +8,7 @@ A Logitech Harmony Hub - + Triggered when an activity is starting @@ -19,9 +19,10 @@ - The label/name of the button to press on a Harmony Hub which will be sent to the device associated with the current activity and label + The label/name of the button to press on a Harmony Hub which will be sent to the device associated with + the current activity and label - + @@ -43,12 +44,12 @@ - + Logitech Harmony Hub Device - + @@ -83,7 +84,8 @@ Player - Send player commands (Rewind,FastForward,Play,Pause,SkipForward,SkipBackwards) to the device associated with the current running activity. + Send player commands (Rewind,FastForward,Play,Pause,SkipForward,SkipBackwards) to the device associated + with the current running activity. diff --git a/bundles/org.openhab.binding.hdanywhere/pom.xml b/bundles/org.openhab.binding.hdanywhere/pom.xml index 9c246f1923670..7be57b324dd58 100644 --- a/bundles/org.openhab.binding.hdanywhere/pom.xml +++ b/bundles/org.openhab.binding.hdanywhere/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.hdanywhere diff --git a/bundles/org.openhab.binding.hdanywhere/src/main/feature/feature.xml b/bundles/org.openhab.binding.hdanywhere/src/main/feature/feature.xml index 80c7125a05746..6a4470344092e 100644 --- a/bundles/org.openhab.binding.hdanywhere/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.hdanywhere/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.hdanywhere/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.hdanywhere/${project.version} + diff --git a/bundles/org.openhab.binding.hdanywhere/src/main/java/org/openhab/binding/hdanywhere/internal/HDanywhereBindingConstants.java b/bundles/org.openhab.binding.hdanywhere/src/main/java/org/openhab/binding/hdanywhere/internal/HDanywhereBindingConstants.java index 5a3b84b0b20b1..a82ed7004a64d 100644 --- a/bundles/org.openhab.binding.hdanywhere/src/main/java/org/openhab/binding/hdanywhere/internal/HDanywhereBindingConstants.java +++ b/bundles/org.openhab.binding.hdanywhere/src/main/java/org/openhab/binding/hdanywhere/internal/HDanywhereBindingConstants.java @@ -81,7 +81,5 @@ public static Port get(String valueSelectorText) throws IllegalArgumentException public String channelID() { return this.id; } - } - } diff --git a/bundles/org.openhab.binding.hdanywhere/src/main/java/org/openhab/binding/hdanywhere/internal/handler/Mhub4K431Handler.java b/bundles/org.openhab.binding.hdanywhere/src/main/java/org/openhab/binding/hdanywhere/internal/handler/Mhub4K431Handler.java index b0b3ab66a0f96..e71ffa57019ac 100644 --- a/bundles/org.openhab.binding.hdanywhere/src/main/java/org/openhab/binding/hdanywhere/internal/handler/Mhub4K431Handler.java +++ b/bundles/org.openhab.binding.hdanywhere/src/main/java/org/openhab/binding/hdanywhere/internal/handler/Mhub4K431Handler.java @@ -164,5 +164,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { } } } - } diff --git a/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/binding/binding.xml index a37301c776a73..809d78a4c12e3 100644 --- a/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + openHAB HDanywhere Binding This is the binding for HDanywhere HDMI Matrices diff --git a/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/thing/mhub4k431.xml b/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/thing/mhub4k431.xml index 6d2bf4a4d50a5..4295ba194cfd1 100644 --- a/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/thing/mhub4k431.xml +++ b/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/thing/mhub4k431.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -34,7 +34,8 @@ Number - The port channel allows to set or read the number of the input port that is connected to the output port. Valid values are 1 to 4 + The port channel allows to set or read the number of the input port that is connected to the output port. + Valid values are 1 to 4 diff --git a/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/thing/multiroomplus.xml b/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/thing/multiroomplus.xml index 29dcce7159646..334c82be757b3 100644 --- a/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/thing/multiroomplus.xml +++ b/bundles/org.openhab.binding.hdanywhere/src/main/resources/ESH-INF/thing/multiroomplus.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -28,7 +28,8 @@ - Specifies the number of input/output ports on the Matrix, e.g. 4 or 8 if 4x4 or 8x8 version of the Matrix + Specifies the number of input/output ports on the Matrix, e.g. 4 or 8 if 4x4 or 8x8 version of the + Matrix 4 @@ -43,7 +44,8 @@ Number - The port channel allows to set or read the number of the input port that is connected to the output port. Valid values are 1 to 8 depending on the nature of the Matrix, e.g 4x4 8x8 etc + The port channel allows to set or read the number of the input port that is connected to the output port. + Valid values are 1 to 8 depending on the nature of the Matrix, e.g 4x4 8x8 etc diff --git a/bundles/org.openhab.binding.hdpowerview/pom.xml b/bundles/org.openhab.binding.hdpowerview/pom.xml index ffc67b1423265..88a1877a5f269 100644 --- a/bundles/org.openhab.binding.hdpowerview/pom.xml +++ b/bundles/org.openhab.binding.hdpowerview/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.hdpowerview diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/feature/feature.xml b/bundles/org.openhab.binding.hdpowerview/src/main/feature/feature.xml index 39c632c82735f..589480fba40c6 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.samba.jcifs/jcifs/1.3.17 - mvn:org.openhab.addons.bundles/org.openhab.binding.hdpowerview/${project.version} - + + openhab-runtime-base + mvn:org.samba.jcifs/jcifs/1.3.17 + mvn:org.openhab.addons.bundles/org.openhab.binding.hdpowerview/${project.version} + diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java index c6129af9acf85..63b5ad2e66881 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java @@ -48,5 +48,4 @@ public class HDPowerViewBindingConstants { SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_HUB); SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_SHADE); } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java index 3bdd8556fb4f5..6e57ab09a7d07 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java @@ -111,5 +111,4 @@ private Response invoke(Invocation invocation, WebTarget target) throws Processi return response; } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/ShadePositionKind.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/ShadePositionKind.java index bb8c320822d2f..5fdef6dfa08d4 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/ShadePositionKind.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/ShadePositionKind.java @@ -41,5 +41,4 @@ public static ShadePositionKind get(int key) { return null; } } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Scenes.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Scenes.java index a1275fdaa5873..5673d2bc81739 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Scenes.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Scenes.java @@ -37,5 +37,4 @@ public String getName() { return new String(Base64.getDecoder().decode(name)); } } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/config/HDPowerViewSceneConfiguration.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/config/HDPowerViewSceneConfiguration.java index d3415b2ee6c9d..91b73c4054119 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/config/HDPowerViewSceneConfiguration.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/config/HDPowerViewSceneConfiguration.java @@ -22,5 +22,4 @@ public class HDPowerViewSceneConfiguration { public static final String ID = "id"; public int id; - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/config/HDPowerViewShadeConfiguration.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/config/HDPowerViewShadeConfiguration.java index 5f1819a5ae66c..620172d1b981c 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/config/HDPowerViewShadeConfiguration.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/config/HDPowerViewShadeConfiguration.java @@ -22,5 +22,4 @@ public class HDPowerViewShadeConfiguration { public static final String ID = "id"; public String id; - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryService.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryService.java index c3153dacd5edb..5c942dd7bd1d3 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryService.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewHubDiscoveryService.java @@ -85,5 +85,4 @@ private Runnable createScanner() { } }; } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewShadeDiscoveryService.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewShadeDiscoveryService.java index 10fd399001fa2..12c7bb6c8ad80 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewShadeDiscoveryService.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewShadeDiscoveryService.java @@ -94,5 +94,4 @@ private Runnable createScanner() { stopScan(); }; } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/AbstractHubbedThingHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/AbstractHubbedThingHandler.java index 4991bd1cd6e8d..7acc5d59be453 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/AbstractHubbedThingHandler.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/AbstractHubbedThingHandler.java @@ -45,5 +45,4 @@ protected HDPowerViewHubHandler getBridgeHandler() { } return (HDPowerViewHubHandler) handler; } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java index fd5c0d0f918a5..83953e408f202 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java @@ -223,5 +223,4 @@ private Map getSceneChannelsById() { } return ret; } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java index 13789dc465212..167b0f7149e5d 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java @@ -127,5 +127,4 @@ private void setPosition(ShadePosition position) { private String getShadeId() { return getConfigAs(HDPowerViewShadeConfiguration.class).id; } - } diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/ESH-INF/binding/binding.xml index ccfa472d7f89f..85e6b7722569f 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Hunter Douglas PowerView Binding The Hunter Douglas PowerView binding provides access to the Hunter Douglas line of PowerView shades. diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.hdpowerview/src/main/resources/ESH-INF/thing/thing-types.xml index 1ec7bd85b4e96..c74073f4c3d39 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.hdpowerview/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -24,7 +24,7 @@ - + Hunter Douglas PowerView Shade diff --git a/bundles/org.openhab.binding.helios/pom.xml b/bundles/org.openhab.binding.helios/pom.xml index 1212f07fc2627..244b8b147fc3a 100644 --- a/bundles/org.openhab.binding.helios/pom.xml +++ b/bundles/org.openhab.binding.helios/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.helios diff --git a/bundles/org.openhab.binding.helios/src/main/feature/feature.xml b/bundles/org.openhab.binding.helios/src/main/feature/feature.xml index a5fc54d21faaa..12b8277e3f22a 100644 --- a/bundles/org.openhab.binding.helios/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.helios/src/main/feature/feature.xml @@ -1,16 +1,16 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.apache.ws.xmlschema/xmlschema-core/2.2.4 - mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxws-api-2.2/2.9.0 - mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.saaj-api-1.3/2.9.0 - mvn:org.apache.cxf/cxf-core/3.1.14 - mvn:org.apache.cxf.services.wsn/cxf-services-wsn-api/3.1.14 - mvn:org.apache.felix/org.apache.felix.framework/6.0.2 - mvn:org.apache.geronimo.specs/geronimo-ws-metadata_2.0_spec/1.1.3 - mvn:org.openhab.addons.bundles/org.openhab.binding.helios/${project.version} - + + openhab-runtime-base + mvn:org.apache.ws.xmlschema/xmlschema-core/2.2.4 + mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxws-api-2.2/2.9.0 + mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.saaj-api-1.3/2.9.0 + mvn:org.apache.cxf/cxf-core/3.1.14 + mvn:org.apache.cxf.services.wsn/cxf-services-wsn-api/3.1.14 + mvn:org.apache.felix/org.apache.felix.framework/6.0.2 + mvn:org.apache.geronimo.specs/geronimo-ws-metadata_2.0_spec/1.1.3 + mvn:org.openhab.addons.bundles/org.openhab.binding.helios/${project.version} + diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTError.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTError.java index b59dd97aec8f5..9b970af54c636 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTError.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTError.java @@ -25,5 +25,4 @@ public class RESTError { RESTError() { } - } diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTSubscribeResponse.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTSubscribeResponse.java index b7007de537756..23fd196933678 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTSubscribeResponse.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTSubscribeResponse.java @@ -23,5 +23,4 @@ public class RESTSubscribeResponse { RESTSubscribeResponse() { } - } diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTSystemInfo.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTSystemInfo.java index 316b699f415bd..6d57cf1d5e84a 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTSystemInfo.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/rest/RESTSystemInfo.java @@ -28,5 +28,4 @@ public class RESTSystemInfo { RESTSystemInfo() { } - } diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCallStateChanged.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCallStateChanged.java index 02484053f7d61..bf08939704bdb 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCallStateChanged.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCallStateChanged.java @@ -49,5 +49,4 @@ public String getDirection() { public void setDirection(String direction) { this.direction = direction; } - } diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCardEntered.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCardEntered.java index 9d3543d6a0048..c8e6636c14022 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCardEntered.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCardEntered.java @@ -49,5 +49,4 @@ public String getValid() { public void setValid(String valid) { this.valid = valid; } - } diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCodeEntered.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCodeEntered.java index eaf572cf63f4b..a967365da2a72 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCodeEntered.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPCodeEntered.java @@ -49,5 +49,4 @@ public String getValid() { public void setValid(String valid) { this.valid = valid; } - } diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPDeviceState.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPDeviceState.java index 4199e9296a776..4d4ed6998e74e 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPDeviceState.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPDeviceState.java @@ -38,5 +38,4 @@ public String getState() { public void setState(String state) { this.state = state; } - } diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPKeyPressed.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPKeyPressed.java index 72b11ddd68e42..1df4b512479cc 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPKeyPressed.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPKeyPressed.java @@ -38,5 +38,4 @@ public String getKeyCode() { public void setKeyCode(String code) { this.keyCode = code; } - } diff --git a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPObjectFactory.java b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPObjectFactory.java index bd5037a87b69e..c56caccbc5a4f 100644 --- a/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPObjectFactory.java +++ b/bundles/org.openhab.binding.helios/src/main/java/org/openhab/binding/helios/internal/ws/soap/SOAPObjectFactory.java @@ -54,5 +54,4 @@ public JAXBElement createHeliosDeviceState(SOAPDeviceState valu public JAXBElement createHeliosKeyPressedd(SOAPKeyPressed value) { return new JAXBElement<>(DATA_QNAME, SOAPKeyPressed.class, null, value); } - } diff --git a/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/binding/binding.xml index f7c124cb100e4..1379060feb7e9 100644 --- a/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Helios Binding This is the binding for Helios IP (Vario/...) class of intercom/(video)doorstations. diff --git a/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/channel-types.xml index 41fcd8356151d..04016cabcb015 100644 --- a/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/channel-types.xml @@ -1,5 +1,6 @@ - @@ -9,13 +10,13 @@ Switch Audio loop test result - + DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + String @@ -44,7 +45,7 @@ DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + trigger @@ -55,13 +56,13 @@ Switch If the detected card is valid, the parameter value is ON. If not, the parameter is set to OFF - + DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + trigger @@ -72,13 +73,13 @@ Switch If the entered code is valid, the parameter value is ON. If not, the parameter is set to OFF - + DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + String @@ -94,7 +95,7 @@ DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + trigger @@ -105,7 +106,7 @@ DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + trigger @@ -116,43 +117,43 @@ DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + Switch Motion detection indicator - + DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + Switch Noise detection indicator - + DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + Switch ON when a switch switched on, OFF when a switch switched off - + Number Number of the switch that switched, e.g. 1 to 4 - + String @@ -169,7 +170,7 @@ DateTime Event date and time in CCYY-MM-DDThh:mm:ss format - + Switch diff --git a/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/ipvario221.xml b/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/ipvario221.xml index 96b264e11c5df..94e0d2c1949db 100644 --- a/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/ipvario221.xml +++ b/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/ipvario221.xml @@ -1,5 +1,6 @@ - @@ -8,31 +9,31 @@ Helios IP Vario Door Station / Intercom with Firmware v2.21 - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/ipvario27.xml b/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/ipvario27.xml index a4165995c264f..fc92d32f18a72 100644 --- a/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/ipvario27.xml +++ b/bundles/org.openhab.binding.helios/src/main/resources/ESH-INF/thing/ipvario27.xml @@ -1,5 +1,6 @@ - @@ -8,19 +9,19 @@ Helios IP Vario Door Station / Intercom with Firmware v2.7 - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.heos/.project b/bundles/org.openhab.binding.heos/.project index 320367b85ec22..3eacf5ff15c44 100644 --- a/bundles/org.openhab.binding.heos/.project +++ b/bundles/org.openhab.binding.heos/.project @@ -1,23 +1,23 @@ - - - org.openhab.binding.heos - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - + + + org.openhab.binding.heos + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.heos/README.md b/bundles/org.openhab.binding.heos/README.md index 882ea8b57fb8c..aad53f8f75938 100644 --- a/bundles/org.openhab.binding.heos/README.md +++ b/bundles/org.openhab.binding.heos/README.md @@ -18,21 +18,25 @@ A bridge uses the thing ID "bridge". Player: A generic player is supported via this binding. Currently no differences are made between the players. -A player uses the thing ID "player" +A player uses the Thing ID "player" Groups: The binding supports HEOS groups. -A group uses the thing ID "group" +A group uses the Thing ID "group" ## Discovery -This binding supports full automatic discovery of available players to be used as a bridge, players and groups (both after establishing a connection via a bridge). +This binding supports full automatic discovery of available players to be used as a bridge, players and groups. +You need to add a Bridge device first (which is also auto-discovered by the binding) which can be any HEOS device in your network (preferably which has wired connection). + +__Important!__ Please note that only one bridge is required to establish a connection. Adding a second bridge can cause trouble with the connection. -It is recommended to use the Paper UI or other GUI to setup the system and add all players and groups. + +It is recommended to use the Paper UI to setup the system and add all players and groups. The bridge is discovered through UPnP in the local network. -Once it is added the players and groups are discovered via the bridge and placed within the inbox. +Once it is added the players and groups are discovered via the bridge and placed in the Paper UI Inbox. ## Binding Configuration @@ -46,7 +50,7 @@ The bridge has the following configuration parameter | Parameter | Description | Required | |----------------- |------------------------------------------------------------ | --------- | -| ipAddress | The network address of the bridge | yes | +| ipAddress | The network address of the Bridge | yes | | username | The user name to login to the HEOS account | no | | password | The password for the HEOS account | no | | heartbeat | The time in seconds for the HEOS Heartbeat (default = 60 s) | no | @@ -65,7 +69,7 @@ Player have the following configuration parameter | Parameter | Description | Required | |----------------- |----------------------------------------------------------- | --------- | -| pid | The internal player ID | yes | +| pid | The internal Player ID | yes | For manual configuration a player can be defined as followed: @@ -74,9 +78,9 @@ Thing heos:player:player1 "name" [pid="123456789"] ```` PID behind the heos:player:--- should be changed as required. -It is recommended to use the player PID. +It is recommended to use the Player PID. If the PID isn't known it can be discovered by establishing a Telnet connection (port 1255) to one player and search for available players (Command: heos://player/get_players) within the network. -Another way is to use Paper UI to discover the player via the bridge and get the PID. +Another way is to use Paper UI to discover the Player via the bridge and get the PID. For further details refer to the [HEOS CLI](https://rn.dmglobal.com/euheos/HEOS_CLI_ProtocolSpecification.pdf) specification. ### Group Configuration @@ -87,7 +91,8 @@ Player have the following configuration parameter |----------------- |------------------------------------------------------------------------------------- | --------- | | members | The members of the groups. These are the player IDs. IDs have to be separated by ";" | yes | - +If you use Paper UI to manage your Things (which is the preferred way), you can also set up your group automatically from Paper UI. +Groups will automatically appear in the Inbox if that Group is active. To do this, build your Group from the HEOS app, then the group will appear in the Inbox. ``` Thing heos:group:group1 "name" [members="45345634;35534567"] ``` @@ -126,13 +131,20 @@ Bridge heos:bridge:main "Bridge" [ipAddress="192.168.0.1", username="userName", | PlayUrl | String | Plays a media file located at the URL | | Shuffle | Switch | Switches shuffle ON or OFF | | RepeatMode | String | Defines the repeat mode: Inputs are: "One" , "All" or "Off" | -| Playlists | String | Plays a playlist. Playlists are identified by numbers (starting at 0!). List can be found in the HEOS App | +| Favourites | String | Plays a favourite. The selection options are retrieved automatically | +| Playlists | String | Plays a playlist. The selection options are retrieved automatically | +| Queue | String | Plays from the queue. The queue items are retrieved automatically | +| ClearQueue | Switch | Clear the queue when turned ON | +The `Favourites`, `Playlists`, `Queue` selection options are queried automatically from the HEOS system (if you set up any in the HEOS app). +This means the available options will be visible in a Selection, you don't have to specify them manually. +You can send commands to these channels from rules by sending the name of the selected item (For example: Starting a favorite radio channel from rule). #### Example ``` Player LivingRoom_Control "Control" {channel="heos:player:main:LivingRoom:Control"} +Selection item=LivingRoom_Playlists label="Playlist" icon="music" ``` ### Channels of Thing type 'group' @@ -155,7 +167,16 @@ Player LivingRoom_Control "Control" {channel="heos:player:main:LivingRoom:Contro | PlayUrl | String | Plays a media file located at the URL | | Shuffle | Switch | Switches shuffle ON or OFF | | RepeatMode | String | Defines the repeat mode: Inputs are: "One" ; "All" or "Off" | -| Playlists | String | Plays a playlist. Playlists are identified by numbers (starting at 0!). List can be found in the HEOS App | +| Favourites | String | Plays a favourite. The selection options are retrieved automatically | +| Playlists | String | Plays a playlist. The selection options are retrieved automatically | +| Queue | String | Plays from the queue. The queue items are retrieved automatically | +| ClearQueue | Switch | Clear the queue when turned ON | + +The `Favourites`, `Playlists`, `Queue` selection options are queried automatically from the HEOS system (if you set up any in the HEOS app). +This means the available options will be visible in a Selection, you don't have to specify them manually. +You can send commands to these channels from rules by sending the name of the selected item (For example: Starting a favorite radio channel from rule). + +### Available inputs | Input names | |-------------- | @@ -191,39 +212,21 @@ Player LivingRoom_Control "Control" {channel="heos:player:main:LivingRoom:Contro | tvaudio | | phono | -An current list can be found within the HEOS CLI protocol which can be found [here](https://rn.dmglobal.com/euheos/HEOS_CLI_ProtocolSpecification.pdf). +A current list can be found within the HEOS CLI protocol which can be found [here](https://rn.dmglobal.com/euheos/HEOS_CLI_ProtocolSpecification.pdf). ### Channels of Thing type 'bridge' | Channel ID | Item Type | Description | |---------------------- |----------- |-------------------------------------------------------------------------------------------------------------------------------------------------------- | | Reboot | Switch | Reboot the whole HEOS System. Can be used if you get in trouble with the system | -| BuildGroup | Switch | Is used to define a group. The player which shall be grouped has to be selected first. If Switch is then activated the group is build. | - - +| BuildGroup | Switch | Is used to define a group. The player which shall be grouped has to be selected first. If Switch is then activated the group is built. | For a list of the commands please refer to the [HEOS CLI protocol](https://rn.dmglobal.com/euheos/HEOS_CLI_ProtocolSpecification.pdf). - ## *Dynamic Channels* -Also the bridge, players and groups supports dynamic channels which represent the players of the network and the favorites. -They are added dynamically if a player is found and if favorites are defined within the HEOS Account. -To activate Favorites the system has to be signed in to the HEOS Account. -The player and group channels are only shown on the bridge. - - -### Favorite Channels - -| Channel ID | Item Type | Description | -|------------ |----------- |------------------------------------------------------------------------------------------------------- | -| {mid} | Switch | A channel which represents the favorite. Please check via UI how the correct Channel Type looks like. | - - Example - - ``` - Switch Favorite_1 "Fav 1 [%s]" {channel="heos:bridge:main:s17492"} - ``` +Also the bridge supports dynamic channels which represent the players of the network. +They are added dynamically if a player is found. The player and group channels are only shown on the bridge. ### Player Channels @@ -241,7 +244,7 @@ Example ## Full Example -###demo.things: +### demo.things: ``` Bridge heos:bridge:main "Bridge" [ipAddress="192.168.0.1", username="userName", password="123456"] { @@ -251,7 +254,7 @@ Bridge heos:bridge:main "Bridge" [ipAddress="192.168.0.1", username="userName", } ``` -###demo.items: +### demo.items: ``` Player LivingRoom_Control "Control" {channel="heos:player:main:LivingRoom:Control"} @@ -260,9 +263,10 @@ Dimmer LivingRoom_Volume "Volume" {channel="heos:player:main:LivingRoom:Volume"} String LivingRoom_Title "Title [%s]" {channel="heos:player:main:LivingRoom:Title"} String LivingRoom_Interpret "Interpret [%s]" {channel="heos:player:main:LivingRoom:Artist"} String LivingRoom_Album "Album [%s]" {channel="heos:player:main:LivingRoom:Album"} +String LivingRoom_Playlists {channel="heos:player:main:LivingRoom:Playlists"} ``` -###demo.sitemap +### demo.sitemap ``` Frame label="LivingRoom" { @@ -272,6 +276,7 @@ String LivingRoom_Album "Album [%s]" {channel="heos:player:main:LivingRoom:Album Default item=LivingRoom_Title Default item=LivingRoom_Interpret Default item=LivingRoom_Album + Selection item=LivingRoom_Playlists label="Playlist" icon="music" } ``` @@ -282,12 +287,11 @@ This section gives some detailed explanations how to use the binding. ### Grouping Players Players can be grouped via the binding. -To do so, select the player channels of the players you want to group at the bridge and then use the "Made Group" channel to create the group. -The first player which is selected will be the group leader. -The group GID then is the same as the PID of the group leader. -Therefore changing play pause and some other things at the leading player will also change that at the whole group. -Muting and Volume on the other hand can be changed individually for each player also for the group leader. -If you want to change that for the whole group you have to do it via the group thing. +The easiest way to do this is to use the created Group type Thing. To group them simply use the `Ungroup` channel on the Group. Switching this Switch ON and OFF will group and ungroup that Group. +The first player which is selected will be the Group leader. +Therefore changing play/pause and some other things at any player (which is included in that group) will also change that at the whole group. +Muting and Volume on the other hand can be changed individually for each Player also for the group leader. +If you want to change that for the whole group you have to do it via the Group thing. ### Inputs @@ -385,22 +389,20 @@ Frame label="Heos Group" visibility=[HeosGroup_Status==ONLINE] { } ``` -### Playlists +## Rule Actions -Playlists can be played by sending the number (starts at 0!) to the binding via the playlists channel at the corresponding player or group. -To find the correct number for the playlist, please have a look to the HEOS App and see at which position the playlist you want to play is located. - -#### Example - -Items: +Multiple actions are supported by this binding. In classic rules these are accessible as shown in the example below: ``` -String HeosKitchen_Playlist "Playlists" (gHeos) {channel="heos:player:918797451:Playlists"} - + val actions = getActions("heos","heos:bridge:bridgeId") + if(null === actions) { + logInfo("actions", "Actions not found, check thing ID") + return + } else { + actions.playInputFromPlayer(-3213214, "aux_in_1", 89089081) + } ``` -Sitemap: +### playInputFromPlayer(sourcePlayer, sourceInput, destination) -``` -Switch item=HeosKitchen_Playlists mappings=[0="San Glaser", 1="Classic", 2="Beasty Boys"] -``` +Allows to play a source from a player to another player. diff --git a/bundles/org.openhab.binding.heos/pom.xml b/bundles/org.openhab.binding.heos/pom.xml index 00678a112e79d..e2d8406a61341 100644 --- a/bundles/org.openhab.binding.heos/pom.xml +++ b/bundles/org.openhab.binding.heos/pom.xml @@ -1,15 +1,17 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.heos - openHAB Add-ons :: Bundles :: Heos Binding + openHAB Add-ons :: Bundles :: HEOS Binding diff --git a/bundles/org.openhab.binding.heos/src/main/feature/feature.xml b/bundles/org.openhab.binding.heos/src/main/feature/feature.xml index aa85ee085b7ce..58ce6978c6e15 100644 --- a/bundles/org.openhab.binding.heos/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.heos/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:commons-net/commons-net/3.6 - mvn:org.openhab.addons.bundles/org.openhab.binding.heos/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:commons-net/commons-net/3.6 + mvn:org.openhab.addons.bundles/org.openhab.binding.heos/${project.version} + diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosBridgeHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosBridgeHandler.java deleted file mode 100644 index ccf57b807afb2..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosBridgeHandler.java +++ /dev/null @@ -1,442 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.handler; - -import static org.openhab.binding.heos.HeosBindingConstants.*; -import static org.openhab.binding.heos.internal.resources.HeosConstants.*; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Channel; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; -import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; -import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.internal.HeosChannelHandlerFactory; -import org.openhab.binding.heos.internal.HeosChannelManager; -import org.openhab.binding.heos.internal.api.HeosFacade; -import org.openhab.binding.heos.internal.api.HeosSystem; -import org.openhab.binding.heos.internal.discovery.HeosPlayerDiscoveryListener; -import org.openhab.binding.heos.internal.handler.HeosChannelHandler; -import org.openhab.binding.heos.internal.resources.HeosEventListener; -import org.openhab.binding.heos.internal.resources.HeosGroup; -import org.openhab.binding.heos.internal.resources.HeosPlayer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link HeosSystemHandler} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Johannes Einig - Initial contribution - */ -public class HeosBridgeHandler extends BaseBridgeHandler implements HeosEventListener { - private final Logger logger = LoggerFactory.getLogger(HeosBridgeHandler.class); - - private static final int HEOS_PORT = 1255; - - private List heosPlaylists = new ArrayList<>(); - private List playerDiscoveryList = new ArrayList<>(); - private Map selectedPlayer = new HashMap<>(); - private List selectedPlayerList = new ArrayList<>(); - private HeosChannelManager channelManager = new HeosChannelManager(this); - private HeosChannelHandlerFactory channelHandlerFactory; - - private Map groupHandlerMap = new HashMap<>(); - private Map hashToGidMap = new HashMap<>(); - - private ScheduledFuture poolExecuter; - - private HeosSystem heos; - private HeosFacade api; - - private int heartbeatPulse = 0; - - private boolean isRegisteredForChangeEvents = false; - private boolean bridgeIsConnected = false; - private boolean loggedIn = false; - private boolean connectionDelay = false; - private boolean bridgeHandlerdisposalOngoing = false; - - public HeosBridgeHandler(Bridge thing, HeosSystem heos, HeosFacade api) { - super(thing); - this.heos = heos; - this.api = api; - channelHandlerFactory = new HeosChannelHandlerFactory(this, api); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - if (command instanceof RefreshType) { - return; - } - ChannelTypeUID channelTypeUID = null; // Needed to detect the player channels on the bridge - Channel channel = this.getThing().getChannel(channelUID.getId()); - if (channel != null) { - channelTypeUID = channel.getChannelTypeUID(); - } else { - logger.debug("No valid channel found"); - return; - } - HeosChannelHandler channelHandler = channelHandlerFactory.getChannelHandler(channelUID, channelTypeUID); - if (channelHandler != null) { - channelHandler.handleCommand(command, this, channelUID); - } - } - - @Override - public synchronized void initialize() { - scheduledStartUp(); - } - - private void scheduledStartUp() { - poolExecuter = scheduler.schedule(() -> { - connectBridge(); - bridgeHandlerdisposalOngoing = false; - heos.startEventListener(); - heos.startHeartBeat(heartbeatPulse); - logger.debug("HEOS System heart beat started. Pulse time is {}s", heartbeatPulse); - // gets all available player and groups to ensure that the system knows - // about the conjunction between the groupMemberHash and the GID - triggerPlayerDiscovery(); - if (thing.getConfiguration().containsKey(USERNAME) && thing.getConfiguration().containsKey(PASSWORD)) { - logger.debug("Logging in to HEOS account."); - String name = thing.getConfiguration().get(USERNAME).toString(); - String password = thing.getConfiguration().get(PASSWORD).toString(); - api.logIn(name, password); - updateState(CH_ID_REBOOT, OnOffType.OFF); - updateStatus(ThingStatus.ONLINE); - } else { - logger.debug("Can't log in. Username or password not set."); - updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_PENDING, - " Username or password not set or incorrect. Please Log-In to enable all HEOS features"); - } - }, 5, TimeUnit.SECONDS); - } - - private void connectBridge() { - if (bridgeIsConnected) { - return; - } - loggedIn = false; - - logger.debug("Initialize Bridge '{}' with IP '{}'", thing.getConfiguration().get(NAME), - thing.getConfiguration().get(HOST)); - heartbeatPulse = Integer.valueOf(thing.getConfiguration().get(HEARTBEAT).toString()); - heos.setConnectionIP(thing.getConfiguration().get(HOST).toString()); - heos.setConnectionPort(HEOS_PORT); - bridgeIsConnected = heos.establishConnection(connectionDelay); // the connectionDelay gives the HEOS time to - // recover after a restart - while (!bridgeIsConnected) { - ScheduledFuture reConnect = scheduler.schedule(() -> { - heos.closeConnection(); - bridgeIsConnected = heos.establishConnection(connectionDelay); - logger.debug("Could not initialize connection to HEOS system"); - }, 5, TimeUnit.SECONDS); - while (!reConnect.isDone()) { - } - } - if (!isRegisteredForChangeEvents) { - api.registerforChangeEvents(this); - isRegisteredForChangeEvents = true; - } - connectionDelay = false; // sets default to false again - } - - @Override - public void dispose() { - bridgeHandlerdisposalOngoing = true; // Flag to prevent the handler from being updated during disposal - api.unregisterforChangeEvents(this); - logger.debug("HEOS bridge removed from change notifications"); - isRegisteredForChangeEvents = false; - loggedIn = false; - logger.debug("Dispose bridge '{}'", thing.getConfiguration().get(NAME)); - heos.closeConnection(); - bridgeIsConnected = false; - poolExecuter.cancel(true); // Prevents doubled execution if OpenHab doubles - // initialization of the bridge - } - - /** - * Manages adding the player channel to the bridge - */ - @Override - public synchronized void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { - addPlayerChannel(childThing); - logger.debug("Initialize child handler for: {}.", childThing.getUID().getId()); - } - - /** - * Manages the removal of the player or group channels from the bridge. - */ - @Override - public synchronized void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { - try { - Thread.sleep(500); - } catch (InterruptedException e) { - logger.debug("Interrupted Exception - Message: {}", e.getMessage()); - } - if (bridgeHandlerdisposalOngoing) { // Checks if bridgeHandler is going to disposed (by stopping the binding or - // openHAB for example) and prevents it from being updated which stops the - // disposal process. - return; - } else if (HeosPlayerHandler.class.equals(childHandler.getClass())) { - String channelIdentifyer = "P" + childThing.getUID().getId(); - updateThingChannels(channelManager.removeSingelChannel(channelIdentifyer)); - } else { - String channelIdentifyer = "G" + childThing.getUID().getId(); - updateThingChannels(channelManager.removeSingelChannel(channelIdentifyer)); - // removes the handler from the groupMemberMap that handler is no longer called - // if group is getting online - removeGroupHandlerInformation((HeosGroupHandler) childHandler); - } - logger.debug("Dispose child handler for: {}.", childThing.getUID().getId()); - } - - public void resetPlayerList(ChannelUID channelUID) { - selectedPlayerList.forEach(element -> updateState(element[1], OnOffType.OFF)); - selectedPlayerList.clear(); - updateState(channelUID, OnOffType.OFF); - } - - /** - * Sets the HEOS Thing offline - * - * @param uid the uid of the Thing which shell set offline - */ - public void setGroupOffline(String hashValue) { - groupHandlerMap.forEach((hash, handler) -> { - if (hash.equals(hashValue)) { - handler.setStatusOffline(); - } - }); - } - - /** - * Sets the HEOS Thing offline - * - * @param uid the uid of the Thing which shell set offline - */ - @SuppressWarnings("null") - public void setThingStatusOffline(ThingUID uid) { - if (getThingByUID(uid) != null) { - HeosThingBaseHandler childHandler = (HeosThingBaseHandler) getThingByUID(uid).getHandler(); - childHandler.setStatusOffline(); - } - } - - /** - * Sets the HEOS Thing online. Also updates the link between - * the groubMemberHash value with the actual gid of this group - * - * @param uid the uid of the Thing which shell set online - */ - public void setGroupOnline(HeosGroup group, ThingUID uid) { - hashToGidMap.put(group.getGroupMemberHash(), group.getGid()); - groupHandlerMap.forEach((hash, handler) -> { - if (hash.equals(group.getGroupMemberHash())) { - handler.setStatusOnline(); - addPlayerChannel(handler.getThing()); - } - }); - } - - public void addGroupHandlerInformation(HeosGroupHandler handler) { - groupHandlerMap.put(handler.getGroupMemberHash(), handler); - } - - public void removeGroupHandlerInformation(HeosGroupHandler handler) { - if (groupHandlerMap.containsKey(handler.getGroupMemberHash())) { - groupHandlerMap.remove(handler.getGroupMemberHash()); - } - } - - public String getActualGID(String groupHash) { - return hashToGidMap.get(groupHash); - } - - @Override - public void playerStateChangeEvent(String pid, String event, String command) { - // Do nothing - } - - @Override - public void playerMediaChangeEvent(String pid, Map info) { - // Do nothing - } - - @Override - public void bridgeChangeEvent(String event, String result, String command) { - if (EVENTTYPE_EVENT.equals(event)) { - if (PLAYERS_CHANGED.equals(command)) { - triggerPlayerDiscovery(); - } else if (GROUPS_CHANGED.equals(command)) { - triggerPlayerDiscovery(); - } else if (CONNECTION_LOST.equals(command)) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); - bridgeIsConnected = false; - logger.debug("Heos Bridge OFFLINE"); - } else if (CONNECTION_RESTORED.equals(command)) { - connectionDelay = true; - initialize(); - } - } - if (EVENTTYPE_SYSTEM.equals(event)) { - if (SING_IN.equals(command)) { - if (SUCCESS.equals(result)) { - if (!loggedIn) { - loggedIn = true; - addPlaylists(); - } - } - } else if (USER_CHANGED.equals(command)) { - if (!loggedIn) { - loggedIn = true; - addPlaylists(); - } - } - } - } - - public void addPlaylists() { - if (loggedIn) { - heosPlaylists.clear(); - heosPlaylists = heos.getPlaylists(); - } - } - - /** - * Create a channel for the childThing. Depending if it is a HEOS Group - * or a player an identification prefix is added - * - * @param childThing the thing the channel is created for - */ - @SuppressWarnings("null") - private void addPlayerChannel(Thing childThing) { - String channelIdentifyer = ""; - String pid = ""; - if (HeosPlayerHandler.class.equals(childThing.getHandler().getClass())) { - channelIdentifyer = "P" + childThing.getUID().getId(); - pid = childThing.getConfiguration().get(PROP_PID).toString(); - } else if (HeosGroupHandler.class.equals(childThing.getHandler().getClass())) { - channelIdentifyer = "G" + childThing.getUID().getId(); - HeosGroupHandler handler = (HeosGroupHandler) childThing.getHandler(); - pid = handler.getGroupID(); - } - Map properties = new HashMap<>(2); - String playerName = childThing.getLabel().toString(); - ChannelUID channelUID = new ChannelUID(getThing().getUID(), channelIdentifyer); - properties.put(NAME, playerName); - properties.put(PID, pid); - - Channel channel = ChannelBuilder.create(channelUID, "Switch").withLabel(playerName).withType(CH_TYPE_PLAYER) - .withProperties(properties).build(); - updateThingChannels(channelManager.addSingleChannel(channel)); - } - - private void updateThingChannels(List channelList) { - ThingBuilder thingBuilder = editThing(); - thingBuilder.withChannels(channelList); - updateThing(thingBuilder.build()); - } - - public Map getNewPlayer() { - return heos.getAllPlayer(); - } - - public Map getNewGroups() { - return heos.getGroups(); - } - - public Map getRemovedGroups() { - return heos.getGroupsRemoved(); - } - - public Map getRemovedPlayer() { - return heos.getPlayerRemoved(); - } - - /** - * The list with the currently selected player - * - * @return a HashMap which the currently selected player - */ - public Map getSelectedPlayer() { - selectedPlayer.clear(); - for (int i = 0; i < selectedPlayerList.size(); i++) { - selectedPlayer.put(selectedPlayerList.get(i)[0], selectedPlayerList.get(i)[1]); - } - return selectedPlayer; - } - - public void setSelectedPlayer(Map selectedPlayer) { - this.selectedPlayer = selectedPlayer; - } - - public List getSelectedPlayerList() { - return selectedPlayerList; - } - - public void setSelectedPlayerList(List selectedPlayerList) { - this.selectedPlayerList = selectedPlayerList; - } - - public List getHeosPlaylists() { - return heosPlaylists; - } - - public HeosChannelHandlerFactory getChannelHandlerFactory() { - return channelHandlerFactory; - } - - public void setChannelHandlerFactory(HeosChannelHandlerFactory channelHandlerFactory) { - this.channelHandlerFactory = channelHandlerFactory; - } - - /** - * Register an {@link HeosPlayerDiscoveryListener} to get informed - * if the amount of groups or players have changed - * - * @param listener the implementing class - */ - public void registerPlayerDiscoverListener(HeosPlayerDiscoveryListener listener) { - playerDiscoveryList.add(listener); - } - - private void triggerPlayerDiscovery() { - playerDiscoveryList.forEach(element -> element.playerChanged()); - } - - public boolean isLoggedin() { - return loggedIn; - } - - public boolean isBridgeConnected() { - return bridgeIsConnected; - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosGroupHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosGroupHandler.java deleted file mode 100644 index e3d1ab30ae099..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosGroupHandler.java +++ /dev/null @@ -1,188 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.handler; - -import static org.openhab.binding.heos.HeosBindingConstants.*; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import org.eclipse.smarthome.config.core.Configuration; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.library.types.PlayPauseType; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.types.Command; -import org.openhab.binding.heos.internal.api.HeosFacade; -import org.openhab.binding.heos.internal.api.HeosSystem; -import org.openhab.binding.heos.internal.resources.HeosConstants; -import org.openhab.binding.heos.internal.resources.HeosGroup; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link HeosGroupHandler} handles the actions for a HEOS group. - * Channel commands are received and send to the dedicated channels - * - * @author Johannes Einig - Initial contribution - */ -public class HeosGroupHandler extends HeosThingBaseHandler { - - private final Logger logger = LoggerFactory.getLogger(HeosGroupHandler.class); - - private String gid; - private HeosGroup heosGroup; - - private boolean blockInitialization; - - public HeosGroupHandler(Thing thing, HeosSystem heos, HeosFacade api) { - super(thing, heos, api); - this.heosGroup = new HeosGroup(); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - // The GID is null if there is no group online with the groubMemberHash - // Only commands from the UNGROUP channel are passed through - // to activate the group if it is offline - if (gid != null || CH_ID_UNGROUP.equals(channelUID.getId())) { - super.handleCommand(channelUID, command); - } - } - - /** - * Initialize the HEOS group. Starts an extra thread to avoid blocking - * during start up phase. Gathering all information can take longer - * than 5 seconds which can throw an error within the OpenHab system. - */ - @Override - public synchronized void initialize() { - // Prevents that initialize() is called multiple times if group goes online - blockInitialization = true; - if (thing.getStatus().equals(ThingStatus.ONLINE)) { - return; - } - // Generates the groupMember from the properties. Is needed to generate group after restart of OpenHab. - heosGroup.updateGroupPlayers(thing.getConfiguration().get(PROP_GROUP_MEMBERS).toString()); - api.registerforChangeEvents(this); - scheduledStartUp(); - } - - public String getGroupMemberHash() { - return heosGroup.getGroupMemberHash(); - } - - @Override - public PercentType getNotificationSoundVolume() { - return PercentType.valueOf(heosGroup.getLevel()); - } - - @Override - public void setNotificationSoundVolume(PercentType volume) { - api.volumeGroup(volume.toString(), gid); - } - - @Override - public void playerStateChangeEvent(String pid, String event, String command) { - if (getThing().getStatus().equals(ThingStatus.UNINITIALIZED)) { - logger.debug("Can't Handle Event. Group {} not initialized. Status is: {}", getConfig().get(PROP_NAME), - getThing().getStatus().toString()); - return; - } - if (pid.equals(gid)) { - handleThingStateUpdate(event, command); - } - } - - @Override - public void playerMediaChangeEvent(String pid, Map info) { - if (pid.equals(gid)) { - handleThingMediaUpdate(info); - } - } - - @Override - public void bridgeChangeEvent(String event, String result, String command) { - if (HeosConstants.USER_CHANGED.equals(command)) { - updateThingChannels(channelManager.addFavoriteChannels(heos.getFavorites())); - } - } - - /** - * Sets the status of the HEOS group to OFFLINE. - * Also sets the UNGROUP channel to OFF and the CONTROL - * channel to PAUSE - */ - @Override - public void setStatusOffline() { - api.unregisterforChangeEvents(this); - updateState(CH_ID_UNGROUP, OnOffType.OFF); - updateState(CH_ID_CONTROL, PlayPauseType.PAUSE); - updateStatus(ThingStatus.OFFLINE); - } - - @Override - public void setStatusOnline() { - if (thing.getStatus().equals(ThingStatus.OFFLINE) && !blockInitialization) { - initialize(); - } - } - - public HeosGroup getHeosGroup() { - return heosGroup; - } - - public String getGroupID() { - return gid; - } - - private void updateConfiguration() { - Map prop = new HashMap<>(); - prop.put(PROP_NAME, heosGroup.getName()); - prop.put(PROP_GROUP_MEMBERS, heosGroup.getGroupMembersAsString()); - prop.put(PROP_GROUP_LEADER, heosGroup.getLeader()); - prop.put(PROP_GROUP_HASH, heosGroup.getGroupMemberHash()); - prop.put(PROP_GID, gid); - Configuration conf = editConfiguration(); - conf.setProperties(prop); - updateConfiguration(conf); - } - - private void scheduledStartUp() { - scheduler.schedule(() -> { - initChannelHandlerFactory(); - bridge.addGroupHandlerInformation(this); - // Checks if there is a group online with the same group member hash. - // If not setting the group offline. - id = gid = bridge.getActualGID(heosGroup.getGroupMemberHash()); - if (gid == null) { - blockInitialization = false; - setStatusOffline(); - } else { - heosGroup.setGid(gid); - heosGroup = heos.getGroupState(heosGroup); - heos.addHeosGroupToOldGroupMap(heosGroup.getGroupMemberHash(), heosGroup); - if (bridge.isLoggedin()) { - updateThingChannels(channelManager.addFavoriteChannels(heos.getFavorites())); - } - updateConfiguration(); - updateStatus(ThingStatus.ONLINE); - updateState(CH_ID_UNGROUP, OnOffType.ON); - blockInitialization = false; - } - }, 4, TimeUnit.SECONDS); - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosPlayerHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosPlayerHandler.java deleted file mode 100644 index ba702bbae14fa..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosPlayerHandler.java +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.handler; - -import static org.openhab.binding.heos.HeosBindingConstants.PROP_PID; - -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.types.Command; -import org.openhab.binding.heos.internal.api.HeosFacade; -import org.openhab.binding.heos.internal.api.HeosSystem; -import org.openhab.binding.heos.internal.resources.HeosConstants; -import org.openhab.binding.heos.internal.resources.HeosPlayer; - -/** - * The {@link HeosPlayerHandler} handles the actions for a HEOS player. - * Channel commands are received and send to the dedicated channels - * - * @author Johannes Einig - Initial contribution - */ -public class HeosPlayerHandler extends HeosThingBaseHandler { - - private final String pid; - private HeosPlayer player = new HeosPlayer(); - - public HeosPlayerHandler(Thing thing, HeosSystem heos, HeosFacade api) { - super(thing, heos, api); - pid = thing.getConfiguration().get(PROP_PID).toString(); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - super.handleCommand(channelUID, command); - } - - @Override - public void initialize() { - api.registerforChangeEvents(this); - // Because initialization can take longer a scheduler with an extra thread is created - scheduler.schedule(() -> { - initChannelHandlerFactory(); - player = heos.getPlayerState(pid); - if (!player.isOnline()) { - setStatusOffline(); - bridge.setThingStatusOffline(thing.getUID()); - return; - } - // Adding the favorite channel to the player - if (bridge.isLoggedin()) { - updateThingChannels(channelManager.addFavoriteChannels(heos.getFavorites())); - } - updateStatus(ThingStatus.ONLINE); - }, 3, TimeUnit.SECONDS); - } - - @Override - public PercentType getNotificationSoundVolume() { - return PercentType.valueOf(player.getLevel()); - } - - @Override - public void setNotificationSoundVolume(PercentType volume) { - api.setVolume(volume.toString(), pid); - } - - @Override - public void playerStateChangeEvent(String pid, String event, String command) { - if (this.pid.equals(pid)) { - handleThingStateUpdate(event, command); - } - } - - @Override - public void playerMediaChangeEvent(String pid, Map info) { - if (this.pid.equals(pid)) { - player.updateMediaInfo(info); - handleThingMediaUpdate(info); - } - } - - @Override - public void bridgeChangeEvent(String event, String result, String command) { - if (HeosConstants.USER_CHANGED.equals(command)) { - updateThingChannels(channelManager.addFavoriteChannels(heos.getFavorites())); - } - } - - @Override - public void setStatusOffline() { - api.unregisterforChangeEvents(this); - updateStatus(ThingStatus.OFFLINE); - } - - @Override - public void setStatusOnline() { - this.initialize(); - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosThingBaseHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosThingBaseHandler.java deleted file mode 100644 index 0d4628f09c488..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/handler/HeosThingBaseHandler.java +++ /dev/null @@ -1,273 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.handler; - -import static org.openhab.binding.heos.HeosBindingConstants.*; -//import static org.openhab.binding.heos.internal.resources.HeosConstants.*; -import static org.openhab.binding.heos.internal.resources.HeosConstants.*; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.List; -import java.util.Map; - -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.library.types.PlayPauseType; -import org.eclipse.smarthome.core.library.types.RawType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.Channel; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.ThingStatusInfo; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; -import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; -import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.io.net.http.HttpUtil; -import org.openhab.binding.heos.internal.HeosChannelHandlerFactory; -import org.openhab.binding.heos.internal.HeosChannelManager; -import org.openhab.binding.heos.internal.api.HeosFacade; -import org.openhab.binding.heos.internal.api.HeosSystem; -import org.openhab.binding.heos.internal.handler.HeosChannelHandler; -import org.openhab.binding.heos.internal.resources.HeosEventListener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link HeosThingBaseHandler} class is the base Class all HEOS handler have to extend. - * It provides basic command handling and common needed methods. - * - * @author Johannes Einig - Initial contribution - * - */ -public abstract class HeosThingBaseHandler extends BaseThingHandler implements HeosEventListener { - - private final Logger logger = LoggerFactory.getLogger(HeosThingBaseHandler.class); - - protected String id; - protected HeosSystem heos; - protected HeosFacade api; - protected HeosChannelHandlerFactory channelHandlerFactory; - protected HeosBridgeHandler bridge; - protected HeosChannelManager channelManager = new HeosChannelManager(this); - - public HeosThingBaseHandler(Thing thing, HeosSystem heos, HeosFacade api) { - super(thing); - this.heos = heos; - this.api = api; - setId(); - } - - public abstract void setStatusOffline(); - - public abstract void setStatusOnline(); - - public abstract PercentType getNotificationSoundVolume(); - - public abstract void setNotificationSoundVolume(PercentType volume); - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - ChannelTypeUID channelTypeUID = null; // Needed to detect the favorite channels - Channel channel = this.getThing().getChannel(channelUID.getId()); - if (channel != null) { - channelTypeUID = channel.getChannelTypeUID(); - } else { - logger.debug("No valid channel found"); - return; - } - HeosChannelHandler channelHandler = channelHandlerFactory.getChannelHandler(channelUID, channelTypeUID); - if (channelHandler != null) { - channelHandler.handleCommand(command, id, this, channelUID); - } - } - - @Override - public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { - if (ThingStatus.OFFLINE.equals(bridgeStatusInfo.getStatus())) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); - } else if (ThingStatus.ONLINE.equals(bridgeStatusInfo.getStatus())) { - updateStatus(ThingStatus.ONLINE); - } else if (ThingStatus.UNINITIALIZED.equals(bridgeStatusInfo.getStatus())) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); - } - } - - private void setId() { - if (thing.getConfiguration().containsKey(GID)) { - id = thing.getConfiguration().get(GID).toString(); - } - if (thing.getConfiguration().containsKey(PROP_PID)) { - id = thing.getConfiguration().get(PROP_PID).toString(); - } - } - - protected void updateThingChannels(List channelList) { - ThingBuilder thingBuilder = editThing(); - thingBuilder.withChannels(channelList); - updateThing(thingBuilder.build()); - } - - /** - * Has to be called by the player or group handler to initialize - * {@link HeosChannelHandlerFactory} - */ - @SuppressWarnings("null") - protected void initChannelHandlerFactory() { - if (getBridge() != null) { - bridge = (HeosBridgeHandler) getBridge().getHandler(); - channelHandlerFactory = bridge.getChannelHandlerFactory(); - } else { - logger.warn("No Bridge set within child handler"); - } - } - - /** - * Dispose the handler and unregister the handler - * form Change Events - */ - @Override - public void dispose() { - api.unregisterforChangeEvents(this); - super.dispose(); - } - - /** - * Plays a media file from an external source. Can be - * used for audio sink function - * - * @param urlStr The external URL where the file is located - */ - public void playURL(String urlStr) { - try { - URL url = new URL(urlStr); - api.playURL(id, url); - } catch (MalformedURLException e) { - logger.debug("Command '{}' is not a propper URL. Error: {}", urlStr, e.getMessage()); - } - } - - /** - * Handles the updates send from the HEOS system to - * the binding. To receive updates the handler has - * to register itself via {@link HeosFacade} via the method: - * {@link HeosFacade#registerforChangeEvents(HeosEventListener)} - * - * @param event - * @param command - */ - @SuppressWarnings("null") - protected void handleThingStateUpdate(String event, String command) { - if (event.equals(STATE)) { - switch (command) { - case PLAY: - updateState(CH_ID_CONTROL, PlayPauseType.PLAY); - break; - case PAUSE: - updateState(CH_ID_CONTROL, PlayPauseType.PAUSE); - break; - case STOP: - updateState(CH_ID_CONTROL, PlayPauseType.PAUSE); - break; - } - } - if (event.equals(VOLUME)) { - updateState(CH_ID_VOLUME, PercentType.valueOf(command)); - } - if (event.equals(MUTE)) { - if (command != null) { - switch (command) { - case ON: - updateState(CH_ID_MUTE, OnOffType.ON); - break; - case OFF: - updateState(CH_ID_MUTE, OnOffType.OFF); - break; - } - } - } - if (event.equals(CUR_POS)) { - updateState(CH_ID_CUR_POS, DecimalType.valueOf(command.toString())); - } - if (event.equals(DURATION)) { - updateState(CH_ID_DURATION, DecimalType.valueOf(command.toString())); - } - if (event.equals(SHUFFLE_MODE_CHANGED)) { - if (ON.equals(command)) { - updateState(CH_ID_SHUFFLE_MODE, OnOffType.ON); - } else { - updateState(CH_ID_SHUFFLE_MODE, OnOffType.OFF); - } - } - if (event.equals(REPEAT_MODE_CHANGED)) { - if (REPEAT_ALL.equals(command)) { - updateState(CH_ID_REPEAT_MODE, StringType.valueOf(HEOS_UI_ALL)); - } else if (REPEAT_MODE.equals(command)) { - updateState(CH_ID_REPEAT_MODE, StringType.valueOf(HEOS_UI_ONE)); - } else if (OFF.equals(command)) { - updateState(CH_ID_REPEAT_MODE, StringType.valueOf(HEOS_UI_OFF)); - } - } - } - - protected void handleThingMediaUpdate(Map info) { - for (String key : info.keySet()) { - switch (key) { - case SONG: - updateState(CH_ID_SONG, StringType.valueOf(info.get(key))); - break; - case ARTIST: - updateState(CH_ID_ARTIST, StringType.valueOf(info.get(key))); - break; - case ALBUM: - updateState(CH_ID_ALBUM, StringType.valueOf(info.get(key))); - break; - case IMAGE_URL: - try { - URL url = new URL(info.get(key)); // checks if String is proper URL - RawType cover = HttpUtil.downloadImage(url.toString()); - if (cover != null) { - updateState(CH_ID_COVER, cover); - } - break; - } catch (MalformedURLException e) { - logger.debug("Cover can't be loaded. No propper URL: {}", info.get(key)); - break; - } - case STATION: - updateState(CH_ID_STATION, StringType.valueOf(info.get(key))); - if (info.get(SID).equals(INPUT_SID)) { - // removes the "input/" part before the input name - String inputName = info.get(MID).substring(info.get(MID).indexOf("/") + 1); - updateState(CH_ID_INPUTS, StringType.valueOf(inputName)); - } - break; - case TYPE: - if (INPUT_SID.equals(info.get(SID))) { - updateState(CH_ID_TYPE, StringType.valueOf(info.get(STATION))); - } else { - updateState(CH_ID_TYPE, StringType.valueOf(info.get(key))); - updateState(CH_ID_INPUTS, StringType.valueOf("")); - } - if (!STATION.equals(info.get(key))) { - updateState(CH_ID_STATION, StringType.valueOf("")); - } - break; - } - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/HeosBindingConstants.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosBindingConstants.java similarity index 76% rename from bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/HeosBindingConstants.java rename to bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosBindingConstants.java index 1d12f48c483fe..52fba25ac6c0b 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/HeosBindingConstants.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosBindingConstants.java @@ -10,7 +10,7 @@ * * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.heos; +package org.openhab.binding.heos.internal; import java.util.Collections; import java.util.Set; @@ -40,10 +40,7 @@ public class HeosBindingConstants extends HeosConstants { public static final ThingTypeUID THING_TYPE_GROUP = new ThingTypeUID(BINDING_ID, "group"); // List off all Channel Types - public static final ChannelTypeUID CH_TYPE_PLAYER = new ChannelTypeUID(BINDING_ID, "chPlayer"); - public static final ChannelTypeUID CH_TYPE_FAVORITE = new ChannelTypeUID(BINDING_ID, "chFavorite"); - public static final ChannelTypeUID CH_TYPE_GROUP = new ChannelTypeUID(BINDING_ID, "chGroup"); // List of all Channel IDs public static final String CH_ID_CONTROL = "Control"; @@ -53,12 +50,13 @@ public class HeosBindingConstants extends HeosConstants { public static final String CH_ID_SONG = "Title"; public static final String CH_ID_ARTIST = "Artist"; public static final String CH_ID_ALBUM = "Album"; - public static final String CH_ID_PLAYER = "Player"; public static final String CH_ID_BUILDGROUP = "BuildGroup"; - public static final String CH_ID_DYNGROUPSHAND = "DynamicGroupHandling"; public static final String CH_ID_REBOOT = "Reboot"; public static final String CH_ID_COVER = "Cover"; public static final String CH_ID_PLAYLISTS = "Playlists"; + public static final String CH_ID_FAVORITES = "Favorites"; + public static final String CH_ID_QUEUE = "Queue"; + public static final String CH_ID_CLEAR_QUEUE = "ClearQueue"; public static final String CH_ID_INPUTS = "Inputs"; public static final String CH_ID_CUR_POS = "CurrentPosition"; public static final String CH_ID_DURATION = "Duration"; @@ -66,7 +64,7 @@ public class HeosBindingConstants extends HeosConstants { public static final String CH_ID_RAW_COMMAND = "RawCommand"; public static final String CH_ID_TYPE = "Type"; public static final String CH_ID_PLAY_URL = "PlayUrl"; - public static final String CH_ID_SHUFFLE_MODE = "Shuffel"; + public static final String CH_ID_SHUFFLE_MODE = "Shuffle"; public static final String CH_ID_REPEAT_MODE = "RepeatMode"; // Values for Bridge, Player and Group Properties; @@ -77,29 +75,17 @@ public class HeosBindingConstants extends HeosConstants { public static final String PROP_GROUP_MEMBERS = "members"; public static final String PROP_NAME = "Name"; public static final String PROP_GID = "Group ID"; - public static final String PROP_MODEL = "Model"; public static final String PROP_IP = "IP Address"; - public static final String PROP_NETOWRK = "Connection"; - public static final String PROP_VERSION = "Version"; + public static final String PROP_NETWORK = "Connection"; public static final String PROP_GROUP_HASH = "Members Hash value"; public static final String PROP_GROUP_LEADER = "Group leader"; - public static final String PROP_ROLE = "Role"; - public static final String PROP_BRIDGE = "Heos Bridge"; - public static final String HOST = "ipAddress"; - public static final String PLAYER_TYPE = "model"; public static final String USERNAME = "username"; public static final String PASSWORD = "password"; public static final String HEARTBEAT = "heartbeat"; - public static final String TYPE_BRIDGE = "heosBridge"; - - public static final String PLAYER = "Player"; - public static final String GROUP = "Group"; - - public static final String ONLINE = "ONLINE"; - public static final String OFFLINE = "OFFLINE"; public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( Stream.of(THING_TYPE_BRIDGE, THING_TYPE_GROUP, THING_TYPE_PLAYER).collect(Collectors.toSet())); + public static final int FAILURE_COUNT_LIMIT = 5; } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosChannelHandlerFactory.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosChannelHandlerFactory.java index 3e50764e361a6..4397c06b8ca1f 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosChannelHandlerFactory.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosChannelHandlerFactory.java @@ -12,38 +12,17 @@ */ package org.openhab.binding.heos.internal; -import static org.openhab.binding.heos.HeosBindingConstants.*; +import static org.openhab.binding.heos.internal.HeosBindingConstants.*; import java.util.HashMap; import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; -import org.openhab.binding.heos.internal.handler.HeosChannelHandler; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerAlbum; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerArtist; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerBuildGroup; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerControl; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerCover; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerCurrentPosition; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerDuration; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerFavoriteSelect; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerGrouping; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerInputs; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerMute; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerPlayURL; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerPlayerSelect; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerPlaylist; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerRawCommand; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerReboot; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerRepeatMode; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerShuffleMode; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerStation; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerTitle; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerType; -import org.openhab.binding.heos.internal.handler.HeosChannelHandlerVolume; +import org.openhab.binding.heos.internal.handler.*; +import org.openhab.binding.heos.internal.resources.HeosEventListener; /** * The {@link HeosChannelHandlerFactory} is responsible for creating and returning @@ -51,78 +30,82 @@ * It also stores already created handler for further use. * * @author Johannes Einig - Initial contribution - * */ +@NonNullByDefault public class HeosChannelHandlerFactory { + private final HeosBridgeHandler bridge; + private final HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider; + private final Map handlerStorageMap = new HashMap<>(); - private HeosBridgeHandler bridge; - private HeosFacade api; - private Map handlerStorageMap = new HashMap<>(); - - public HeosChannelHandlerFactory(HeosBridgeHandler bridge, HeosFacade api) { + public HeosChannelHandlerFactory(HeosBridgeHandler bridge, + HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider) { this.bridge = bridge; - this.api = api; + this.heosDynamicStateDescriptionProvider = heosDynamicStateDescriptionProvider; } - public HeosChannelHandler getChannelHandler(ChannelUID channelUID, ChannelTypeUID channelTypeUID) { + public @Nullable HeosChannelHandler getChannelHandler(ChannelUID channelUID, HeosEventListener eventListener, + @Nullable ChannelTypeUID channelTypeUID) { if (handlerStorageMap.containsKey(channelUID)) { return handlerStorageMap.get(channelUID); } else { - HeosChannelHandler createdChannelHandler = createNewChannelHandler(channelUID, channelTypeUID); - handlerStorageMap.put(channelUID, createdChannelHandler); - return createdChannelHandler; + HeosChannelHandler handler = createNewChannelHandler(channelUID, eventListener, channelTypeUID); + if (handler != null) { + handlerStorageMap.put(channelUID, handler); + } + return handler; } } - private HeosChannelHandler createNewChannelHandler(ChannelUID channelUID, ChannelTypeUID channelTypeUID) { + private @Nullable HeosChannelHandler createNewChannelHandler(ChannelUID channelUID, HeosEventListener eventListener, + @Nullable ChannelTypeUID channelTypeUID) { switch (channelUID.getId()) { case CH_ID_CONTROL: - return new HeosChannelHandlerControl(bridge, api); + return new HeosChannelHandlerControl(eventListener, bridge); case CH_ID_VOLUME: - return new HeosChannelHandlerVolume(bridge, api); + return new HeosChannelHandlerVolume(eventListener, bridge); case CH_ID_MUTE: - return new HeosChannelHandlerMute(bridge, api); - case CH_ID_PLAY_URL: - return new HeosChannelHandlerPlayURL(bridge, api); + return new HeosChannelHandlerMute(eventListener, bridge); case CH_ID_INPUTS: - return new HeosChannelHandlerInputs(bridge, api); - case CH_ID_UNGROUP: - return new HeosChannelHandlerGrouping(bridge, api); - case CH_ID_RAW_COMMAND: - return new HeosChannelHandlerRawCommand(bridge, api); - case CH_ID_REBOOT: - return new HeosChannelHandlerReboot(bridge, api); - case CH_ID_BUILDGROUP: - return new HeosChannelHandlerBuildGroup(bridge, api); - case CH_ID_PLAYLISTS: - return new HeosChannelHandlerPlaylist(bridge, api); + return new HeosChannelHandlerInputs(eventListener, bridge); case CH_ID_REPEAT_MODE: - return new HeosChannelHandlerRepeatMode(bridge, api); + return new HeosChannelHandlerRepeatMode(eventListener, bridge); case CH_ID_SHUFFLE_MODE: - return new HeosChannelHandlerShuffleMode(bridge, api); + return new HeosChannelHandlerShuffleMode(eventListener, bridge); case CH_ID_ALBUM: - return new HeosChannelHandlerAlbum(bridge, api); case CH_ID_SONG: - return new HeosChannelHandlerTitle(bridge, api); case CH_ID_ARTIST: - return new HeosChannelHandlerArtist(bridge, api); case CH_ID_COVER: - return new HeosChannelHandlerCover(bridge, api); - case CH_ID_CUR_POS: - return new HeosChannelHandlerCurrentPosition(bridge, api); - case CH_ID_DURATION: - return new HeosChannelHandlerDuration(bridge, api); case CH_ID_TYPE: - return new HeosChannelHandlerType(bridge, api); case CH_ID_STATION: - return new HeosChannelHandlerStation(bridge, api); + return new HeosChannelHandlerNowPlaying(eventListener, bridge); + case CH_ID_QUEUE: + return new HeosChannelHandlerQueue(heosDynamicStateDescriptionProvider, bridge); + case CH_ID_CLEAR_QUEUE: + return new HeosChannelHandlerClearQueue(bridge); + + case CH_ID_PLAY_URL: + return new HeosChannelHandlerPlayURL(bridge); + case CH_ID_UNGROUP: + return new HeosChannelHandlerGrouping(bridge); + case CH_ID_RAW_COMMAND: + return new HeosChannelHandlerRawCommand(eventListener, bridge); + case CH_ID_REBOOT: + return new HeosChannelHandlerReboot(bridge); + case CH_ID_BUILDGROUP: + return new HeosChannelHandlerBuildGroup(channelUID, bridge); + case CH_ID_PLAYLISTS: + return new HeosChannelHandlerPlaylist(heosDynamicStateDescriptionProvider, bridge); + case CH_ID_FAVORITES: + return new HeosChannelHandlerFavorite(heosDynamicStateDescriptionProvider, bridge); + case CH_ID_CUR_POS: + case CH_ID_DURATION: + // nothing to handle, we receive updates automatically + return null; } + if (channelTypeUID != null) { - if (CH_TYPE_FAVORITE.equals(channelTypeUID)) { - return new HeosChannelHandlerFavoriteSelect(bridge, api); - } if (CH_TYPE_PLAYER.equals(channelTypeUID)) { - return new HeosChannelHandlerPlayerSelect(bridge, api); + return new HeosChannelHandlerPlayerSelect(channelUID, bridge); } } return null; diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosChannelManager.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosChannelManager.java index 68bf0efbe7b94..d22f1df145c33 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosChannelManager.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosChannelManager.java @@ -12,140 +12,83 @@ */ package org.openhab.binding.heos.internal; -import static org.openhab.binding.heos.HeosBindingConstants.CH_TYPE_FAVORITE; -import static org.openhab.binding.heos.internal.resources.HeosConstants.*; - import java.util.ArrayList; -import java.util.Iterator; +import java.util.Collections; import java.util.List; -import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; -import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The {@link HeosChannelManager} provides the functions to * add and remove channels from the channel list provided by the thing * The generation of the individual channels has to be done by the thingHandler - * itself. Only for the favorites a function is provided which generates the - * individual channels for each favorite. - * + * itself. * * @author Johannes Einig - Initial contribution */ +@NonNullByDefault public class HeosChannelManager { - private final Logger logger = LoggerFactory.getLogger(HeosChannelManager.class); - - private ThingHandler handler; - - private List channelList = new ArrayList<>(); + private final ThingHandler handler; public HeosChannelManager(ThingHandler handler) { this.handler = handler; } - public List addSingleChannel(Channel channel) { - getChannelsFromThing(); - addChannel(channel); - return channelList; - } - - public List addMultibleChannels(List channels) { - getChannelsFromThing(); - channels.forEach(channel -> addChannel(channel)); - return channelList; + public synchronized List addSingleChannel(Channel channel) { + ChannelWrapper channelList = getChannelsFromThing(); + channelList.removeChannel(channel.getUID()); + channelList.add(channel); + return channelList.get(); } - public List removeSingelChannel(String channelIdentifyer) { - getChannelsFromThing(); - removeChannel(generateChannelUID(channelIdentifyer)); - return channelList; + public synchronized List removeSingleChannel(String channelIdentifier) { + ChannelWrapper channelWrapper = getChannelsFromThing(); + channelWrapper.removeChannel(generateChannelUID(channelIdentifier)); + return channelWrapper.get(); } - public List removeSingleChannel(ChannelUID uid) { - getChannelsFromThing(); - removeChannel(uid); - return channelList; + /* + * Gets the channels from the Thing and makes the channel + * list editable. + */ + private ChannelWrapper getChannelsFromThing() { + return new ChannelWrapper(handler.getThing().getChannels()); } - public List removeMutlibleChannels(List channelIdentifyer) { - getChannelsFromThing(); - channelIdentifyer.forEach(identifyer -> removeChannel(generateChannelUID(identifyer))); - return channelList; + private ChannelUID generateChannelUID(String channelIdentifier) { + return new ChannelUID(handler.getThing().getUID(), channelIdentifier); } - public List removeMultibleChannels(List channelUIDs) { - getChannelsFromThing(); - channelUIDs.forEach(uid -> removeChannel(uid)); - return channelList; - } + /** + * Wrap a channel list + * + * @author Martin van Wingerden - Initial contribution + */ + private static class ChannelWrapper { + private final List channels; - public List removeChannelsByType(ChannelTypeUID channelType) { - getChannelsFromThing(); - Iterator channelIterator = channelList.iterator(); - while (channelIterator.hasNext()) { - if (channelType.equals(channelIterator.next().getChannelTypeUID())) { - channelIterator.remove(); - } + ChannelWrapper(List channels) { + this.channels = new ArrayList<>(channels); } - return channelList; - } - - public List removeAllChannels() { - getChannelsFromThing(); - channelList.clear(); - return channelList; - } - public List addFavoriteChannels(List> favoritesList) { - List channelList = new ArrayList<>(); - favoritesList.forEach(element -> channelList.add(generateFavoriteChannel(element))); - return addMultibleChannels(channelList); - } - - private Channel generateFavoriteChannel(Map properties) { - return ChannelBuilder.create(generateChannelUID(properties.get(MID)), "Switch").withLabel(properties.get(NAME)) - .withType(CH_TYPE_FAVORITE).withProperties(properties).build(); - } - - /* - * Gets the channels from the Thing and makes the channel - * list editable. - */ - private void getChannelsFromThing() { - List channelListFromThing = handler.getThing().getChannels(); - channelList.clear(); - channelList.addAll(channelListFromThing); - } + private void removeChannel(ChannelUID uid) { + List itemsToBeRemoved = channels.stream().filter(Objects::nonNull) + .filter(channel -> uid.equals(channel.getUID())).collect(Collectors.toList()); - private ChannelUID generateChannelUID(String channelIdentifyer) { - return new ChannelUID(handler.getThing().getUID(), channelIdentifyer); - } + channels.removeAll(itemsToBeRemoved); + } - private void removeChannel(ChannelUID uid) { - Channel channelToBeRemoved = channelList.stream().filter(channel -> uid.equals(channel.getUID())).findFirst() - .orElse(null); - if (channelToBeRemoved != null) { - channelList.remove(channelToBeRemoved); + public void add(Channel channel) { + channels.add(channel); } - } - /* - * Function to add an channel to the channel list. - * Checks first if channel already exists. - * If so, updated the channel by removing it first and - * add it again. - */ - private void addChannel(Channel channel) { - // If channel already exists remove it first - removeChannel(channel.getUID()); - // Then add the new/updated channel to the list - channelList.add(channel); - logger.debug("Addding Channel: {}", channel.getLabel()); + public List get() { + return Collections.unmodifiableList(channels); + } } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosHandlerFactory.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosHandlerFactory.java index 8dd0df736e1cb..90d760bf8fcbf 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosHandlerFactory.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/HeosHandlerFactory.java @@ -12,13 +12,15 @@ */ package org.openhab.binding.heos.internal; -import static org.openhab.binding.heos.HeosBindingConstants.*; +import static org.openhab.binding.heos.internal.HeosBindingConstants.*; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.core.audio.AudioHTTPServer; import org.eclipse.smarthome.core.audio.AudioSink; @@ -31,13 +33,13 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.handler.HeosGroupHandler; -import org.openhab.binding.heos.handler.HeosPlayerHandler; import org.openhab.binding.heos.internal.api.HeosAudioSink; -import org.openhab.binding.heos.internal.api.HeosFacade; -import org.openhab.binding.heos.internal.api.HeosSystem; import org.openhab.binding.heos.internal.discovery.HeosPlayerDiscovery; +import org.openhab.binding.heos.internal.handler.HeosBridgeHandler; +import org.openhab.binding.heos.internal.handler.HeosDynamicStateDescriptionProvider; +import org.openhab.binding.heos.internal.handler.HeosGroupHandler; +import org.openhab.binding.heos.internal.handler.HeosPlayerHandler; +import org.openhab.binding.heos.internal.handler.HeosThingBaseHandler; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; @@ -53,19 +55,16 @@ * @author Johannes Einig - Initial contribution */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.heos") +@NonNullByDefault public class HeosHandlerFactory extends BaseThingHandlerFactory { private final Logger logger = LoggerFactory.getLogger(HeosHandlerFactory.class); - private Map> discoveryServiceRegs = new HashMap<>(); + private final Map> discoveryServiceRegs = new HashMap<>(); + private final Map> audioSinkRegistrations = new ConcurrentHashMap<>(); - private HeosSystem heos = new HeosSystem(); - private HeosFacade api = heos.getAPI(); - - private AudioHTTPServer audioHTTPServer; - private Map> audioSinkRegistrations = new ConcurrentHashMap<>(); - private NetworkAddressService networkAddressService; - - private String callbackUrl; + private @NonNullByDefault({}) AudioHTTPServer audioHTTPServer; + private @NonNullByDefault({}) NetworkAddressService networkAddressService; + private @NonNullByDefault({}) HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider; @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -79,11 +78,12 @@ protected void activate(ComponentContext componentContext) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (THING_TYPE_BRIDGE.equals(thingTypeUID)) { - HeosBridgeHandler bridgeHandler = new HeosBridgeHandler((Bridge) thing, heos, api); + HeosBridgeHandler bridgeHandler = new HeosBridgeHandler((Bridge) thing, + heosDynamicStateDescriptionProvider); HeosPlayerDiscovery playerDiscovery = new HeosPlayerDiscovery(bridgeHandler); discoveryServiceRegs.put(bridgeHandler.getThing().getUID(), bundleContext .registerService(DiscoveryService.class.getName(), playerDiscovery, new Hashtable<>())); @@ -92,28 +92,26 @@ protected ThingHandler createHandler(Thing thing) { return bridgeHandler; } if (THING_TYPE_PLAYER.equals(thingTypeUID)) { - HeosPlayerHandler playerHandler = new HeosPlayerHandler(thing, heos, api); - // register the speaker as an audio sink - HeosAudioSink audioSink = new HeosAudioSink(playerHandler, audioHTTPServer, createCallbackUrl()); - @SuppressWarnings("unchecked") - ServiceRegistration reg = (ServiceRegistration) bundleContext - .registerService(AudioSink.class.getName(), audioSink, new Hashtable<>()); - audioSinkRegistrations.put(thing.getUID().toString(), reg); + HeosPlayerHandler playerHandler = new HeosPlayerHandler(thing, heosDynamicStateDescriptionProvider); + registerAudioSink(thing, playerHandler); return playerHandler; } if (THING_TYPE_GROUP.equals(thingTypeUID)) { - HeosGroupHandler groupHandler = new HeosGroupHandler(thing, heos, api); - // register the group as an audio sink - HeosAudioSink audioSink = new HeosAudioSink(groupHandler, audioHTTPServer, createCallbackUrl()); - @SuppressWarnings("unchecked") - ServiceRegistration reg = (ServiceRegistration) bundleContext - .registerService(AudioSink.class.getName(), audioSink, new Hashtable<>()); - audioSinkRegistrations.put(thing.getUID().toString(), reg); + HeosGroupHandler groupHandler = new HeosGroupHandler(thing, heosDynamicStateDescriptionProvider); + registerAudioSink(thing, groupHandler); return groupHandler; } return null; } + private void registerAudioSink(Thing thing, HeosThingBaseHandler thingBaseHandler) { + HeosAudioSink audioSink = new HeosAudioSink(thingBaseHandler, audioHTTPServer, createCallbackUrl()); + @SuppressWarnings("unchecked") + ServiceRegistration reg = (ServiceRegistration) bundleContext + .registerService(AudioSink.class.getName(), audioSink, new Hashtable<>()); + audioSinkRegistrations.put(thing.getUID().toString(), reg); + } + @Override public void unregisterHandler(Thing thing) { if (thing.getThingTypeUID().equals(THING_TYPE_BRIDGE)) { @@ -153,22 +151,27 @@ protected void unsetNetworkAddressService(NetworkAddressService networkAddressSe this.networkAddressService = null; } - private String createCallbackUrl() { - if (callbackUrl != null) { - return callbackUrl; - } else { - final String ipAddress = networkAddressService.getPrimaryIpv4HostAddress(); - if (ipAddress == null) { - logger.warn("No network interface could be found."); - return null; - } - // we do not use SSL as it can cause certificate validation issues. - final int port = HttpServiceUtil.getHttpServicePort(bundleContext); - if (port == -1) { - logger.warn("Cannot find port of the http service."); - return null; - } - return "http://" + ipAddress + ":" + port; + @Reference + protected void setDynamicStateDescriptionProvider(HeosDynamicStateDescriptionProvider provider) { + this.heosDynamicStateDescriptionProvider = provider; + } + + protected void unsetDynamicStateDescriptionProvider(HeosDynamicStateDescriptionProvider provider) { + this.heosDynamicStateDescriptionProvider = null; + } + + private @Nullable String createCallbackUrl() { + final String ipAddress = networkAddressService.getPrimaryIpv4HostAddress(); + if (ipAddress == null) { + logger.warn("No network interface could be found."); + return null; + } + // we do not use SSL as it can cause certificate validation issues. + final int port = HttpServiceUtil.getHttpServicePort(bundleContext); + if (port == -1) { + logger.warn("Cannot find port of the http service."); + return null; } + return "http://" + ipAddress + ":" + port; } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/HeosActions.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/HeosActions.java new file mode 100644 index 0000000000000..9adb5aeb4dbd6 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/action/HeosActions.java @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.action; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.binding.ThingActions; +import org.eclipse.smarthome.core.thing.binding.ThingActionsScope; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotConnectedException; +import org.openhab.binding.heos.internal.handler.HeosBridgeHandler; +import org.openhab.binding.heos.internal.resources.Telnet; +import org.openhab.core.automation.annotation.ActionInput; +import org.openhab.core.automation.annotation.RuleAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The class is responsible to call corresponding + * action on HEOS Handler + * + * @author Martin van Wingerden - Initial contribution + */ +@ThingActionsScope(name = "heos") +@NonNullByDefault +public class HeosActions implements ThingActions { + + private final static Logger logger = LoggerFactory.getLogger(HeosActions.class); + + private @Nullable HeosBridgeHandler handler; + + @Override + public void setThingHandler(@Nullable ThingHandler handler) { + if (handler instanceof HeosBridgeHandler) { + this.handler = (HeosBridgeHandler) handler; + } + } + + @Override + public @Nullable ThingHandler getThingHandler() { + return this.handler; + } + + private @Nullable HeosFacade getConnection() throws HeosNotConnectedException { + if (handler == null) { + return null; + } + + return handler.getApiConnection(); + } + + @RuleAction(label = "Play Input", description = "Play an input from another device") + public void playInputFromPlayer( + @ActionInput(name = "source", label = "Source Player", description = "Player used for input") @Nullable Integer sourcePlayer, + @ActionInput(name = "input", label = "Source Input", description = "Input source used") @Nullable String input, + @ActionInput(name = "destination", label = "Destination Player", description = "Device for audio output") @Nullable Integer destinationPlayer) { + if (sourcePlayer == null || input == null || destinationPlayer == null) { + logger.debug( + "Skipping HEOS playInputFromPlayer due to null value: sourcePlayer: {}, input: {}, destination: {}", + sourcePlayer, input, destinationPlayer); + return; + } + + try { + HeosFacade connection = getConnection(); + + if (connection == null) { + logger.debug("Skipping HEOS playInputFromPlayer because no connection was available"); + return; + } + + connection.playInputSource(destinationPlayer.toString(), sourcePlayer.toString(), input); + } catch (IOException | Telnet.ReadException e) { + logger.warn("Failed to play input source!", e); + } + } + + public static void playInputFromPlayer(@Nullable ThingActions actions, @Nullable Integer sourcePlayer, + @Nullable String input, @Nullable Integer destinationPlayer) { + if (actions instanceof HeosActions) { + ((HeosActions) actions).playInputFromPlayer(sourcePlayer, input, destinationPlayer); + } else { + throw new IllegalArgumentException("Instance is not an HeosActionsService class."); + } + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosAudioSink.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosAudioSink.java index 68f7f9c3f32b7..ed51abca5ed56 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosAudioSink.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosAudioSink.java @@ -12,10 +12,13 @@ */ package org.openhab.binding.heos.internal.api; +import java.io.IOException; import java.util.HashSet; import java.util.Locale; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.audio.AudioFormat; import org.eclipse.smarthome.core.audio.AudioHTTPServer; import org.eclipse.smarthome.core.audio.AudioSink; @@ -27,7 +30,8 @@ import org.eclipse.smarthome.core.audio.utils.AudioStreamUtils; import org.eclipse.smarthome.core.library.types.PercentType; import org.eclipse.smarthome.core.thing.util.ThingHandlerHelper; -import org.openhab.binding.heos.handler.HeosThingBaseHandler; +import org.openhab.binding.heos.internal.handler.HeosThingBaseHandler; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,10 +39,9 @@ * This makes HEOS to serve as an {@link AudioSink}. * * @author Johannes Einig - Initial contribution - * */ +@NonNullByDefault public class HeosAudioSink implements AudioSink { - private final Logger logger = LoggerFactory.getLogger(HeosAudioSink.class); private static final Set SUPPORTED_AUDIO_FORMATS = new HashSet<>(); @@ -53,11 +56,11 @@ public class HeosAudioSink implements AudioSink { SUPPORTED_AUDIO_STREAMS.add(FixedLengthAudioStream.class); } - private AudioHTTPServer audioHTTPServer; - private HeosThingBaseHandler handler; - private String callbackUrl; + private final HeosThingBaseHandler handler; + private final AudioHTTPServer audioHTTPServer; + private @Nullable final String callbackUrl; - public HeosAudioSink(HeosThingBaseHandler handler, AudioHTTPServer audioHTTPServer, String callbackUrl) { + public HeosAudioSink(HeosThingBaseHandler handler, AudioHTTPServer audioHTTPServer, @Nullable String callbackUrl) { this.handler = handler; this.audioHTTPServer = audioHTTPServer; this.callbackUrl = callbackUrl; @@ -69,42 +72,44 @@ public String getId() { } @Override - public String getLabel(Locale locale) { + public @Nullable String getLabel(@Nullable Locale locale) { return handler.getThing().getLabel(); } @Override - public void process(AudioStream audioStream) throws UnsupportedAudioFormatException { - String url = null; - if (audioStream instanceof URLAudioStream) { - // it is an external URL, the speaker can access it itself and play it. - URLAudioStream urlAudioStream = (URLAudioStream) audioStream; - url = urlAudioStream.getURL(); - handler.playURL(url); - } else if (audioStream instanceof FixedLengthAudioStream) { - if (callbackUrl != null) { - // we serve it on our own HTTP server for 30 seconds as HEOS requests the stream several times - String relativeUrl = audioHTTPServer.serve((FixedLengthAudioStream) audioStream, 30).toString(); - url = callbackUrl + relativeUrl; - AudioFormat audioFormat = audioStream.getFormat(); - if (!ThingHandlerHelper.isHandlerInitialized(handler)) { - logger.debug("HEOS speaker '{}' is not initialized - status is {}", handler.getThing().getUID(), - handler.getThing().getStatus()); - } else if (AudioFormat.MP3.isCompatible(audioFormat)) { - handler.playURL(url + AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.MP3_EXTENSION); - } else if (AudioFormat.WAV.isCompatible(audioFormat)) { - handler.playURL(url + AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.WAV_EXTENSION); - } else if (AudioFormat.WAV.isCompatible(audioFormat)) { - handler.playURL(url + AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.AAC_EXTENSION); + public void process(@Nullable AudioStream audioStream) throws UnsupportedAudioFormatException { + try { + if (audioStream instanceof URLAudioStream) { + // it is an external URL, the speaker can access it itself and play it. + URLAudioStream urlAudioStream = (URLAudioStream) audioStream; + handler.playURL(urlAudioStream.getURL()); + } else if (audioStream instanceof FixedLengthAudioStream) { + if (callbackUrl != null) { + // we serve it on our own HTTP server for 30 seconds as HEOS requests the stream several times + String relativeUrl = audioHTTPServer.serve((FixedLengthAudioStream) audioStream, 30); + String url = callbackUrl + relativeUrl + AudioStreamUtils.EXTENSION_SEPARATOR; + AudioFormat audioFormat = audioStream.getFormat(); + if (!ThingHandlerHelper.isHandlerInitialized(handler)) { + logger.debug("HEOS speaker '{}' is not initialized - status is {}", handler.getThing().getUID(), + handler.getThing().getStatus()); + } else if (AudioFormat.MP3.isCompatible(audioFormat)) { + handler.playURL(url + FileAudioStream.MP3_EXTENSION); + } else if (AudioFormat.WAV.isCompatible(audioFormat)) { + handler.playURL(url + FileAudioStream.WAV_EXTENSION); + } else if (AudioFormat.AAC.isCompatible(audioFormat)) { + handler.playURL(url + FileAudioStream.AAC_EXTENSION); + } else { + throw new UnsupportedAudioFormatException("HEOS only supports MP3, WAV and AAC.", audioFormat); + } } else { - throw new UnsupportedAudioFormatException("HEOS only supports MP3 or WAV.", audioFormat); + logger.warn("We do not have any callback url, so HEOS cannot play the audio stream!"); } } else { - logger.warn("We do not have any callback url, so HEOS cannot play the audio stream!"); - return; + throw new UnsupportedAudioFormatException( + "HEOS can only handle FixedLengthAudioStreams & URLAudioStream.", null); } - } else { - throw new UnsupportedAudioFormatException("HEOS can only handle FixedLengthAudioStreams.", null); + } catch (IOException | ReadException e) { + logger.warn("Failed to play audio stream: {}", e.getMessage()); } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosEventController.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosEventController.java index b96af8f1cb69b..85b7de7e17c3f 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosEventController.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosEventController.java @@ -14,9 +14,17 @@ import static org.openhab.binding.heos.internal.resources.HeosConstants.*; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.heos.internal.json.dto.HeosCommunicationAttribute; +import org.openhab.binding.heos.internal.json.dto.HeosEvent; +import org.openhab.binding.heos.internal.json.dto.HeosEventObject; +import org.openhab.binding.heos.internal.json.dto.HeosResponseObject; +import org.openhab.binding.heos.internal.json.payload.Media; import org.openhab.binding.heos.internal.resources.HeosCommands; -import org.openhab.binding.heos.internal.resources.HeosResponseDecoder; import org.openhab.binding.heos.internal.resources.HeosSystemEventListener; +import org.openhab.binding.heos.internal.resources.Telnet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,225 +34,86 @@ * * @author Johannes Einig - Initial contribution */ +@NonNullByDefault public class HeosEventController extends HeosSystemEventListener { private final Logger logger = LoggerFactory.getLogger(HeosEventController.class); - private HeosResponseDecoder heosDecoder; - private HeosSystem system; - private HeosCommands command; - private String eventType; - private String eventCommand; + private final HeosSystem system; - public HeosEventController(HeosResponseDecoder heosDecoder, HeosCommands command, HeosSystem system) { - this.heosDecoder = heosDecoder; + private long lastEventTime; + + public HeosEventController(HeosSystem system) { this.system = system; - this.command = command; + lastEventTime = System.currentTimeMillis(); } - public void handleEvent(int client) { - if (client == 0) { - logger.debug("HEOS send response: {}", heosDecoder.getRawResponseMessage()); - } else if (client == 1) { - logger.debug("HEOS event response: {}", heosDecoder.getRawResponseMessage()); - } - - if (heosDecoder.getSendResult().equals(FAIL)) { - String errorCode = heosDecoder.getErrorCode(); - String errorMessage = heosDecoder.getErrorMessage(); + public void handleEvent(HeosEventObject eventObject) { + HeosEvent command = eventObject.command; + lastEventTime = System.currentTimeMillis(); - logger.debug("HEOS System response failure with error code '{}' and message '{}'", errorCode, errorMessage); - } else { - this.eventType = heosDecoder.getEventType(); - this.eventCommand = heosDecoder.getCommandType(); + logger.debug("Handling event: {}", eventObject); - switch (eventType) { - case EVENTTYPE_EVENT: - eventTypeEvent(); - break; - case EVENTTYPE_PLAYER: - eventTypePlayer(); - break; - case EVENTTYPE_SYSTEM: - eventTypeSystem(); - break; - case EVENTTYPE_BROWSE: - eventTypeBrowse(); - break; - case EVENTTYPE_GROUP: - eventTypeGroup(); - break; - } + if (command == null) { + return; } - } - private void eventTypeEvent() { - switch (eventCommand) { + switch (command) { case PLAYER_NOW_PLAYING_PROGRESS: - playerProgressChanged(); - break; - case PLAYERS_CHANGED: - fireBridgeEvent(EVENTTYPE_EVENT, SUCCESS, eventCommand); - break; - case PLAYER_NOW_PLAYING_CHANGED: - mediaStateChanged(); - break; case PLAYER_STATE_CHANGED: - playerStateChanged(); - break; - case PLAYER_QUEUE_CHANGED: - break; - case SOURCES_CHANGED: - break; case PLAYER_VOLUME_CHANGED: - volumeChanged(); - break; - case GROUPS_CHANGED: - fireBridgeEvent(EVENTTYPE_EVENT, SUCCESS, eventCommand); - break; - case USER_CHANGED: - userChanged(); - break; case SHUFFLE_MODE_CHANGED: - shuffleModeChanged(); - break; case REPEAT_MODE_CHANGED: - repeatModeChanged(); + case PLAYER_PLAYBACK_ERROR: + case GROUP_VOLUME_CHANGED: + case PLAYER_QUEUE_CHANGED: + case SOURCES_CHANGED: + fireStateEvent(eventObject); break; - } - } - private void eventTypePlayer() { - switch (eventCommand) { - case GET_NOW_PLAYING_MEDIA: - getMediaState(); - break; - case GET_PLAYER_INFO: - break; - case GET_PLAY_STATE: - playerStateChanged(); - break; - case GET_VOLUME: - volumeChanged(); - break; - case GET_MUTE: - muteChanged(); - break; - case GET_PLAY_MODE: - playModeChanged(); - break; - case GET_QUEUE: - break; - case SET_PLAY_STATE: - break; - case SET_VOLUME: + case USER_CHANGED: + fireBridgeEvent(EVENT_TYPE_SYSTEM, true, command); break; - } - } - private void eventTypeBrowse() { - switch (eventCommand) { - case GET_MUSIC_SOURCES: - break; - case BROWSE: - break; - } - } + case PLAYER_NOW_PLAYING_CHANGED: + String pid = eventObject.getAttribute(HeosCommunicationAttribute.PLAYER_ID); - private void eventTypeSystem() { - switch (eventCommand) { - case SING_IN: - signIn(); - break; - } - } + if (pid == null) { + logger.debug("HEOS did not mention which player changed, unlikely but ignore"); + break; + } - private void eventTypeGroup() { - switch (eventCommand) { - case GET_VOLUME: - volumeChanged(); - break; - case GET_MUTE: - muteChanged(); + try { + HeosResponseObject mediaResponse = system.send(HeosCommands.getNowPlayingMedia(pid), + Media.class); + Media responseMedia = mediaResponse.payload; + if (responseMedia != null) { + fireMediaEvent(pid, responseMedia); + } + } catch (IOException | Telnet.ReadException e) { + logger.debug("Failed to retrieve current playing media, will try again next time.", e); + } break; - } - } - - private void playerStateChanged() { - String pid = heosDecoder.getPid(); - String event = STATE; - String command = heosDecoder.getPlayState(); - fireStateEvent(pid, event, command); - } - - private void playerProgressChanged() { - String pos = heosDecoder.getPlayerCurrentPosition(); - String duration = heosDecoder.getPlayerDuration(); - String pid = heosDecoder.getPid(); - - int intPosition = Integer.valueOf(pos) / 1000; - int intDuration = Integer.valueOf(duration) / 1000; - - fireStateEvent(pid, CUR_POS, String.valueOf(intPosition)); - fireStateEvent(pid, DURATION, String.valueOf(intDuration)); - } - - private void volumeChanged() { - String pid = heosDecoder.getPid(); - String event = VOLUME; - String command = heosDecoder.getPlayerVolume(); - fireStateEvent(pid, event, command); - event = MUTE; - command = heosDecoder.getPlayerMuteState(); - fireStateEvent(pid, event, command); - } - - private void muteChanged() { - String pid = heosDecoder.getPid(); - String event = MUTE; - String command = heosDecoder.getPlayerMuteState(); - fireStateEvent(pid, event, command); - } - private void playModeChanged() { - shuffleModeChanged(); - repeatModeChanged(); - } - - private void mediaStateChanged() { - String pid = heosDecoder.getPid(); - system.send(command.getNowPlayingMedia(pid)); - fireMediaEvent(pid, heosDecoder.getNowPlayingMedia()); - } - - private void getMediaState() { - String pid = heosDecoder.getPid(); - fireMediaEvent(pid, heosDecoder.getNowPlayingMedia()); - } - - private void signIn() { - if (!heosDecoder.isCommandUnderProgress()) { - fireBridgeEvent(EVENTTYPE_SYSTEM, SUCCESS, SING_IN); + case GROUPS_CHANGED: + case PLAYERS_CHANGED: + fireBridgeEvent(EVENT_TYPE_EVENT, true, command); + break; } } - private void shuffleModeChanged() { - fireStateEvent(heosDecoder.getPid(), SHUFFLE_MODE_CHANGED, heosDecoder.getShuffleMode()); - - } - - private void repeatModeChanged() { - fireStateEvent(heosDecoder.getPid(), REPEAT_MODE_CHANGED, heosDecoder.getRepeateMode()); + public void connectionToSystemLost() { + fireBridgeEvent(EVENT_TYPE_EVENT, false, CONNECTION_LOST); } - private void userChanged() { - fireBridgeEvent(EVENTTYPE_SYSTEM, SUCCESS, USER_CHANGED); + public void eventStreamTimeout() { + fireBridgeEvent(EVENT_TYPE_EVENT, false, EVENT_STREAM_TIMEOUT); } - public void connectionToSystemLost() { - fireBridgeEvent(EVENTTYPE_EVENT, FAIL, CONNECTION_LOST); + public void systemReachable() { + fireBridgeEvent(EVENT_TYPE_EVENT, true, CONNECTION_RESTORED); } - public void connectionToSystemRestored() { - fireBridgeEvent(EVENTTYPE_EVENT, SUCCESS, CONNECTION_RESTORED); + long getLastEventTime() { + return lastEventTime; } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosFacade.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosFacade.java index a1f851718a80c..bd6ceca83f8ab 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosFacade.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosFacade.java @@ -12,10 +12,31 @@ */ package org.openhab.binding.heos.internal.api; -import java.net.URL; +import static org.openhab.binding.heos.internal.resources.HeosConstants.*; -//import org.openhab.binding.heos.internal.resources.HeosConstants; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.jetbrains.annotations.NotNull; +import org.openhab.binding.heos.internal.json.dto.HeosResponseObject; +import org.openhab.binding.heos.internal.json.payload.BrowseResult; +import org.openhab.binding.heos.internal.json.payload.Group; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.json.payload.Player; +import org.openhab.binding.heos.internal.resources.HeosCommands; +import org.openhab.binding.heos.internal.resources.HeosConstants; import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonElement; /** * The {@link HeosFacade} is the interface for handling commands, which are @@ -23,14 +44,76 @@ * * @author Johannes Einig - Initial contribution */ +@NonNullByDefault public class HeosFacade { + private static final int MAX_QUEUE_PAGES = 25; + private final Logger logger = LoggerFactory.getLogger(HeosFacade.class); + + private final HeosSystem heosSystem; + private final HeosEventController eventController; + + public HeosFacade(HeosSystem heosSystem, HeosEventController eventController) { + this.heosSystem = heosSystem; + this.eventController = eventController; + } + + public synchronized List getFavorites() throws IOException, ReadException { + return getBrowseResults(FAVORITE_SID); + } + + public List getInputs() throws IOException, ReadException { + return getBrowseResults(String.valueOf(INPUT_SID)); + } + + public List getPlaylists() throws IOException, ReadException { + return getBrowseResults(PLAYLISTS_SID); + } + + @NotNull + private List getBrowseResults(String sourceIdentifier) throws IOException, ReadException { + HeosResponseObject response = browseSource(sourceIdentifier); + logger.debug("Response: {}", response); + + if (response.payload == null) { + return Collections.emptyList(); + } + logger.debug("Received results: {}", Arrays.asList(response.payload)); + + return Arrays.asList(response.payload); + } + + public List getQueue(String pid) throws IOException, ReadException { + List media = new ArrayList<>(); + for (int page = 0; page < MAX_QUEUE_PAGES; page++) { + HeosResponseObject response = fetchQueue(pid, page); + if (!response.result || response.payload == null) { + break; + } + + media.addAll(Arrays.asList(response.payload)); + + if (response.payload.length < 100) { + break; + } + + if (page == MAX_QUEUE_PAGES - 1) { + logger.info("Currently only a maximum of {} pages is fetched for every queue", MAX_QUEUE_PAGES); + } + } + + return media; + } + + HeosResponseObject fetchQueue(String pid, int page) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getQueue(pid, page * 100, (page + 1) * 100), Media[].class); + } - private HeosSystem controller; - private HeosEventController event; + public HeosResponseObject getPlayerInfo(String pid) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getPlayerInfo(pid), Player.class); + } - public HeosFacade(HeosSystem controller, HeosEventController event) { - this.controller = controller; - this.event = event; + public HeosResponseObject getGroupInfo(String gid) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getGroupInfo(gid), Group.class); } /** @@ -38,8 +121,8 @@ public HeosFacade(HeosSystem controller, HeosEventController event) { * * @param pid The PID of the dedicated player */ - public void pause(String pid) { - controller.send(controller.command().setPlayStatePause(pid)); + public void pause(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setPlayStatePause(pid)); } /** @@ -47,8 +130,8 @@ public void pause(String pid) { * * @param pid The PID of the dedicated player */ - public void play(String pid) { - controller.send(controller.command().setPlayStatePlay(pid)); + public void play(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setPlayStatePlay(pid)); } /** @@ -56,8 +139,8 @@ public void play(String pid) { * * @param pid The PID of the dedicated player */ - public void stop(String pid) { - controller.send(controller.command().setPlayStateStop(pid)); + public void stop(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setPlayStateStop(pid)); } /** @@ -65,8 +148,8 @@ public void stop(String pid) { * * @param pid The PID of the dedicated player */ - public void next(String pid) { - controller.send(controller.command().playNext(pid)); + public void next(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.playNext(pid)); } /** @@ -74,8 +157,8 @@ public void next(String pid) { * * @param pid The PID of the dedicated player */ - public void previous(String pid) { - controller.send(controller.command().playPrevious(pid)); + public void previous(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.playPrevious(pid)); } /** @@ -83,8 +166,8 @@ public void previous(String pid) { * * @param pid The PID of the dedicated player */ - public void mute(String pid) { - controller.send(controller.command().setMuteToggle(pid)); + public void mute(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setMuteToggle(pid)); } /** @@ -92,8 +175,8 @@ public void mute(String pid) { * * @param pid The PID of the dedicated player */ - public void muteON(String pid) { - controller.send(controller.command().setMuteOn(pid)); + public void muteON(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setMuteOn(pid)); } /** @@ -101,28 +184,28 @@ public void muteON(String pid) { * * @param pid The PID of the dedicated player */ - public void muteOFF(String pid) { - controller.send(controller.command().setMuteOff(pid)); + public void muteOFF(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setMuteOff(pid)); } /** * Set the play mode of the player or group * - * @param pid The PID of the dedicated player or group + * @param pid The PID of the dedicated player or group * @param mode The shuffle mode: Allowed commands: on; off */ - public void setShuffleMode(String pid, String mode) { - controller.send(controller.command().setShuffleMode(pid, mode)); + public void setShuffleMode(String pid, String mode) throws IOException, ReadException { + heosSystem.send(HeosCommands.setShuffleMode(pid, mode)); } /** * Sets the repeat mode of the player or group * - * @param pid The ID of the dedicated player or group + * @param pid The ID of the dedicated player or group * @param mode The repeat mode. Allowed commands: on_all; on_one; off */ - public void setRepeatMode(String pid, String mode) { - controller.send(controller.command().setRepeatMode(pid, mode)); + public void setRepeatMode(String pid, String mode) throws IOException, ReadException { + heosSystem.send(HeosCommands.setRepeatMode(pid, mode)); } /** @@ -131,8 +214,8 @@ public void setRepeatMode(String pid, String mode) { * @param vol The volume the player shall be set to (value between 0 -100) * @param pid The ID of the dedicated player or group */ - public void setVolume(String vol, String pid) { - controller.send(controller.command().setVolume(vol, pid)); + public void setVolume(String vol, String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setVolume(vol, pid)); } /** @@ -140,8 +223,8 @@ public void setVolume(String vol, String pid) { * * @param pid The ID of the dedicated player or group */ - public void increaseVolume(String pid) { - controller.send(controller.command().volumeUp(pid)); + public void increaseVolume(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.volumeUp(pid)); } /** @@ -149,8 +232,8 @@ public void increaseVolume(String pid) { * * @param pid The ID of the dedicated player or group */ - public void decreaseVolume(String pid) { - controller.send(controller.command().volumeDown(pid)); + public void decreaseVolume(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.volumeDown(pid)); } /** @@ -158,8 +241,8 @@ public void decreaseVolume(String pid) { * * @param gid The GID of the group */ - public void muteGroup(String gid) { - controller.send(controller.command().setMuteToggle(gid)); + public void muteGroup(String gid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setMuteToggle(gid)); } /** @@ -167,8 +250,8 @@ public void muteGroup(String gid) { * * @param gid The GID of the group */ - public void muteGroupON(String gid) { - controller.send(controller.command().setGroupMuteOn(gid)); + public void muteGroupON(String gid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setGroupMuteOn(gid)); } /** @@ -176,8 +259,8 @@ public void muteGroupON(String gid) { * * @param gid The GID of the group */ - public void muteGroupOFF(String gid) { - controller.send(controller.command().setGroupMuteOff(gid)); + public void muteGroupOFF(String gid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setGroupMuteOff(gid)); } /** @@ -186,26 +269,26 @@ public void muteGroupOFF(String gid) { * @param vol The volume the group shall be set to (value between 0-100) * @param gid The GID of the group */ - public void volumeGroup(String vol, String gid) { - controller.send(controller.command().setGroupVolume(vol, gid)); + public void volumeGroup(String vol, String gid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setGroupVolume(vol, gid)); } /** * Increases the HEOS group volume 1 Step * - * @param pid The ID of the dedicated player or group + * @param gid The ID of the dedicated player or group */ - public void increaseGroupVolume(String gid) { - controller.send(controller.command().setGroupVolumeUp(gid)); + public void increaseGroupVolume(String gid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setGroupVolumeUp(gid)); } /** * Decreases the HEOS group volume 1 Step * - * @param pid The ID of the dedicated player or group + * @param gid The ID of the dedicated player or group */ - public void decreaseGroupVolume(String gid) { - controller.send(controller.command().setGroupVolumeDown(gid)); + public void decreaseGroupVolume(String gid) throws IOException, ReadException { + heosSystem.send(HeosCommands.setGroupVolumeDown(gid)); } /** @@ -213,27 +296,29 @@ public void decreaseGroupVolume(String gid) { * * @param gid The GID of the group */ - public void ungroupGroup(String gid) { + public void ungroupGroup(String gid) throws IOException, ReadException { String[] pid = new String[] { gid }; - controller.send(controller.command().setGroup(pid)); + heosSystem.send(HeosCommands.setGroup(pid)); } /** * Builds a group from single players * * @param pids The single player IDs of the player which shall be grouped + * @return */ - public void groupPlayer(String[] pids) { - controller.send(controller.command().setGroup(pids)); + public boolean groupPlayer(String[] pids) throws IOException, ReadException { + return heosSystem.send(HeosCommands.setGroup(pids)).result; } /** * Browses through a HEOS source. Currently no response * * @param sid The source sid which shall be browsed + * @return */ - public void browseSource(String sid) { - controller.send(controller.command().browseSource(sid)); + public HeosResponseObject browseSource(String sid) throws IOException, ReadException { + return heosSystem.send(HeosCommands.browseSource(sid), BrowseResult[].class); } /** @@ -244,51 +329,58 @@ public void browseSource(String sid) { * @param sid The source ID where the media is located * @param cid The container ID of the media */ - public void addContainerToQueuePlayNow(String pid, String sid, String cid) { - controller.send(controller.command().addContainerToQueuePlayNow(pid, sid, cid)); + public void addContainerToQueuePlayNow(String pid, String sid, String cid) throws IOException, ReadException { + heosSystem.send(HeosCommands.addContainerToQueuePlayNow(pid, sid, cid)); } /** - * Sets the connection parameter if the HOES system and connects to the system + * Reboot the bridge to which the connection is established + */ + public void reboot() throws IOException, ReadException { + heosSystem.send(HeosCommands.rebootSystem()); + } + + /** + * Login in via the bridge to the HEOS account * - * @param ip The IP address of the HEOS player which is used as bridge - * @param port The port the system shall establish the connection + * @param name The username + * @param password The password of the user + * @return */ - public void setHeosConnection(String ip, int port) { - controller.setConnectionIP(ip); - controller.setConnectionPort(port); - controller.establishConnection(false); + public HeosResponseObject logIn(String name, String password) throws IOException, ReadException { + return heosSystem.send(HeosCommands.signIn(name, password)); } /** - * Reboot the bridge to which the connection is established + * Get all the players known by HEOS + * + * @return */ - public void reboot() { - controller.sendWithoutResponse(controller.command().rebootSystem()); + public HeosResponseObject getPlayers() throws IOException, ReadException { + return heosSystem.send(HeosCommands.getPlayers(), Player[].class); } /** - * Login in via the bridge to the HEOS account - * - * @param name The username - * @param password The password of the user + * Get all the groups known by HEOS + * + * @return */ - public void logIn(String name, String password) { - controller.command().setUsernamePwassword(name, password); - controller.send(controller.command().signIn(name, password)); + public HeosResponseObject getGroups() throws IOException, ReadException { + return heosSystem.send(HeosCommands.getGroups(), Group[].class); } /** * Plays a specific station on the HEOS player * - * @param pid The player ID - * @param sid The source ID where the media is located - * @param cid The container ID of the media - * @param mid The media ID of the media + * @param pid The player ID + * @param sid The source ID where the media is located + * @param cid The container ID of the media + * @param mid The media ID of the media * @param name Station name returned by 'browse' command. */ - public void playStation(String pid, String sid, String cid, String mid, String name) { - controller.send(controller.command().playStation(pid, sid, cid, mid, name)); + public void playStream(@Nullable String pid, @Nullable String sid, @Nullable String cid, @Nullable String mid, + @Nullable String name) throws IOException, ReadException { + heosSystem.send(HeosCommands.playStream(pid, sid, cid, mid, name)); } /** @@ -298,8 +390,8 @@ public void playStation(String pid, String sid, String cid, String mid, String n * @param sid The source ID where the media is located * @param mid The media ID of the media */ - public void playStation(String pid, String sid, String mid) { - controller.send(controller.command().playStation(pid, sid, mid)); + public void playStream(String pid, String sid, String mid) throws IOException, ReadException { + heosSystem.send(HeosCommands.playStream(pid, sid, mid)); } /** @@ -309,20 +401,21 @@ public void playStation(String pid, String sid, String mid) { * @param pid * @param input */ - public void playInputSource(String pid, String input) { - controller.send(controller.command().playInputSource(pid, pid, input)); + public void playInputSource(String pid, String input) throws IOException, ReadException { + heosSystem.send(HeosCommands.playInputSource(pid, pid, input)); } /** * Plays a specified input source from another player on the selected player. * Input name as per specified in HEOS CLI Protocol * - * @param des_pid the PID where the source shall be played - * @param source_pid the PID where the source is located. - * @param input the input name + * @param destinationPid the PID where the source shall be played + * @param sourcePid the PID where the source is located. + * @param input the input name */ - public void playInputSource(String des_pid, String source_pid, String input) { - controller.send(controller.command().playInputSource(des_pid, source_pid, input)); + public void playInputSource(String destinationPid, String sourcePid, String input) + throws IOException, ReadException { + heosSystem.send(HeosCommands.playInputSource(destinationPid, sourcePid, input)); } /** @@ -331,19 +424,17 @@ public void playInputSource(String des_pid, String source_pid, String input) { * @param pid the PID where the file shall be played * @param url the complete URL the file is located */ - public void playURL(String pid, URL url) { - controller.send(controller.command().playURL(pid, url.toString())); + public void playURL(String pid, URL url) throws IOException, ReadException { + heosSystem.send(HeosCommands.playURL(pid, url.toString())); } /** - * Gets the information like mid, sid and so on of the - * currently playing media. Response is handled via the - * HeosEventController + * clear the queue * * @param pid The player ID the media is playing on */ - public void getPlayingMediaInfo(String pid) { - controller.send(controller.command().getNowPlayingMedia(pid)); + public void clearQueue(String pid) throws IOException, ReadException { + heosSystem.send(HeosCommands.clearQueue(pid)); } /** @@ -352,8 +443,8 @@ public void getPlayingMediaInfo(String pid) { * @param pid The player ID the media is playing on * @param qid The queue ID of the media. (starts by 1) */ - public void deleteMediaFromQueue(String pid, String qid) { - controller.send(controller.command().deleteQueueItem(pid, qid)); + public void deleteMediaFromQueue(String pid, String qid) throws IOException, ReadException { + heosSystem.send(HeosCommands.deleteQueueItem(pid, qid)); } /** @@ -362,8 +453,8 @@ public void deleteMediaFromQueue(String pid, String qid) { * @param pid The player ID the media shall be played on * @param qid The queue ID of the media. (starts by 1) */ - public void playMediafromQueue(String pid, String qid) { - controller.send(controller.command().playQueueItem(pid, qid)); + public void playMediaFromQueue(String pid, String qid) throws IOException, ReadException { + heosSystem.send(HeosCommands.playQueueItem(pid, qid)); } /** @@ -372,9 +463,10 @@ public void playMediafromQueue(String pid, String qid) { * {@link HeosConstants.PAUSE} or {@link HeosConstants.STOP}. * * @param id The player ID the state shall get for + * @return */ - public void getHeosPlayState(String id) { - controller.send(controller.command().getPlayState(id)); + public HeosResponseObject getPlayState(String id) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getPlayState(id)); } /** @@ -383,9 +475,10 @@ public void getHeosPlayState(String id) { * or {@link HeosConstants.OFF}. * * @param id The player id the mute state shall get for + * @return */ - public void getHeosPlayerMuteState(String id) { - controller.send(controller.command().getMute(id)); + public HeosResponseObject getPlayerMuteState(String id) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getMute(id)); } /** @@ -394,29 +487,10 @@ public void getHeosPlayerMuteState(String id) { * a value between 0 and 100 * * @param id The player id the volume shall get for + * @return */ - public void getHeosPlayerVolume(String id) { - controller.send(controller.command().getVolume(id)); - } - - /** - * Ask for the actual song duration of the player. The result has - * to be handled by the event controller. - * - * @param id The player id the song duration shall get for - */ - public void getHeosPlayerDuration(String id) { - controller.send(controller.command().getPlayState(id)); - } - - /** - * Ask for the actual song position of the player. The result has - * to be handled by the event controller. - * - * @param id The player id the song position shall get for - */ - public void getHeosPlayerCurrentPosition(String id) { - controller.send(controller.command().getPlayState(id)); + public HeosResponseObject getPlayerVolume(String id) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getVolume(id)); } /** @@ -425,79 +499,33 @@ public void getHeosPlayerCurrentPosition(String id) { * {@link HeosConstants.HEOS_REPEAT_ALL} or {@link HeosConstants.HEOS_REPEAT_ONE} * * @param id The player id the shuffle mode shall get for + * @return */ - public void getHeosPlayerShuffleMode(String id) { - controller.send(controller.command().getPlayMode(id)); - } - - public void getHeosPlayerRepeatMode(String id) { - controller.send(controller.command().getPlayMode(id)); - } - - public void getHeosGroupeMuteState(String id) { - controller.send(controller.command().getGroupMute(id)); - } - - public void getHeosGroupVolume(String id) { - controller.send(controller.command().getGroupVolume(id)); - } - - public void getNowPlayingMedia(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); - } - - public void getNowPlayingMediaArtist(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); + public HeosResponseObject getPlayMode(String id) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getPlayMode(id)); } - public void getNowPlayingMediaSong(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); + public HeosResponseObject getGroupMuteState(String id) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getGroupMute(id)); } - public void getNowPlayingMediaAlbum(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); + public HeosResponseObject getGroupVolume(String id) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getGroupVolume(id)); } - public void getNowPlayingMediaImageUrl(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); - } - - public void getNowPlayingMediaImageQid(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); - } - - public void getNowPlayingMediaMid(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); - } - - public void getNowPlayingMediaAlbumID(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); - } - - public void getNowPlayingMediaStation(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); - } - - public void getNowPlayingMediaType(String id) { - controller.send(controller.command().getNowPlayingMedia(id)); + public HeosResponseObject getNowPlayingMedia(String id) throws IOException, ReadException { + return heosSystem.send(HeosCommands.getNowPlayingMedia(id), Media.class); } /** - * - * @param pid The ID of the dedicated player or group - */ - public void setActivePlayer(String pid) { - controller.command().setPlayerID(pid); - } - - /** - * Sends a RAW command to the HESO bridge. The command has to be + * Sends a RAW command to the HEOS bridge. The command has to be * in accordance with the HEOS CLI specification * * @param command to send + * @return */ - public void sendRawCommand(String command) { - controller.send(command); + public HeosResponseObject sendRawCommand(String command) throws IOException, ReadException { + return heosSystem.send(command, JsonElement.class); } /** @@ -505,8 +533,8 @@ public void sendRawCommand(String command) { * * @param listener The HeosEventListener */ - public void registerforChangeEvents(HeosEventListener listener) { - event.addListener(listener); + public void registerForChangeEvents(HeosEventListener listener) { + eventController.addListener(listener); } /** @@ -514,7 +542,15 @@ public void registerforChangeEvents(HeosEventListener listener) { * * @param listener The HeosEventListener */ - public void unregisterforChangeEvents(HeosEventListener listener) { - event.removeListener(listener); + public void unregisterForChangeEvents(HeosEventListener listener) { + eventController.removeListener(listener); + } + + public boolean isConnected() { + return heosSystem.isConnected(); + } + + public void closeConnection() { + heosSystem.closeConnection(); } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosSystem.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosSystem.java index 601024d770b06..648b41ba4ccac 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosSystem.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/api/HeosSystem.java @@ -12,128 +12,70 @@ */ package org.openhab.binding.heos.internal.api; -import static org.openhab.binding.heos.internal.resources.HeosConstants.*; +import static org.openhab.binding.heos.internal.handler.FutureUtil.cancel; +import java.beans.PropertyChangeListener; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -// import org.eclipse.smarthome.core.thing.ThingStatus; -// import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import java.util.concurrent.*; +import java.util.function.Consumer; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.heos.internal.json.HeosJsonParser; +import org.openhab.binding.heos.internal.json.dto.HeosResponseObject; import org.openhab.binding.heos.internal.resources.HeosCommands; -import org.openhab.binding.heos.internal.resources.HeosGroup; -import org.openhab.binding.heos.internal.resources.HeosPlayer; -import org.openhab.binding.heos.internal.resources.HeosResponseDecoder; import org.openhab.binding.heos.internal.resources.HeosSendCommand; import org.openhab.binding.heos.internal.resources.Telnet; import org.openhab.binding.heos.internal.resources.Telnet.ReadException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.gson.JsonSyntaxException; + /** * The {@link HeosSystem} is handling the main commands, which are * sent and received by the HEOS system. * * @author Johannes Einig - Initial contribution */ +@NonNullByDefault public class HeosSystem { private final Logger logger = LoggerFactory.getLogger(HeosSystem.class); - private static final int START_DELAY = 30; - private static final int WAIT_TIME_AFTER_RECONNECT = 15000; + private static final int START_DELAY_SEC = 30; + private static final long LAST_EVENT_THRESHOLD = TimeUnit.HOURS.toMillis(2); - private String connectionIP = ""; - private int connectionPort; + private final ScheduledExecutorService scheduler; + private @Nullable ExecutorService singleThreadExecutor; - private Telnet commandLine; - private Telnet eventLine; - private HeosCommands heosCommand = new HeosCommands(); - private HeosResponseDecoder heosDecoder = new HeosResponseDecoder(); - private HeosEventController eventController = new HeosEventController(heosDecoder, heosCommand, this); - private HeosSendCommand sendCommand = new HeosSendCommand(commandLine, heosDecoder, eventController); + private final HeosEventController eventController = new HeosEventController(this); - private Map playerMapNew = new HashMap<>(); - private Map groupMapNew = new HashMap<>(); - private Map playerMapOld = new HashMap<>(); - private Map groupMapOld = new HashMap<>(); - private Map removedPlayerMap = new HashMap<>(); - private Map removedGroupMap = new HashMap<>(); - private HeosFacade heosApi = new HeosFacade(this, eventController); + private final Telnet eventLine = new Telnet(); + private final HeosSendCommand eventSendCommand = new HeosSendCommand(eventLine); - private ScheduledExecutorService keepAlive; - private KeepAliveRunnable keepAliveRunnable = new KeepAliveRunnable(); + private final Telnet commandLine = new Telnet(); + private final HeosSendCommand sendCommand = new HeosSendCommand(commandLine); - /** - * Method to be used to send a command to the HEOS system. - * - * If a ReadException is detected during reading the response - * to the send command the method tries to send the command - * a second time. - * Method returns true if sending the message and reading the response was - * successful. It returns false if either the client is not connected - * or a failure during reading occurs. - * A response reading failure is returned after a timeout during the - * read command was detected. (catch by a ReadException) - * - * @param command the command to be send - * @return true if sending and reading successful - */ - public synchronized boolean send(String command) { - for (int i = 0; i < 2;) { - logger.debug("Sending Command: {}", command); - try { - if (sendCommand.send(command)) { - return true; - } else { - logger.debug("Could not send message. HEOS bridge is not connected"); - return false; - } - } catch (ReadException e) { - logger.debug("HEOS System read failure during response. message: {}", e.getMessage()); - logger.debug("HEOS failed command: {}", command); - i++; - if (i < 2) { - logger.debug("HEOS System trys to send command again...."); - } else { - logger.debug("Could not send command. Please check the system connection"); - } - } catch (IOException e) { - logger.debug("IO Exception during send HEOS command with message: {}", e.getMessage()); - return false; - } + private final HeosJsonParser parser = new HeosJsonParser(); + private final PropertyChangeListener eventProcessor = evt -> { + String newValue = (String) evt.getNewValue(); + ExecutorService executor = singleThreadExecutor; + if (executor == null) { + logger.debug("No executor available ignoring event: {}", newValue); + return; } - return false; - } - - /** - * This method shall only be used if no response from network - * is expected. Else the read buffer is not cleared - * - * @param command - * @return true if send was successful - */ - public boolean sendWithoutResponse(String command) { - if (sendCommand.sendWithoutResponse(command)) { - return true; - } else { - logger.debug("Could not send message. Client is not connected"); - return false; + try { + executor.submit(() -> eventController.handleEvent(parser.parseEvent(newValue))); + } catch (JsonSyntaxException e) { + logger.debug("Failed processing event JSON", e); } - } + }; - /** - * This method returns a class from type HeosCommands. Within this class all - * possible commands to control the HEOS network are defined. - * - * @return a class with all HEOS Commands - */ - public HeosCommands command() { - return heosCommand; + private @Nullable ScheduledFuture keepAliveJob; + private @Nullable ScheduledFuture reconnectJob; + + public HeosSystem(ScheduledExecutorService scheduler) { + this.scheduler = scheduler; } /** @@ -141,56 +83,32 @@ public HeosCommands command() { * set. The caller has to handle the retry to establish the connection * if the method returns {@code false}. * - * @param connectionDelay if set to true system waits for 10 seconds before connecting to event line + * @param connectionIP + * @param connectionPort + * @param heartbeat * @return {@code true} if connection is established else returns {@code false} */ - public boolean establishConnection(boolean connectionDelay) { - this.commandLine = new Telnet(); - this.eventLine = new Telnet(); - - boolean commandLineConnected = false; - boolean eventLineConnected = false; - - try { - commandLineConnected = commandLine.connect(connectionIP, connectionPort); - } catch (IOException e) { - logger.debug("Exception during connection to bridge with message: {}", e.getMessage()); - logger.debug("Could not connect HEOS command line at IP {} @ port {}", connectionIP, connectionPort); - commandLineConnected = false; - } - if (commandLineConnected) { + public HeosFacade establishConnection(String connectionIP, int connectionPort, int heartbeat) + throws IOException, ReadException { + singleThreadExecutor = Executors.newSingleThreadExecutor(); + if (commandLine.connect(connectionIP, connectionPort)) { logger.debug("HEOS command line connected at IP {} @ port {}", connectionIP, connectionPort); - sendCommand.setTelnetClient(commandLine); - send(command().registerChangeEventOFF()); + send(HeosCommands.registerChangeEventOff()); } - try { - eventLineConnected = eventLine.connect(connectionIP, connectionPort); - } catch (IOException e) { - logger.debug("Exception during connection to bridge with message: {}", e.getMessage()); - logger.debug("Could not connect HEOS event line at IP {} @ port {}", connectionIP, connectionPort); - eventLineConnected = false; - } - if (eventLineConnected) { + if (eventLine.connect(connectionIP, connectionPort)) { logger.debug("HEOS event line connected at IP {} @ port {}", connectionIP, connectionPort); - if (connectionDelay) { - // Allows the HEOS system to find all needed things internally. - // During the first connection after a restart or long sleep of the HEOS system, - // the system needs time to activate all internal processes to provide the information - // to the bridge - try { - Thread.sleep(WAIT_TIME_AFTER_RECONNECT); - } catch (InterruptedException e) { - logger.debug("Thread.sleep interrupt during waiting time for HEOS Network"); - } - } - sendCommand.setTelnetClient(eventLine); - send(command().registerChangeEventOFF()); + eventSendCommand.send(HeosCommands.registerChangeEventOff(), Void.class); } - // Setting back the TelnetClient to the commandLine so that all - // commands are send via the commandLine. - sendCommand.setTelnetClient(commandLine); - return commandLine.isConnected() && eventLine.isConnected(); + + startHeartBeat(heartbeat); + startEventListener(); + + return new HeosFacade(this, eventController); + } + + boolean isConnected() { + return sendCommand.isConnected() && eventSendCommand.isConnected(); } /** @@ -199,302 +117,42 @@ public boolean establishConnection(boolean connectionDelay) { * is lost, the method reconnects to the HEOS system by calling the * {@code establishConnection()} method. If the connection is lost or * reconnect the method fires a bridgeEvent via the {@code HeosEvenController.class} - * - * @see establishConnection() - * @see HeosEvenController.class */ - public void startHeartBeat(int heartbeatPulse) { - keepAlive = Executors.newScheduledThreadPool(1); - keepAlive.scheduleWithFixedDelay(this.keepAliveRunnable, START_DELAY, heartbeatPulse, TimeUnit.SECONDS); + void startHeartBeat(int heartbeatPulse) { + keepAliveJob = scheduler.scheduleWithFixedDelay(new KeepAliveRunnable(), START_DELAY_SEC, heartbeatPulse, + TimeUnit.SECONDS); } - public synchronized void startEventListener() { - logger.debug("HEOS System Event Listener is booting...."); - - if (sendCommand.setTelnetClient(eventLine)) { - send(command().registerChangeEventOn()); - logger.debug("HEOS System Event Listener is starting...."); - eventLine.startInputListener(); - } - - sendCommand.setTelnetClient(commandLine); - logger.debug("HEOS System Event Listener succsessfully started"); + synchronized void startEventListener() throws IOException, ReadException { + logger.debug("HEOS System Event Listener is starting...."); + eventSendCommand.startInputListener(HeosCommands.registerChangeEventOn()); - eventLine.getReadResultListener().addPropertyChangeListener(evt -> { - heosDecoder.getHeosJsonParser().parseResult((String) evt.getNewValue()); - eventController.handleEvent(1); - }); + logger.debug("HEOS System Event Listener successfully started"); + eventLine.getReadResultListener().addPropertyChangeListener(eventProcessor); } - public void closeConnection() { + void closeConnection() { logger.debug("Shutting down HEOS Heart Beat"); - if (keepAlive != null) { - keepAlive.shutdown(); - } - logger.debug("Stopping HEOS event line listener"); - eventLine.stopInputListener(); - if (eventLine.isConnected()) { - logger.debug("HEOS event line is still open closing it...."); - if (eventLine.isConnectionAlive()) { - sendCommand.setTelnetClient(eventLine); - send(command().registerChangeEventOFF()); - try { - Thread.sleep(300); - sendCommand.setTelnetClient(commandLine); - logger.debug("Disconnecting HEOS event line"); - eventLine.disconnect(); - logger.debug("Disconnecting HEOS command line"); - commandLine.disconnect(); - } catch (IOException | InterruptedException e) { - logger.error("Failure during closing connection to HEOS with message: {}", e.getMessage());// - return; - } - } - logger.debug("Connection to HEOS system closed"); - } - } + cancel(keepAliveJob); + cancel(this.reconnectJob, false); - /** - * This method update the current state of the HEOS Player - * like the play state title and so on. This method updates all - * states and shall be used for initialization only. For ongoing - * updates use the eventListener - * - * @param pid Player PID from the player - * @return a HEOS Player with the updated states - */ - public synchronized HeosPlayer getPlayerState(String pid) { - HeosPlayer heosPlayer = new HeosPlayer(); - send(command().getPlayerInfo(pid)); - while (heosDecoder.getSendResult().equals(FAIL)) { - try { - for (int i = 2; i > 0; i--) { - logger.debug("HEOS System waiting for player with PID: '{}' to be available. Open tries: {}", pid, - i); - Thread.sleep(3000); - send(command().getPlayerInfo(pid)); - } - heosPlayer.setOnline(false); - return heosPlayer; - } catch (InterruptedException e) { - logger.debug("Interrupted Exception - Message: {}", e.getMessage()); - } + eventLine.getReadResultListener().removePropertyChangeListener(eventProcessor); + eventSendCommand.stopInputListener(HeosCommands.registerChangeEventOff()); + eventSendCommand.disconnect(); + sendCommand.disconnect(); + @Nullable + ExecutorService executor = this.singleThreadExecutor; + if (executor != null && executor.isShutdown()) { + executor.shutdownNow(); } - heosPlayer.updatePlayerInfo(heosDecoder.getPayloadList().get(0)); - heosPlayer = updatePlayerState(heosPlayer); - heosPlayer.setOnline(true); - return heosPlayer; } - /** - * This method returns a {@code Map} with - * all player found on the network after an connection to the system is - * established via a bridge. - * - * @return a HashMap with all HEOS Player in the network - */ - public synchronized Map getAllPlayer() { - playerMapNew.clear(); - - send(command().getPlayers()); - boolean resultIsEmpty = heosDecoder.getPayloadList().isEmpty(); - - while (resultIsEmpty) { - send(command().getPlayers()); - resultIsEmpty = heosDecoder.getPayloadList().isEmpty(); - logger.debug("HEOS System found no players."); - } - List> playerList = heosDecoder.getPayloadList(); - - for (Map player : playerList) { - HeosPlayer heosPlayer = new HeosPlayer(); - heosPlayer.updatePlayerInfo(player); - playerMapNew.put(heosPlayer.getPid(), heosPlayer); - removedPlayerMap = comparePlayerMaps(playerMapNew, playerMapOld); - playerMapOld.clear(); - playerMapOld.putAll(playerMapNew); - } - return playerMapNew; + HeosResponseObject send(String command) throws IOException, ReadException { + return send(command, Void.class); } - private synchronized HeosPlayer updatePlayerState(HeosPlayer heosPlayer) { - String pid = heosPlayer.getPid(); - send(command().getPlayState(pid)); - heosPlayer.setState(heosDecoder.getPlayState()); - send(command().getMute(pid)); - heosPlayer.setMute(heosDecoder.getPlayerMuteState()); - send(command().getVolume(pid)); - heosPlayer.setLevel(heosDecoder.getPlayerVolume()); - send(command().getNowPlayingMedia(pid)); - heosPlayer.updateMediaInfo(heosDecoder.getNowPlayingMedia()); - send(command().getPlayMode(pid)); - heosPlayer.setShuffle(heosDecoder.getShuffleMode()); - heosPlayer.setRepeatMode(heosDecoder.getRepeateMode()); - return heosPlayer; - } - - /** - * This method searches for all groups which are on the HEOS network - * and returns a {@code Map}. - * Before calling this method a connection via a bridge has to be - * established - * - * @return a HashMap with all HEOS groups - */ - public synchronized Map getGroups() { - groupMapNew.clear(); - removedGroupMap.clear(); - send(command().getGroups()); - if (heosDecoder.payloadListIsEmpty()) { - removedGroupMap = compareGroupMaps(groupMapNew, groupMapOld); - groupMapOld.clear(); - return groupMapNew; - } - List> groupList = heosDecoder.getPayloadList(); - int groupCounter = 0; - - for (Map group : groupList) { - HeosGroup heosGroup = new HeosGroup(); - heosGroup.updateGroupInfo(group); - heosGroup.updateGroupPlayers(heosDecoder.getPlayerList().get(groupCounter)); - logger.debug("Found: Group {} with {} Players", heosGroup.getName(), - heosDecoder.getPlayerList().get(groupCounter).size()); - groupMapNew.put(heosGroup.getGroupMemberHash(), heosGroup); - removedGroupMap = compareGroupMaps(groupMapNew, groupMapOld); - groupMapOld.clear(); // clear the old map so that only the currently available groups are added in the next - // step. - groupMapOld.putAll(groupMapNew); - groupCounter++; - } - return groupMapNew; - } - - /** - * This method update the current state of the HEOS Group - * like the play state title and so on. This method updates all - * states and shall be used for initialization only. For ongoing - * updates use the eventListener - * - * @param gid Group GID from the group - * @return a HEOS group with the updated states - */ - public synchronized HeosGroup getGroupState(HeosGroup heosGroup) { - String gid = heosGroup.getGid(); - send(command().getGroupInfo(gid)); - - // During start up sometimes the system has not collected all information - // and sends a failure. - - while (heosDecoder.getSendResult().equals(FAIL)) { - try { - for (int i = 2; i > 0; i--) { - logger.debug("HEOS System waiting for group with PID: '{}' to be available. Open tries: {}", gid, - i); - Thread.sleep(1500); - send(command().getGroupInfo(gid)); - } - heosGroup.setOnline(false); - return heosGroup; - } catch (InterruptedException e) { - logger.debug("Interrupted Exception - Message: {}", e.getMessage()); - } - } - heosGroup.setOnline(true); - heosGroup.updateGroupInfo(heosDecoder.getPayloadList().get(0)); - heosGroup.updateGroupPlayers((heosDecoder.getPlayerList().get(0))); - send(command().getPlayState(gid)); - heosGroup.setState(heosDecoder.getPlayState()); - send(command().getGroupMute(gid)); - heosGroup.setMute(heosDecoder.getGroupMute()); - send(command().getGroupVolume(gid)); - heosGroup.setLevel(heosDecoder.getGroupVolume()); - send(command().getNowPlayingMedia(gid)); - heosGroup.updateMediaInfo(heosDecoder.getNowPlayingMedia()); - send(command().getPlayMode(gid)); - heosGroup.setShuffle(heosDecoder.getShuffleMode()); - heosGroup.setRepeatMode(heosDecoder.getRepeateMode()); - return heosGroup; - } - - private Map compareGroupMaps(Map mapNew, Map mapOld) { - Map removedItems = new HashMap<>(); - for (String key : mapOld.keySet()) { - if (!mapNew.containsKey(key)) { - removedItems.put(key, mapOld.get(key)); - } - } - return removedItems; - } - - private Map comparePlayerMaps(Map mapNew, Map mapOld) { - Map removedItems = new HashMap<>(); - for (String key : mapOld.keySet()) { - if (!mapNew.containsKey(key)) { - removedItems.put(key, mapOld.get(key)); - } - } - return removedItems; - } - - /** - * Be used to fill the map which contains old Groups at startup - * with existing HEOS groups. - * - * @param map a Map with {@code heosGroup.getNameHash(), heosGroup} - */ - public void addHeosGroupToOldGroupMap(String hashValue, HeosGroup heosGroup) { - groupMapOld.put(hashValue, heosGroup); - } - - public List> getFavorites() { - send(command().browseSource(FAVORIT_SID)); - return heosDecoder.getPayloadList(); - } - - public List getPlaylists() { - List playlistsList = new ArrayList<>(); - send(command().browseSource(PLAYLISTS_SID)); - List> payload = heosDecoder.getPayloadList(); - for (int i = 0; i < payload.size(); i++) { - playlistsList.add(payload.get(i).get(CID)); - } - return playlistsList; - } - - public HeosFacade getAPI() { - return heosApi; - } - - public String getConnectionIP() { - return connectionIP; - } - - public void setConnectionIP(String connectionIP) { - this.connectionIP = connectionIP; - } - - public int getConnectionPort() { - return connectionPort; - } - - public void setConnectionPort(int connectionPort) { - this.connectionPort = connectionPort; - } - - public Map getPlayerMap() { - return playerMapNew; - } - - public Map getGroupMap() { - return groupMapNew; - } - - public Map getGroupsRemoved() { - return removedGroupMap; - } - - public Map getPlayerRemoved() { - return removedPlayerMap; + synchronized HeosResponseObject send(String command, Class clazz) throws IOException, ReadException { + return sendCommand.send(command, clazz); } /** @@ -502,45 +160,64 @@ public Map getPlayerRemoved() { * * @author Johannes Einig */ - public class KeepAliveRunnable implements Runnable { + private class KeepAliveRunnable implements Runnable { + @Override public void run() { try { - if (sendCommand.isConnectionAlive()) { - logger.debug("Sending Heos Heart Beat"); - if (!sendCommand.send(command().heartbeat())) { - logger.debug("Connection to HEOS Network lost!"); - restartConnection(); + if (sendCommand.isHostReachable()) { + long timeSinceLastEvent = System.currentTimeMillis() - eventController.getLastEventTime(); + logger.debug("Time since latest event: {} s", timeSinceLastEvent / 1000); + + if (timeSinceLastEvent > LAST_EVENT_THRESHOLD) { + logger.debug("Events haven't been received for too long"); + resetEventStream(); + return; + } + + logger.debug("Sending HEOS Heart Beat"); + HeosResponseObject response = send(HeosCommands.heartbeat()); + if (response.result) { + return; } - } else { - logger.debug("Connection to HEOS Network lost!"); - restartConnection(); } + logger.debug("Connection to HEOS Network lost!"); + // catches a failure during a heart beat send message if connection was // getting lost between last Heart Beat but Bridge is online again and not - // detected by isConnectionAlive() + // detected by isHostReachable() } catch (ReadException | IOException e) { + logger.debug("Failed at {}", System.currentTimeMillis(), e); logger.debug("Failure during HEOS Heart Beat command with message: {}", e.getMessage()); - restartConnection(); } + restartConnection(); } private void restartConnection() { + reset(a -> eventController.connectionToSystemLost()); + } + + private void resetEventStream() { + reset(a -> eventController.eventStreamTimeout()); + } + + private void reset(Consumer<@Nullable Void> method) { closeConnection(); - eventController.connectionToSystemLost(); - try { - while (!sendCommand.isConnectionAlive()) { - logger.debug("Trying to reconnect to HEOS Network..."); - Thread.sleep(5000); - } - logger.debug("Reconnecting to Bridge with IP {} @ port {}", connectionIP, connectionPort); - Thread.sleep(15000); // Waiting time is needed because System needs some time to start up - } catch (InterruptedException e) { - logger.debug("Failure during restart procedure. Trying again simplified...."); - eventController.connectionToSystemRestored(); + method.accept(null); + + cancel(HeosSystem.this.reconnectJob, false); + reconnectJob = scheduler.scheduleWithFixedDelay(this::reconnect, 1, 5, TimeUnit.SECONDS); + } + + private void reconnect() { + logger.debug("Trying to reconnect to HEOS Network..."); + if (!sendCommand.isHostReachable()) { return; } - eventController.connectionToSystemRestored(); + + cancel(HeosSystem.this.reconnectJob, false); + logger.debug("Reconnecting to Bridge"); + scheduler.schedule(eventController::systemReachable, 15, TimeUnit.SECONDS); } } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/BridgeConfiguration.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/BridgeConfiguration.java new file mode 100644 index 0000000000000..106decbd6a798 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/BridgeConfiguration.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * Configuration wrapper for bridge configuration + * + * @author Martin van Wingerden - Initial Contribution + */ +@NonNullByDefault +public class BridgeConfiguration { + public static final String IP_ADDRESS = "ipAddress"; + + /** + * Network address of the HEOS bridge + */ + public String ipAddress = ""; + + /** + * Username for login to the HEOS account. + */ + public @Nullable String username; + + /** + * Password for login to the HEOS account + */ + public @Nullable String password; + + /** + * The time in seconds for the HEOS Heartbeat (default = 60 s) + */ + public int heartbeat; +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/GroupConfiguration.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/GroupConfiguration.java new file mode 100644 index 0000000000000..061fd8863a308 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/GroupConfiguration.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Configuration wrapper for group configuration + * + * @author Martin van Wingerden - Initial Contribution + */ +@NonNullByDefault +public class GroupConfiguration { + /** + * + */ + public String members = ""; +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/PlayerConfiguration.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/PlayerConfiguration.java new file mode 100644 index 0000000000000..baf1eafa43faa --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/configuration/PlayerConfiguration.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.configuration; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Configuration wrapper for player configuration + * + * @author Martin van Wingerden - Initial Contribution + */ +@NonNullByDefault +public class PlayerConfiguration { + /** + * The Player ID + */ + public String pid = ""; +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosDiscoveryParticipant.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosDiscoveryParticipant.java index 2aa79027b0a59..f8a8d6b778736 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosDiscoveryParticipant.java @@ -12,13 +12,11 @@ */ package org.openhab.binding.heos.internal.discovery; -import static org.openhab.binding.heos.HeosBindingConstants.*; -import static org.openhab.binding.heos.internal.resources.HeosConstants.NAME; +import static org.openhab.binding.heos.internal.HeosBindingConstants.*; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.Optional; import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -26,12 +24,13 @@ import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; import org.eclipse.smarthome.config.discovery.upnp.UpnpDiscoveryParticipant; +import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.jupnp.model.meta.DeviceDetails; -import org.jupnp.model.meta.ManufacturerDetails; import org.jupnp.model.meta.ModelDetails; import org.jupnp.model.meta.RemoteDevice; +import org.openhab.binding.heos.internal.configuration.BridgeConfiguration; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +44,6 @@ @NonNullByDefault @Component(service = UpnpDiscoveryParticipant.class, immediate = true, configurationPid = "discovery.heos") public class HeosDiscoveryParticipant implements UpnpDiscoveryParticipant { - private final Logger logger = LoggerFactory.getLogger(HeosDiscoveryParticipant.class); @Override @@ -57,34 +55,34 @@ public Set getSupportedThingTypeUIDs() { public @Nullable DiscoveryResult createResult(RemoteDevice device) { ThingUID uid = getThingUID(device); if (uid != null) { - Map properties = new HashMap<>(3); - properties.put(HOST, device.getIdentity().getDescriptorURL().getHost()); - properties.put(NAME, device.getDetails().getModelDetails().getModelName()); - properties.put(PROP_ROLE, PROP_BRIDGE); // Used to hide other bridges if one is already used + Map properties = new HashMap<>(); + properties.put(Thing.PROPERTY_VENDOR, device.getDetails().getManufacturerDetails().getManufacturer()); + properties.put(Thing.PROPERTY_MODEL_ID, getModel(device.getDetails().getModelDetails())); + properties.put(Thing.PROPERTY_SERIAL_NUMBER, device.getDetails().getSerialNumber()); + properties.put(BridgeConfiguration.IP_ADDRESS, device.getIdentity().getDescriptorURL().getHost()); + properties.put(PROP_NAME, device.getDetails().getFriendlyName()); DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties) .withLabel(" Bridge - " + device.getDetails().getFriendlyName()) - .withRepresentationProperty("Device").build(); + .withRepresentationProperty(Thing.PROPERTY_VENDOR).build(); logger.debug("Found HEOS device with UID: {}", uid.getAsString()); return result; } return null; } + private String getModel(ModelDetails modelDetails) { + return String.format("%s (%s)", modelDetails.getModelName(), modelDetails.getModelNumber()); + } + @Override public @Nullable ThingUID getThingUID(RemoteDevice device) { - Optional optDevice = Optional.ofNullable(device); - String modelName = optDevice.map(RemoteDevice::getDetails).map(DeviceDetails::getModelDetails) - .map(ModelDetails::getModelName).orElse("UNKNOWN"); - String modelManufacturer = optDevice.map(RemoteDevice::getDetails).map(DeviceDetails::getManufacturerDetails) - .map(ManufacturerDetails::getManufacturer).orElse("UNKNOWN"); - - if (modelManufacturer.equals("Denon")) { - if (modelName.startsWith("HEOS") || modelName.endsWith("H")) { - String deviceType = device.getType().getType(); - if (deviceType.startsWith("ACT") || deviceType.startsWith("Aios")) { - return new ThingUID(THING_TYPE_BRIDGE, - optDevice.get().getIdentity().getUdn().getIdentifierString()); - } + DeviceDetails details = device.getDetails(); + String modelName = details.getModelDetails().getModelName(); + String modelManufacturer = details.getManufacturerDetails().getManufacturer(); + if ("Denon".equals(modelManufacturer) && (modelName.startsWith("HEOS") || modelName.endsWith("H"))) { + String deviceType = device.getType().getType(); + if (deviceType.startsWith("ACT") || deviceType.startsWith("Aios")) { + return new ThingUID(THING_TYPE_BRIDGE, device.getIdentity().getUdn().getIdentifierString()); } } return null; diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosPlayerDiscovery.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosPlayerDiscovery.java index adac78967d6f1..49cb21f9bb8d0 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosPlayerDiscovery.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosPlayerDiscovery.java @@ -12,8 +12,10 @@ */ package org.openhab.binding.heos.internal.discovery; -import static org.openhab.binding.heos.HeosBindingConstants.*; +import static org.openhab.binding.heos.internal.HeosBindingConstants.*; +import static org.openhab.binding.heos.internal.handler.FutureUtil.cancel; +import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -22,14 +24,20 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; -import org.openhab.binding.heos.handler.HeosBridgeHandler; +import org.openhab.binding.heos.internal.handler.HeosBridgeHandler; +import org.openhab.binding.heos.internal.handler.HeosPlayerHandler; +import org.openhab.binding.heos.internal.json.payload.Group; +import org.openhab.binding.heos.internal.json.payload.Player; import org.openhab.binding.heos.internal.resources.HeosGroup; -import org.openhab.binding.heos.internal.resources.HeosPlayer; +import org.openhab.binding.heos.internal.resources.Telnet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,6 +47,7 @@ * * @author Johannes Einig - Initial contribution */ +@NonNullByDefault public class HeosPlayerDiscovery extends AbstractDiscoveryService implements HeosPlayerDiscoveryListener { private final Logger logger = LoggerFactory.getLogger(HeosPlayerDiscovery.class); @@ -46,9 +55,12 @@ public class HeosPlayerDiscovery extends AbstractDiscoveryService implements Heo private static final int INITIAL_DELAY = 5; private static final int SCAN_INTERVAL = 20; - private HeosBridgeHandler bridge; + private final HeosBridgeHandler bridge; - private ScheduledFuture scanningJob; + private Map players = new HashMap<>(); + private Map groups = new HashMap<>(); + + private @Nullable ScheduledFuture scanningJob; public HeosPlayerDiscovery(HeosBridgeHandler bridge) throws IllegalArgumentException { super(SEARCH_TIME); @@ -67,118 +79,137 @@ protected void startScan() { logger.debug("Scan for Players not possible. HEOS Bridge is not connected"); return; } + + scanForPlayers(); + scanForGroups(); + } + + private void scanForPlayers() { logger.debug("Start scan for HEOS Player"); - Map playerMap = new HashMap<>(); - playerMap = bridge.getNewPlayer(); + try { + Map currentPlayers = new HashMap<>(); - if (playerMap == null) { - return; - } else { - logger.debug("Found: {} new Player", playerMap.size()); - ThingUID bridgeUID = bridge.getThing().getUID(); - - for (String playerPID : playerMap.keySet()) { - HeosPlayer player = playerMap.get(playerPID); - ThingUID uid = new ThingUID(THING_TYPE_PLAYER, playerMap.get(playerPID).getPid()); - Map properties = new HashMap<>(); - properties.put(PROP_NAME, player.getName()); - properties.put(PROP_PID, player.getPid()); - properties.put(PROP_MODEL, player.getModel()); - properties.put(PROP_VERSION, player.getVersion()); - properties.put(PROP_NETOWRK, player.getNetwork()); - properties.put(PROP_IP, player.getIp()); - DiscoveryResult result = DiscoveryResultBuilder.create(uid).withLabel(player.getName()) - .withProperties(properties).withBridge(bridgeUID).build(); - thingDiscovered(result); + for (Player player : bridge.getPlayers()) { + currentPlayers.put(player.playerId, player); } + + handleRemovedPlayers(findRemovedEntries(currentPlayers, players)); + handleDiscoveredPlayers(currentPlayers); + + players = currentPlayers; + } catch (IOException | Telnet.ReadException e) { + logger.debug("Failed getting/processing groups", e); } + } + + private void handleDiscoveredPlayers(Map currentPlayers) { + logger.debug("Found: {} player", currentPlayers.size()); + ThingUID bridgeUID = bridge.getThing().getUID(); + + for (Player player : currentPlayers.values()) { + ThingUID uid = new ThingUID(THING_TYPE_PLAYER, String.valueOf(player.playerId)); + Map properties = new HashMap<>(); + HeosPlayerHandler.propertiesFromPlayer(properties, player); + + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withLabel(player.name) + .withProperties(properties).withBridge(bridgeUID) + .withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER).build(); + thingDiscovered(result); + } + } + private void handleRemovedPlayers(Map removedPlayers) { + for (Player player : removedPlayers.values()) { + // The same as above! + ThingUID uid = new ThingUID(THING_TYPE_PLAYER, String.valueOf(player.playerId)); + logger.debug("Removed HEOS Player: {} ", uid); + thingRemoved(uid); + } + } + + private void scanForGroups() { logger.debug("Start scan for HEOS Groups"); - Map groupMap = new HashMap<>(); + try { + HashMap currentGroups = new HashMap<>(); + + for (Group group : bridge.getGroups()) { + logger.debug("Found: Group {} with {} Players", group.name, group.players.size()); + currentGroups.put(HeosGroup.calculateGroupMemberHash(group), group); + } + + handleRemovedGroups(findRemovedEntries(currentGroups, groups)); + handleDiscoveredGroups(currentGroups); - groupMap = bridge.getNewGroups(); + groups = currentGroups; + } catch (IOException | Telnet.ReadException e) { + logger.debug("Failed getting/processing groups", e); + } + } - if (groupMap == null) { + private void handleDiscoveredGroups(HashMap currentGroups) { + if (currentGroups.isEmpty()) { + logger.debug("No HEOS Groups found"); return; - } else { - if (!groupMap.isEmpty()) { - logger.debug("Found: {} new Groups", groupMap.size()); - ThingUID bridgeUID = bridge.getThing().getUID(); - - for (String groupGID : groupMap.keySet()) { - HeosGroup group = groupMap.get(groupGID); - String groupMemberHash = group.getGroupMemberHash(); - // Using an unsigned hashCode from the group members to identify - // the group and generates the Thing UID. - // This allows identifying the group even if the sorting within the group has changed - ThingUID uid = new ThingUID(THING_TYPE_GROUP, groupMemberHash); - Map properties = new HashMap<>(); - properties.put(PROP_NAME, group.getName()); - properties.put(PROP_GID, group.getGid()); - properties.put(PROP_GROUP_MEMBERS, group.getGroupMembersAsString()); - properties.put(PROP_GROUP_LEADER, group.getLeader()); - properties.put(PROP_GROUP_HASH, group.getGroupMemberHash()); - DiscoveryResult result = DiscoveryResultBuilder.create(uid).withLabel(group.getName()) - .withProperties(properties).withBridge(bridgeUID).build(); - thingDiscovered(result); - bridge.setGroupOnline(group, uid); - } - } else { - logger.debug("No HEOS Groups found"); - } } - removedPlayers(); - removedGroups(); + logger.debug("Found: {} new Groups", currentGroups.size()); + ThingUID bridgeUID = bridge.getThing().getUID(); + + for (Map.Entry entry : currentGroups.entrySet()) { + Group group = entry.getValue(); + String groupMemberHash = entry.getKey(); + // Using an unsigned hashCode from the group members to identify + // the group and generates the Thing UID. + // This allows identifying the group even if the sorting within the group has changed + ThingUID uid = new ThingUID(THING_TYPE_GROUP, groupMemberHash); + Map properties = new HashMap<>(); + properties.put(PROP_NAME, group.name); + properties.put(PROP_GID, group.id); + String groupMembers = group.players.stream().map(p -> p.id).collect(Collectors.joining(";")); + properties.put(PROP_GROUP_MEMBERS, groupMembers); + properties.put(PROP_GROUP_LEADER, group.players.get(0).id); + properties.put(PROP_GROUP_HASH, groupMemberHash); + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withLabel(group.name).withProperties(properties) + .withBridge(bridgeUID).withRepresentationProperty(PROP_GROUP_HASH).build(); + thingDiscovered(result); + bridge.setGroupOnline(groupMemberHash, group.id); + } } - // Informs the system of removed groups by using the thingRemoved method. - private void removedGroups() { - Map removedGroupMap = new HashMap<>(); - removedGroupMap = bridge.getRemovedGroups(); - if (!removedGroupMap.isEmpty()) { - for (String key : removedGroupMap.keySet()) { - // The same as above! - ThingUID uid = new ThingUID(THING_TYPE_GROUP, removedGroupMap.get(key).getGroupMemberHash()); - logger.debug("Removed HEOS Group: {}", uid); - thingRemoved(uid); - bridge.setGroupOffline(removedGroupMap.get(key).getGroupMemberHash()); - } + private void handleRemovedGroups(Map removedGroups) { + for (String groupMemberHash : removedGroups.keySet()) { + // The same as above! + ThingUID uid = new ThingUID(THING_TYPE_GROUP, groupMemberHash); + logger.debug("Removed HEOS Group: {}", uid); + thingRemoved(uid); + bridge.setGroupOffline(groupMemberHash); } } - // Informs the system of removed players by using the thingRemoved method. - private void removedPlayers() { - Map removedPlayerMap = new HashMap<>(); - removedPlayerMap = bridge.getRemovedPlayer(); - if (!removedPlayerMap.isEmpty()) { - for (String key : removedPlayerMap.keySet()) { - // The same as above! - ThingUID uid = new ThingUID(THING_TYPE_PLAYER, removedPlayerMap.get(key).getPid()); - logger.debug("Removed HEOS Player: {} ", uid); - thingRemoved(uid); + private Map findRemovedEntries(Map mapNew, Map mapOld) { + Map removedItems = new HashMap<>(); + for (K key : mapOld.keySet()) { + if (!mapNew.containsKey(key)) { + removedItems.put(key, mapOld.get(key)); } } + return removedItems; } @Override protected void startBackgroundDiscovery() { - logger.trace("Start HEOS Player background discovery"); - if (scanningJob == null || scanningJob.isCancelled()) { + ScheduledFuture runningScanningJob = this.scanningJob; + if (runningScanningJob == null || runningScanningJob.isCancelled()) { this.scanningJob = scheduler.scheduleWithFixedDelay(this::startScan, INITIAL_DELAY, SCAN_INTERVAL, TimeUnit.SECONDS); } - logger.trace("scanningJob active"); } @Override protected void stopBackgroundDiscovery() { logger.debug("Stop HEOS Player background discovery"); - if (scanningJob != null && !scanningJob.isCancelled()) { - scanningJob.cancel(true); - scanningJob = null; - } + cancel(scanningJob); } @Override @@ -187,7 +218,7 @@ protected synchronized void stopScan() { removeOlderResults(getTimestampOfLastScan()); } - public void scanForNewPlayers() { + private void scanForNewPlayers() { removeOlderResults(getTimestampOfLastScan()); startScan(); } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosPlayerDiscoveryListener.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosPlayerDiscoveryListener.java index 096dcdabfb7f9..0108110cb2b1a 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosPlayerDiscoveryListener.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/discovery/HeosPlayerDiscoveryListener.java @@ -12,7 +12,8 @@ */ package org.openhab.binding.heos.internal.discovery; -//import org.openhab.binding.heos.handler.HeosBridgeHandler; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.heos.internal.handler.HeosBridgeHandler; /** * The {@link HeosPlayerDiscoveryListener } is an Event Listener @@ -22,6 +23,7 @@ * * @author Johannes Einig - Initial contribution */ +@NonNullByDefault public interface HeosPlayerDiscoveryListener { void playerChanged(); } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosFunctionalException.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosFunctionalException.java new file mode 100644 index 0000000000000..9a2e3e67c1997 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosFunctionalException.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.exception; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.heos.internal.json.dto.HeosErrorCode; + +/** + * Exception to inform the caller that there is functional error reported by the HEOS system + * + * @author Martin van Wingerden - Initial contribution + */ +@NonNullByDefault +public class HeosFunctionalException extends IOException { + private final HeosErrorCode code; + + public HeosFunctionalException(HeosErrorCode code) { + this.code = code; + } + + public HeosErrorCode getCode() { + return code; + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosNotConnectedException.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosNotConnectedException.java new file mode 100644 index 0000000000000..806f2b10ca172 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosNotConnectedException.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.exception; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Exception to inform the caller that there is no connection to the HEOS system (yet) + * + * @author Martin van Wingerden - Initial contribution + */ +@NonNullByDefault +public class HeosNotConnectedException extends IOException { + public HeosNotConnectedException() { + super("HEOS not connected"); + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosNotFoundException.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosNotFoundException.java new file mode 100644 index 0000000000000..d5a3497b5be3c --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/exception/HeosNotFoundException.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.exception; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Exception to inform the caller that there is no connection to the HEOS system (yet) + * + * @author Martin van Wingerden - Initial contribution + */ +@NonNullByDefault +public class HeosNotFoundException extends IOException { + public HeosNotFoundException() { + super("HEOS not found"); + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/BaseHeosChannelHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/BaseHeosChannelHandler.java new file mode 100644 index 0000000000000..a15bed95ccc79 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/BaseHeosChannelHandler.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotConnectedException; + +/** + * Base class for the channel handlers + * + * @author Martin van Wingerden - Initial contribution + */ +@NonNullByDefault +public abstract class BaseHeosChannelHandler implements HeosChannelHandler { + final HeosBridgeHandler bridge; + + public BaseHeosChannelHandler(HeosBridgeHandler bridge) { + this.bridge = bridge; + } + + protected HeosFacade getApi() throws HeosNotConnectedException { + return bridge.getApiConnection(); + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/FutureUtil.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/FutureUtil.java new file mode 100644 index 0000000000000..7737d7ccc9bc0 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/FutureUtil.java @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import java.util.concurrent.Future; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * Instead of continously rewriting the termination of future a small util method was added + * + * @author Martin van Wingerden - Initial Contribution + */ +@NonNullByDefault +public class FutureUtil { + private FutureUtil() { + // this is a util no instances should be created + } + + /** + * Cancel the future + * + * - when it is not null + * - and it is not already cancelled + * + * interrupt if still/already running + * + * @param future nullable future to be cancelled + */ + public static void cancel(@Nullable Future future) { + cancel(future, true); + } + + /** + * Cancel the future + * + * - when it is not null + * - and it is not already cancelled + * + * @param future nullable future to be cancelled + * @param interruptIfRunning choose whether to interrupt a running future + */ + public static void cancel(@Nullable Future future, boolean interruptIfRunning) { + if (future != null && !future.isCancelled()) { + future.cancel(interruptIfRunning); + } + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosBridgeHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosBridgeHandler.java new file mode 100644 index 0000000000000..a58907acda104 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosBridgeHandler.java @@ -0,0 +1,518 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import static org.eclipse.smarthome.core.thing.ThingStatus.OFFLINE; +import static org.eclipse.smarthome.core.thing.ThingStatus.ONLINE; +import static org.openhab.binding.heos.internal.HeosBindingConstants.*; +import static org.openhab.binding.heos.internal.handler.FutureUtil.cancel; + +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; +import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; +import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.heos.internal.HeosChannelHandlerFactory; +import org.openhab.binding.heos.internal.HeosChannelManager; +import org.openhab.binding.heos.internal.action.HeosActions; +import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.api.HeosSystem; +import org.openhab.binding.heos.internal.configuration.BridgeConfiguration; +import org.openhab.binding.heos.internal.discovery.HeosPlayerDiscoveryListener; +import org.openhab.binding.heos.internal.exception.HeosNotConnectedException; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.json.dto.HeosError; +import org.openhab.binding.heos.internal.json.dto.HeosEvent; +import org.openhab.binding.heos.internal.json.dto.HeosEventObject; +import org.openhab.binding.heos.internal.json.dto.HeosResponseObject; +import org.openhab.binding.heos.internal.json.payload.Group; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.json.payload.Player; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link HeosBridgeHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Johannes Einig - Initial contribution + */ +@NonNullByDefault +public class HeosBridgeHandler extends BaseBridgeHandler implements HeosEventListener { + private final Logger logger = LoggerFactory.getLogger(HeosBridgeHandler.class); + + private static final int HEOS_PORT = 1255; + + private final List playerDiscoveryList = new CopyOnWriteArrayList<>(); + private final HeosChannelManager channelManager = new HeosChannelManager(this); + private final HeosChannelHandlerFactory channelHandlerFactory; + + private final Map groupHandlerMap = new ConcurrentHashMap<>(); + private final Map hashToGidMap = new ConcurrentHashMap<>(); + + private List selectedPlayerList = new CopyOnWriteArrayList<>(); + + private @Nullable Future startupFuture; + private final List> childHandlerInitializedFutures = new CopyOnWriteArrayList<>(); + + private final HeosSystem heosSystem; + private @Nullable HeosFacade apiConnection; + + private boolean loggedIn = false; + private boolean bridgeHandlerDisposalOngoing = false; + + private @NonNullByDefault({}) BridgeConfiguration configuration; + + private int failureCount; + + public HeosBridgeHandler(Bridge bridge, HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider) { + super(bridge); + heosSystem = new HeosSystem(scheduler); + channelHandlerFactory = new HeosChannelHandlerFactory(this, heosDynamicStateDescriptionProvider); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + return; + } + @Nullable + Channel channel = this.getThing().getChannel(channelUID.getId()); + if (channel == null) { + logger.debug("No valid channel found"); + return; + } + + @Nullable + ChannelTypeUID channelTypeUID = channel.getChannelTypeUID(); + @Nullable + HeosChannelHandler channelHandler = channelHandlerFactory.getChannelHandler(channelUID, this, channelTypeUID); + if (channelHandler != null) { + try { + channelHandler.handleBridgeCommand(command, thing.getUID()); + failureCount = 0; + updateStatus(ONLINE); + } catch (IOException | ReadException e) { + logger.debug("Failed to handle bridge command", e); + failureCount++; + + if (failureCount > FAILURE_COUNT_LIMIT) { + updateStatus(OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Failed to handle command: " + e.getMessage()); + } + } + } + } + + @Override + public synchronized void initialize() { + configuration = thing.getConfiguration().as(BridgeConfiguration.class); + cancel(startupFuture); + startupFuture = scheduler.submit(this::delayedInitialize); + } + + private void delayedInitialize() { + @Nullable + HeosFacade connection = null; + try { + logger.debug("Running scheduledStartUp job"); + + connection = connectBridge(); + updateStatus(ThingStatus.ONLINE); + updateState(CH_ID_REBOOT, OnOffType.OFF); + + logger.debug("HEOS System heart beat started. Pulse time is {}s", configuration.heartbeat); + // gets all available player and groups to ensure that the system knows + // about the conjunction between the groupMemberHash and the GID + triggerPlayerDiscovery(); + @Nullable + String username = configuration.username; + @Nullable + String password = configuration.password; + if (username != null && !"".equals(username) && password != null && !"".equals(password)) { + login(connection, username, password); + } else { + updateStatus(ThingStatus.ONLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Can't log in. Username or password not set."); + } + + fetchPlayersAndGroups(); + } catch (Telnet.ReadException | IOException | RuntimeException e) { + logger.debug("Error occurred while connecting", e); + if (connection != null) { + connection.closeConnection(); + } + updateStatus(OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Errors occurred: " + e.getMessage()); + cancel(startupFuture, false); + startupFuture = scheduler.schedule(this::delayedInitialize, 30, TimeUnit.SECONDS); + } + } + + private void fetchPlayersAndGroups() { + try { + @Nullable + Player[] onlinePlayers = getApiConnection().getPlayers().payload; + @Nullable + Group[] onlineGroups = getApiConnection().getGroups().payload; + + updatePlayerStatus(onlinePlayers, onlineGroups); + } catch (ReadException | IOException e) { + logger.debug("Failed updating online state of groups/players", e); + } + } + + private void updatePlayerStatus(@Nullable Player[] onlinePlayers, @Nullable Group[] onlineGroups) { + if (onlinePlayers == null || onlineGroups == null) { + return; + } + Set players = Stream.of(onlinePlayers).map(p -> Objects.toString(p.playerId)) + .collect(Collectors.toSet()); + Set groups = Stream.of(onlineGroups).map(p -> p.id).collect(Collectors.toSet()); + + for (Thing thing : getThing().getThings()) { + try { + @Nullable + ThingHandler handler = thing.getHandler(); + if (handler instanceof HeosThingBaseHandler) { + Set target = handler instanceof HeosPlayerHandler ? players : groups; + HeosThingBaseHandler heosHandler = (HeosThingBaseHandler) handler; + String id = heosHandler.getId(); + + if (target.contains(id)) { + heosHandler.setStatusOnline(); + } else { + heosHandler.setStatusOffline(); + } + } + } catch (HeosNotFoundException e) { + logger.debug("SKipping handler which reported not found", e); + } + } + } + + private HeosFacade connectBridge() throws IOException, Telnet.ReadException { + loggedIn = false; + + logger.debug("Initialize Bridge '{}' with IP '{}'", thing.getProperties().get(PROP_NAME), + configuration.ipAddress); + bridgeHandlerDisposalOngoing = false; + HeosFacade connection = heosSystem.establishConnection(configuration.ipAddress, HEOS_PORT, + configuration.heartbeat); + connection.registerForChangeEvents(this); + + apiConnection = connection; + + return connection; + } + + private void login(HeosFacade connection, String username, String password) throws IOException, ReadException { + logger.debug("Logging in to HEOS account."); + HeosResponseObject response = connection.logIn(username, password); + + if (response.result) { + logger.debug("successfully logged-in, event is fired to handle post-login behaviour"); + return; + } + + @Nullable + HeosError error = response.getError(); + logger.debug("Failed to login: {}", error); + updateStatus(ONLINE, ThingStatusDetail.CONFIGURATION_ERROR, + error != null ? error.code.toString() : "Failed to login, no error was returned."); + } + + @Override + public void dispose() { + bridgeHandlerDisposalOngoing = true; // Flag to prevent the handler from being updated during disposal + + cancel(startupFuture); + for (Future future : childHandlerInitializedFutures) { + cancel(future); + } + + @Nullable + HeosFacade localApiConnection = apiConnection; + if (localApiConnection == null) { + logger.debug("Not disposing bridge because of missing apiConnection"); + return; + } + + localApiConnection.unregisterForChangeEvents(this); + logger.debug("HEOS bridge removed from change notifications"); + + logger.debug("Dispose bridge '{}'", thing.getProperties().get(PROP_NAME)); + localApiConnection.closeConnection(); + } + + /** + * Manages the removal of the player or group channels from the bridge. + */ + @Override + public synchronized void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { + logger.debug("Disposing child handler for: {}.", childThing.getUID().getId()); + if (bridgeHandlerDisposalOngoing) { // Checks if bridgeHandler is going to disposed (by stopping the binding or + // openHAB for example) and prevents it from being updated which stops the + // disposal process. + } else if (childHandler instanceof HeosPlayerHandler) { + String channelIdentifier = "P" + childThing.getUID().getId(); + updateThingChannels(channelManager.removeSingleChannel(channelIdentifier)); + } else if (childHandler instanceof HeosGroupHandler) { + String channelIdentifier = "G" + childThing.getUID().getId(); + updateThingChannels(channelManager.removeSingleChannel(channelIdentifier)); + // removes the handler from the groupMemberMap that handler is no longer called + // if group is getting online + removeGroupHandlerInformation((HeosGroupHandler) childHandler); + } + } + + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + logger.debug("Initialized child handler for: {}.", childThing.getUID().getId()); + childHandlerInitializedFutures.add(scheduler.submit(() -> addPlayerChannel(childThing, null))); + } + + void resetPlayerList(ChannelUID channelUID) { + selectedPlayerList.forEach(element -> updateState(element[1], OnOffType.OFF)); + selectedPlayerList.clear(); + updateState(channelUID, OnOffType.OFF); + } + + /** + * Sets the HEOS Thing offline + */ + @SuppressWarnings("null") + public void setGroupOffline(String hashValue) { + HeosGroupHandler groupHandler = groupHandlerMap.get(hashValue); + if (groupHandler != null) { + groupHandler.setStatusOffline(); + } + } + + /** + * Sets the HEOS Thing online. Also updates the link between + * the groupMemberHash value with the actual gid of this group * + */ + public void setGroupOnline(String groupMemberHash, String groupId) { + hashToGidMap.put(groupMemberHash, groupId); + Optional.ofNullable(groupHandlerMap.get(groupMemberHash)).ifPresent(handler -> { + handler.setStatusOnline(); + addPlayerChannel(handler.getThing(), groupId); + }); + } + + /** + * Create a channel for the childThing. Depending if it is a HEOS Group + * or a player an identification prefix is added + * + * @param childThing the thing the channel is created for + * @param groupId + */ + private void addPlayerChannel(Thing childThing, @Nullable String groupId) { + try { + String channelIdentifier = ""; + String pid = ""; + @Nullable + ThingHandler handler = childThing.getHandler(); + if (handler instanceof HeosPlayerHandler) { + channelIdentifier = "P" + childThing.getUID().getId(); + pid = ((HeosPlayerHandler) handler).getId(); + } else if (handler instanceof HeosGroupHandler) { + channelIdentifier = "G" + childThing.getUID().getId(); + if (groupId == null) { + pid = ((HeosGroupHandler) handler).getId(); + } else { + pid = groupId; + } + } + Map properties = new HashMap<>(); + @Nullable + String playerName = childThing.getLabel(); + playerName = playerName == null ? pid : playerName; + ChannelUID channelUID = new ChannelUID(getThing().getUID(), channelIdentifier); + properties.put(PROP_NAME, playerName); + properties.put(PID, pid); + + Channel channel = ChannelBuilder.create(channelUID, "Switch").withLabel(playerName).withType(CH_TYPE_PLAYER) + .withProperties(properties).build(); + updateThingChannels(channelManager.addSingleChannel(channel)); + } catch (HeosNotFoundException e) { + logger.debug("Group is not yet initialized fully"); + } + } + + public void addGroupHandlerInformation(HeosGroupHandler handler) { + groupHandlerMap.put(handler.getGroupMemberHash(), handler); + } + + private void removeGroupHandlerInformation(HeosGroupHandler handler) { + groupHandlerMap.remove(handler.getGroupMemberHash()); + } + + public @Nullable String getActualGID(String groupHash) { + return hashToGidMap.get(groupHash); + } + + @Override + public void playerStateChangeEvent(HeosEventObject eventObject) { + // do nothing + } + + @Override + public void playerStateChangeEvent(HeosResponseObject responseObject) { + // do nothing + } + + @Override + public void playerMediaChangeEvent(String pid, Media media) { + // do nothing + } + + @Override + public void bridgeChangeEvent(String event, boolean success, Object command) { + if (EVENT_TYPE_EVENT.equals(event)) { + if (HeosEvent.PLAYERS_CHANGED.equals(command) || HeosEvent.GROUPS_CHANGED.equals(command)) { + fetchPlayersAndGroups(); + triggerPlayerDiscovery(); + } else if (EVENT_STREAM_TIMEOUT.equals(command)) { + logger.debug("HEOS Bridge events timed-out might be nothing, trying to reconnect"); + } else if (CONNECTION_LOST.equals(command)) { + updateStatus(OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + logger.debug("HEOS Bridge OFFLINE"); + } else if (CONNECTION_RESTORED.equals(command)) { + initialize(); + } + } + if (EVENT_TYPE_SYSTEM.equals(event) && HeosEvent.USER_CHANGED == command) { + if (success && !loggedIn) { + loggedIn = true; + } + } + } + + private synchronized void updateThingChannels(List channelList) { + ThingBuilder thingBuilder = editThing(); + thingBuilder.withChannels(channelList); + updateThing(thingBuilder.build()); + } + + public Player[] getPlayers() throws IOException, ReadException { + HeosResponseObject response = getApiConnection().getPlayers(); + @Nullable + Player[] players = response.payload; + if (players == null) { + throw new IOException("Received no valid payload"); + } + return players; + } + + public Group[] getGroups() throws IOException, ReadException { + HeosResponseObject response = getApiConnection().getGroups(); + @Nullable + Group[] groups = response.payload; + if (groups == null) { + throw new IOException("Received no valid payload"); + } + return groups; + } + + /** + * The list with the currently selected player + * + * @return a HashMap which the currently selected player + */ + public Map getSelectedPlayer() { + return selectedPlayerList.stream().collect(Collectors.toMap(a -> a[0], a -> a[1], (a, b) -> a)); + } + + public List getSelectedPlayerList() { + return selectedPlayerList; + } + + public void setSelectedPlayerList(List selectedPlayerList) { + this.selectedPlayerList = selectedPlayerList; + } + + public HeosChannelHandlerFactory getChannelHandlerFactory() { + return channelHandlerFactory; + } + + /** + * Register an {@link HeosPlayerDiscoveryListener} to get informed + * if the amount of groups or players have changed + * + * @param listener the implementing class + */ + public void registerPlayerDiscoverListener(HeosPlayerDiscoveryListener listener) { + playerDiscoveryList.add(listener); + } + + private void triggerPlayerDiscovery() { + playerDiscoveryList.forEach(HeosPlayerDiscoveryListener::playerChanged); + } + + public boolean isLoggedIn() { + return loggedIn; + } + + public boolean isBridgeConnected() { + @Nullable + HeosFacade connection = apiConnection; + return connection != null && connection.isConnected(); + } + + public HeosFacade getApiConnection() throws HeosNotConnectedException { + @Nullable + HeosFacade localApiConnection = apiConnection; + if (localApiConnection != null) { + return localApiConnection; + } else { + throw new HeosNotConnectedException(); + } + } + + @Override + public Collection> getServices() { + return Collections.singletonList(HeosActions.class); + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandler.java index 1eeaa4028c496..a8147bd5fa375 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandler.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandler.java @@ -12,14 +12,13 @@ */ package org.openhab.binding.heos.internal.handler; -import org.eclipse.smarthome.core.thing.ChannelUID; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.types.Command; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.handler.HeosGroupHandler; -import org.openhab.binding.heos.handler.HeosPlayerHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandler} handles the base class for the different @@ -28,77 +27,27 @@ * * @author Johannes Einig - Initial contribution */ -public abstract class HeosChannelHandler { - protected final Logger logger = LoggerFactory.getLogger(HeosChannelHandler.class); - - protected Object handler; - protected HeosBridgeHandler bridge; - protected HeosFacade api; - protected String id; - protected Command command; - protected ChannelUID channelUID; - - /** - * - * @param bridge Requires the HeosBridgeHandler - * @param api The HeosFacade class - */ - public HeosChannelHandler(HeosBridgeHandler bridge, HeosFacade api) { - this.bridge = bridge; - this.api = api; - } - +@NonNullByDefault +public interface HeosChannelHandler { /** * Handle a command received from a channel. Requires the class which * wants to handle the command to decide which subclass has to be used - * - * @param command the command to handle - * @param id of the group or player - * @param handler The class which wants to handle the command - * @param channelUID the channelUID of the handleCommand function + * + * @param command the command to handle + * @param id of the group or player + * @param uid */ - public void handleCommand(Command command, String id, Object handler, ChannelUID channelUID) { - this.command = command; - this.id = id; - this.handler = handler; - this.channelUID = channelUID; + void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException; - if (handler instanceof HeosPlayerHandler) { - handleCommandPlayer(); - } else if (handler instanceof HeosGroupHandler) { - handleCommandGroup(); - } - } + void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, HeosGroupHandler heosGroupHandler) + throws IOException, ReadException; /** * Handles a command for classes without an id. Used * for BridgeHandler * - * @param command the command to handle - * @param handler The class which wants to handle the command - * @param channelUID the channelUID of the handleCommand function - */ - public void handleCommand(Command command, Object handler, ChannelUID channelUID) { - this.command = command; - this.handler = handler; - this.channelUID = channelUID; - if (handler instanceof HeosBridgeHandler) { - handleCommandBridge(); - } - } - - /** - * Handles the command for HEOS player - */ - protected abstract void handleCommandPlayer(); - - /** - * Handles the command for HEOS groups - */ - protected abstract void handleCommandGroup(); - - /** - * Handles the command for the HEOS bridge + * @param command the command to handle + * @param uid */ - protected abstract void handleCommandBridge(); + void handleBridgeCommand(Command command, ThingUID uid) throws IOException, ReadException; } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerAlbum.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerAlbum.java deleted file mode 100644 index f588f6b94d5f4..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerAlbum.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerAlbum} handles the refresh commands - * coming from the implementing thing - * - * @author Johannes Einig - Initial contribution - */ -public class HeosChannelHandlerAlbum extends HeosChannelHandler { - - public HeosChannelHandlerAlbum(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - // No such channel on bridge - } - - private void handleCommand() { - if (command instanceof RefreshType) { - api.getNowPlayingMediaAlbum(id); - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerArtist.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerArtist.java deleted file mode 100644 index 4ba79984ab8ba..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerArtist.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerArtist} handles the refresh commands - * coming from the implementing thing - * - * @author Johannes Einig - Initial contribution - */ -public class HeosChannelHandlerArtist extends HeosChannelHandler { - - public HeosChannelHandlerArtist(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - // No such channel on bridge - } - - private void handleCommand() { - if (command instanceof RefreshType) { - api.getNowPlayingMediaArtist(id); - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerBuildGroup.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerBuildGroup.java index b061c144f27e3..1801930844e34 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerBuildGroup.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerBuildGroup.java @@ -12,12 +12,17 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerBuildGroup} handles the BuidlGroup channel command @@ -25,36 +30,37 @@ * * @author Johannes Einig - Initial contribution * */ -public class HeosChannelHandlerBuildGroup extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerBuildGroup extends BaseHeosChannelHandler { + private final ChannelUID channelUID; - public HeosChannelHandlerBuildGroup(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerBuildGroup(ChannelUID channelUID, HeosBridgeHandler bridge) { + super(bridge); + this.channelUID = channelUID; } @Override - protected void handleCommandPlayer() { + public void handlePlayerCommand(Command command, String id, ThingUID uid) { // not used on player } @Override - protected void handleCommandGroup() { + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) { // not used on group } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) throws IOException, ReadException { if (command instanceof RefreshType) { bridge.resetPlayerList(channelUID); return; } - if (command.equals(OnOffType.ON)) { + + if (command == OnOffType.ON) { List selectedPlayerList = bridge.getSelectedPlayerList(); if (!selectedPlayerList.isEmpty()) { - String[] player = new String[selectedPlayerList.size()]; - for (int i = 0; i < selectedPlayerList.size(); i++) { - player[i] = selectedPlayerList.get(i)[0]; - } - api.groupPlayer(player); + getApi().groupPlayer(selectedPlayerList.stream().map(a -> a[0]).toArray(String[]::new)); bridge.resetPlayerList(channelUID); } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerClearQueue.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerClearQueue.java new file mode 100644 index 0000000000000..ec792f94aad6a --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerClearQueue.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; + +/** + * The {@link HeosChannelHandlerReboot} handles the Reboot channel command + * from the implementing thing. + * + * @author Johannes Einig - Initial contribution + */ +@NonNullByDefault +public class HeosChannelHandlerClearQueue extends BaseHeosChannelHandler { + public HeosChannelHandlerClearQueue(HeosBridgeHandler bridge) { + super(bridge); + } + + @Override + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id); + } + + @Override + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + handleCommand(command, id); + } + + @Override + public void handleBridgeCommand(Command command, ThingUID uid) { + // Not used on bridge + } + + private void handleCommand(Command command, String id) throws IOException, ReadException { + if (command instanceof RefreshType) { + return; + } + + if (command == OnOffType.ON) { + getApi().clearQueue(id); + } + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerControl.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerControl.java index 96e9bb1996270..3f797c8a48bb3 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerControl.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerControl.java @@ -12,61 +12,70 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerControl} handles the control commands * coming from the implementing thing * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerControl extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerControl extends BaseHeosChannelHandler { + private final HeosEventListener eventListener; - public HeosChannelHandlerControl(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerControl(HeosEventListener eventListener, HeosBridgeHandler bridge) { + super(bridge); + this.eventListener = eventListener; } @Override - protected void handleCommandPlayer() { - handleCommand(); + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id); } @Override - protected void handleCommandGroup() { - handleCommand(); + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + handleCommand(command, id); } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // No such channel within bridge } - private void handleCommand() { + private void handleCommand(Command command, String id) throws IOException, ReadException { if (command instanceof RefreshType) { - api.getHeosPlayState(id); + eventListener.playerStateChangeEvent(getApi().getPlayState(id)); return; } switch (command.toString()) { case "PLAY": - api.play(id); + case "ON": + getApi().play(id); break; case "PAUSE": - api.pause(id); + case "OFF": + getApi().pause(id); break; case "NEXT": - api.next(id); + getApi().next(id); break; case "PREVIOUS": - api.previous(id); - break; - case "ON": - api.play(id); - break; - case "OFF": - api.pause(id); + getApi().previous(id); break; } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerCover.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerCover.java deleted file mode 100644 index 1bd771c1f5ccd..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerCover.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerCover} handles the refresh commands - * coming from the implementing thing - * - * @author Johannes Einig - Initial contribution - */ -public class HeosChannelHandlerCover extends HeosChannelHandler { - - public HeosChannelHandlerCover(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - // No such channel on bridge - } - - private void handleCommand() { - if (command instanceof RefreshType) { - api.getNowPlayingMediaImageUrl(id); - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerCurrentPosition.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerCurrentPosition.java deleted file mode 100644 index 71fd942f8e07a..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerCurrentPosition.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerCurrentPosition} handles the refresh commands - * coming from the implementing thing - * - * @author Johannes Einig - Initial contribution - * - */ -public class HeosChannelHandlerCurrentPosition extends HeosChannelHandler { - - public HeosChannelHandlerCurrentPosition(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - // No such channel on bridge - } - - private void handleCommand() { - if (command instanceof RefreshType) { - // Channel is refreshed automatically if song is played - return; - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerDuration.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerDuration.java deleted file mode 100644 index 6bd33b9f67fcc..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerDuration.java +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerDuration} handles the refresh commands - * coming from the implementing thing - * - * @author Johannes Einig - Initial contribution - * - */ -public class HeosChannelHandlerDuration extends HeosChannelHandler { - - public HeosChannelHandlerDuration(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - // No such channel on bridge - } - - private void handleCommand() { - if (command instanceof RefreshType) { - // Channel is refreshed automatically if song is played - return; - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerFavorite.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerFavorite.java new file mode 100644 index 0000000000000..6725fad5c4b41 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerFavorite.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import static org.openhab.binding.heos.internal.HeosBindingConstants.CH_ID_FAVORITES; +import static org.openhab.binding.heos.internal.resources.HeosConstants.FAVORITE_SID; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; + +/** + * The {@link HeosChannelHandlerFavorite} handles the playlist selection channel command + * from the implementing thing. + * + * @author Johannes Einig - Initial contribution + */ +@NonNullByDefault +public class HeosChannelHandlerFavorite extends BaseHeosChannelHandler { + private final HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider; + + public HeosChannelHandlerFavorite(HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider, + HeosBridgeHandler bridge) { + super(bridge); + this.heosDynamicStateDescriptionProvider = heosDynamicStateDescriptionProvider; + } + + @Override + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id, uid); + } + + @Override + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + handleCommand(command, id, uid); + } + + @Override + public void handleBridgeCommand(Command command, ThingUID uid) { + // not used on bridge + } + + private void handleCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + ChannelUID channelUID = new ChannelUID(uid, CH_ID_FAVORITES); + if (command instanceof RefreshType) { + heosDynamicStateDescriptionProvider.setFavorites(channelUID, getApi().getFavorites()); + return; + } + + String idCommand = heosDynamicStateDescriptionProvider.getValueByLabel(channelUID, command.toString()); + getApi().playStream(id, FAVORITE_SID, idCommand); + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerFavoriteSelect.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerFavoriteSelect.java deleted file mode 100644 index 4258290787d08..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerFavoriteSelect.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import static org.openhab.binding.heos.internal.resources.HeosConstants.FAVORIT_SID; - -import java.util.List; - -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerFavoriteSelect} handles the favorite selection channel command - * from the implementing thing. - * - * @author Johannes Einig - Initial contribution - * - */ -public class HeosChannelHandlerFavoriteSelect extends HeosChannelHandler { - - public HeosChannelHandlerFavoriteSelect(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - if (command instanceof RefreshType) { - bridge.resetPlayerList(channelUID); - return; - } - if (command.equals(OnOffType.ON)) { - List selectedPlayerList = bridge.getSelectedPlayerList(); - if (!selectedPlayerList.isEmpty()) { - for (int i = 0; i < selectedPlayerList.size(); i++) { - String pid = selectedPlayerList.get(i)[0]; - String mid = channelUID.getId(); // the channel ID represents the MID of the favorite - api.playStation(pid, FAVORIT_SID, mid); - } - } - bridge.resetPlayerList(channelUID); - } - } - - private void handleCommand() { - if (OnOffType.ON.equals(command)) { - api.playStation(id, FAVORIT_SID, channelUID.getId()); - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerGrouping.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerGrouping.java index 2cae780c32e00..745cf9633318b 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerGrouping.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerGrouping.java @@ -12,12 +12,16 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.handler.HeosGroupHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; -import org.openhab.binding.heos.internal.resources.HeosGroup; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerGrouping} handles the grouping channel command @@ -25,36 +29,36 @@ * * @author Johannes Einig - Initial contribution */ -public class HeosChannelHandlerGrouping extends HeosChannelHandler { - - public HeosChannelHandlerGrouping(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); +@NonNullByDefault +public class HeosChannelHandlerGrouping extends BaseHeosChannelHandler { + public HeosChannelHandlerGrouping(HeosBridgeHandler bridge) { + super(bridge); } @Override - protected void handleCommandPlayer() { + public void handlePlayerCommand(Command command, String id, ThingUID uid) { // No such channel on player } @Override - protected void handleCommandGroup() { + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (command instanceof RefreshType) { - HeosGroupHandler heosGroupHandler = (HeosGroupHandler) handler; - heosGroupHandler.initialize(); return; } - if (command.equals(OnOffType.OFF)) { - api.ungroupGroup(id); - } else if (command.equals(OnOffType.ON)) { - HeosGroupHandler heosGroupHandler = (HeosGroupHandler) handler; - HeosGroup heosGroup = heosGroupHandler.getHeosGroup(); - String[] playerArray = heosGroup.getGroupMemberPidList().toArray(new String[0]); - api.groupPlayer(playerArray); + if (OnOffType.OFF == command) { + if (id == null) { + throw new HeosNotFoundException(); + } + getApi().ungroupGroup(id); + } else if (OnOffType.ON == command) { + getApi().groupPlayer(heosGroupHandler.getGroupMemberPidList()); } } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // No such channel on Bridge } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerInputs.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerInputs.java index 2438029ae6ab6..5b971308acba8 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerInputs.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerInputs.java @@ -12,53 +12,78 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The {@link HeosChannelHandlerInputs} handles the Input channel command * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerInputs extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerInputs extends BaseHeosChannelHandler { + protected final Logger logger = LoggerFactory.getLogger(HeosChannelHandlerInputs.class); + + private final HeosEventListener eventListener; - public HeosChannelHandlerInputs(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerInputs(HeosEventListener eventListener, HeosBridgeHandler bridge) { + super(bridge); + this.eventListener = eventListener; } @Override - protected void handleCommandPlayer() { - handleCommand(); + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id); } @Override - protected void handleCommandGroup() { - handleCommand(); + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + handleCommand(command, id); } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // not used on bridge } - private void handleCommand() { + private void handleCommand(Command command, String id) throws IOException, ReadException { if (command instanceof RefreshType) { - api.getNowPlayingMedia(id); + @Nullable + Media payload = getApi().getNowPlayingMedia(id).payload; + if (payload != null) { + eventListener.playerMediaChangeEvent(id, payload); + } return; } - if (bridge.getSelectedPlayer().isEmpty()) { - api.playInputSource(id, command.toString()); - } else if (bridge.getSelectedPlayer().size() > 1) { + + Map selectedPlayers = bridge.getSelectedPlayer(); + if (selectedPlayers.isEmpty()) { + // no selected player, just play it from the player itself + getApi().playInputSource(id, command.toString()); + } else if (selectedPlayers.size() > 1) { logger.debug("Only one source can be selected for HEOS Input. Selected amount of sources: {} ", - bridge.getSelectedPlayer().size()); + selectedPlayers.size()); } else { - for (String sourcePid : bridge.getSelectedPlayer().keySet()) { - api.playInputSource(id, sourcePid, command.toString()); + for (String sourcePid : selectedPlayers.keySet()) { + getApi().playInputSource(id, sourcePid, command.toString()); } } - bridge.getSelectedPlayer().clear(); } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerMute.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerMute.java index e16894d8a1ad0..32e53137b92dd 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerMute.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerMute.java @@ -12,52 +12,66 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerMute} handles the Mute channel command * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerMute extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerMute extends BaseHeosChannelHandler { + private final HeosEventListener eventListener; - public HeosChannelHandlerMute(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerMute(HeosEventListener eventListener, HeosBridgeHandler bridge) { + super(bridge); + this.eventListener = eventListener; } @Override - protected void handleCommandPlayer() { + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { if (command instanceof RefreshType) { - api.getHeosPlayerMuteState(id); + eventListener.playerStateChangeEvent(getApi().getPlayerMuteState(id)); return; } if (command.equals(OnOffType.ON)) { - api.muteON(id); + getApi().muteON(id); } else if (command.equals(OnOffType.OFF)) { - api.muteOFF(id); + getApi().muteOFF(id); } } @Override - protected void handleCommandGroup() { + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + if (command instanceof RefreshType) { - api.getHeosGroupeMuteState(id); + eventListener.playerStateChangeEvent(getApi().getGroupMuteState(id)); return; } if (command.equals(OnOffType.ON)) { - api.muteGroupON(id); + getApi().muteGroupON(id); } else if (command.equals(OnOffType.OFF)) { - api.muteGroupOFF(id); + getApi().muteGroupOFF(id); } } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // No such channel on bridge } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerNowPlaying.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerNowPlaying.java new file mode 100644 index 0000000000000..1472223e25027 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerNowPlaying.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; + +/** + * The {@link HeosChannelHandlerNowPlaying} handles the refresh commands + * coming from the implementing thing + * + * @author Johannes Einig - Initial contribution + */ +@NonNullByDefault +public class HeosChannelHandlerNowPlaying extends BaseHeosChannelHandler { + private final HeosEventListener eventListener; + + public HeosChannelHandlerNowPlaying(HeosEventListener eventListener, HeosBridgeHandler bridge) { + super(bridge); + this.eventListener = eventListener; + } + + @Override + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id); + } + + @Override + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + + handleCommand(command, id); + } + + @Override + public void handleBridgeCommand(Command command, ThingUID uid) { + // No such channel on bridge + } + + private void handleCommand(Command command, String id) throws IOException, ReadException { + if (command instanceof RefreshType) { + // TODO consider caching this somehow, this method is triggered from a lot of channels for the same player + @Nullable + Media payload = getApi().getNowPlayingMedia(id).payload; + if (payload != null) { + eventListener.playerMediaChangeEvent(id, payload); + } + } + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlayURL.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlayURL.java index 9a983ede9fc9a..1a80909961155 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlayURL.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlayURL.java @@ -12,50 +12,63 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The {@link HeosChannelHandlerPlayURL} handles the PlayURL channel command * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerPlayURL extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerPlayURL extends BaseHeosChannelHandler { + protected final Logger logger = LoggerFactory.getLogger(HeosChannelHandlerPlayURL.class); - public HeosChannelHandlerPlayURL(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerPlayURL(HeosBridgeHandler bridge) { + super(bridge); } @Override - protected void handleCommandPlayer() { - handleCommand(); + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id); } @Override - protected void handleCommandGroup() { - handleCommand(); + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + + handleCommand(command, id); } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // not used on bridge } - private void handleCommand() { + private void handleCommand(Command command, String id) throws IOException, ReadException { if (command instanceof RefreshType) { return; } try { URL url = new URL(command.toString()); - api.playURL(id, url); + getApi().playURL(id, url); } catch (MalformedURLException e) { - logger.debug("Command '{}' is not a propper URL. Error: {}", command.toString(), e.getMessage()); + logger.debug("Command '{}' is not a proper URL. Error: {}", command.toString(), e.getMessage()); } } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlayerSelect.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlayerSelect.java index 7adef1740759f..e5d2fa07313e7 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlayerSelect.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlayerSelect.java @@ -16,11 +16,16 @@ import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The {@link HeosChannelHandlerPlayerSelect} handles the player selection channel command @@ -28,34 +33,41 @@ * * @author Johannes Einig - Initial contribution */ -public class HeosChannelHandlerPlayerSelect extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerPlayerSelect extends BaseHeosChannelHandler { + protected final Logger logger = LoggerFactory.getLogger(HeosChannelHandlerPlayerSelect.class); - public HeosChannelHandlerPlayerSelect(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + private final ChannelUID channelUID; + + public HeosChannelHandlerPlayerSelect(ChannelUID channelUID, HeosBridgeHandler bridge) { + super(bridge); + this.channelUID = channelUID; } @Override - protected void handleCommandPlayer() { + public void handlePlayerCommand(Command command, String id, ThingUID uid) { // not used on player } @Override - protected void handleCommandGroup() { + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) { // not used on group } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { if (command instanceof RefreshType) { return; } - List selectedPlayerList = bridge.getSelectedPlayerList(); Channel channel = bridge.getThing().getChannel(channelUID.getId()); if (channel == null) { - logger.debug("Channel {} not found", channelUID.toString()); + logger.debug("Channel {} not found", channelUID); return; } + List selectedPlayerList = bridge.getSelectedPlayerList(); + if (command.equals(OnOffType.ON)) { String[] selectedPlayerInfo = new String[2]; selectedPlayerInfo[0] = channel.getProperties().get(PID); @@ -65,7 +77,7 @@ protected void handleCommandBridge() { int indexPlayerChannel = -1; for (int i = 0; i < selectedPlayerList.size(); i++) { String localPID = selectedPlayerList.get(i)[0]; - if (localPID == channel.getProperties().get(PID)) { + if (localPID.equals(channel.getProperties().get(PID))) { indexPlayerChannel = i; } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlaylist.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlaylist.java index 83e647c7d632c..7d1046d6beaa3 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlaylist.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerPlaylist.java @@ -12,45 +12,64 @@ */ package org.openhab.binding.heos.internal.handler; +import static org.openhab.binding.heos.internal.HeosBindingConstants.CH_ID_PLAYLISTS; import static org.openhab.binding.heos.internal.resources.HeosConstants.PLAYLISTS_SID; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerPlaylist} handles the playlist selection channel command * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerPlaylist extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerPlaylist extends BaseHeosChannelHandler { + private final HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider; - public HeosChannelHandlerPlaylist(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerPlaylist(HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider, + HeosBridgeHandler bridge) { + super(bridge); + this.heosDynamicStateDescriptionProvider = heosDynamicStateDescriptionProvider; } @Override - protected void handleCommandPlayer() { - handleCommand(); + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id, uid); } @Override - protected void handleCommandGroup() { - handleCommand(); + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + + handleCommand(command, id, uid); } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // not used on bridge } - private void handleCommand() { + private void handleCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + ChannelUID channelUID = new ChannelUID(uid, CH_ID_PLAYLISTS); if (command instanceof RefreshType) { + heosDynamicStateDescriptionProvider.setPlaylists(channelUID, getApi().getPlaylists()); return; } - String cid = bridge.getHeosPlaylists().get(Integer.valueOf(command.toString())); - api.addContainerToQueuePlayNow(id, PLAYLISTS_SID, cid); + + String idCommand = heosDynamicStateDescriptionProvider.getValueByLabel(channelUID, command.toString()); + getApi().addContainerToQueuePlayNow(id, PLAYLISTS_SID, idCommand); } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerQueue.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerQueue.java new file mode 100644 index 0000000000000..97bdda64a1daf --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerQueue.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import static org.openhab.binding.heos.internal.HeosBindingConstants.CH_ID_QUEUE; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; + +/** + * The {@link HeosChannelHandlerFavorite} handles the playlist selection channel command + * from the implementing thing. + * + * @author Johannes Einig - Initial contribution + */ +@NonNullByDefault +public class HeosChannelHandlerQueue extends BaseHeosChannelHandler { + private final HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider; + + public HeosChannelHandlerQueue(HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider, + HeosBridgeHandler bridge) { + super(bridge); + this.heosDynamicStateDescriptionProvider = heosDynamicStateDescriptionProvider; + } + + @Override + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id, uid); + } + + @Override + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + + handleCommand(command, id, uid); + } + + @Override + public void handleBridgeCommand(Command command, ThingUID uid) { + // not used on bridge + } + + private void handleCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + ChannelUID channelUID = new ChannelUID(uid, CH_ID_QUEUE); + if (command instanceof RefreshType) { + heosDynamicStateDescriptionProvider.setQueue(channelUID, getApi().getQueue(id)); + return; + } + + String idCommand = heosDynamicStateDescriptionProvider.getValueByLabel(channelUID, command.toString()); + getApi().playMediaFromQueue(id, idCommand); + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerRawCommand.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerRawCommand.java index 199801ab774ad..c4452a3fdcfa5 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerRawCommand.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerRawCommand.java @@ -12,9 +12,18 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.json.dto.HeosResponseObject; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; + +import com.google.gson.JsonElement; /** * @@ -22,29 +31,36 @@ * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerRawCommand extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerRawCommand extends BaseHeosChannelHandler { + private final HeosEventListener eventListener; - public HeosChannelHandlerRawCommand(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerRawCommand(HeosEventListener eventListener, HeosBridgeHandler bridge) { + super(bridge); + this.eventListener = eventListener; } @Override - protected void handleCommandPlayer() { + public void handlePlayerCommand(Command command, String id, ThingUID uid) { // not used on player } @Override - protected void handleCommandGroup() { + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) { // not used on group } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) throws IOException, ReadException { if (command instanceof RefreshType) { return; } - api.sendRawCommand(command.toString()); + HeosResponseObject response = getApi().sendRawCommand(command.toString()); + + if (response.result) { + eventListener.playerStateChangeEvent(response); + } } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerReboot.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerReboot.java index 664b84dd65c28..b5177ec7736fa 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerReboot.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerReboot.java @@ -12,41 +12,46 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerReboot} handles the Reboot channel command * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerReboot extends HeosChannelHandler { - - public HeosChannelHandlerReboot(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); +@NonNullByDefault +public class HeosChannelHandlerReboot extends BaseHeosChannelHandler { + public HeosChannelHandlerReboot(HeosBridgeHandler bridge) { + super(bridge); } @Override - protected void handleCommandPlayer() { + public void handlePlayerCommand(Command command, String id, ThingUID uid) { // not used on player } @Override - protected void handleCommandGroup() { + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) { // Not used on group } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) throws IOException, ReadException { if (command instanceof RefreshType) { return; } - if (command.equals(OnOffType.ON)) { - api.reboot(); + if (command == OnOffType.ON) { + getApi().reboot(); } } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerRepeatMode.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerRepeatMode.java index 9aafa5e0c65fe..891f36340d6a2 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerRepeatMode.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerRepeatMode.java @@ -12,50 +12,65 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; import org.openhab.binding.heos.internal.resources.HeosConstants; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerRepeatMode} handles the RepeatMode channel command * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerRepeatMode extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerRepeatMode extends BaseHeosChannelHandler { + private final HeosEventListener eventListener; - public HeosChannelHandlerRepeatMode(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerRepeatMode(HeosEventListener eventListener, HeosBridgeHandler bridge) { + super(bridge); + this.eventListener = eventListener; } @Override - protected void handleCommandPlayer() { - handleCommand(); + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id); } @Override - protected void handleCommandGroup() { - handleCommand(); + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + + handleCommand(command, id); } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // Do nothing } - private void handleCommand() { + private void handleCommand(Command command, String id) throws IOException, ReadException { if (command instanceof RefreshType) { - api.getHeosPlayerRepeatMode(id); + eventListener.playerStateChangeEvent(getApi().getPlayMode(id)); return; } + if (HeosConstants.HEOS_UI_ALL.equalsIgnoreCase(command.toString())) { - api.setRepeatMode(id, HeosConstants.REPEAT_ALL); + getApi().setRepeatMode(id, HeosConstants.REPEAT_ALL); } else if (HeosConstants.HEOS_UI_ONE.equalsIgnoreCase(command.toString())) { - api.setRepeatMode(id, HeosConstants.REPEAT_ONE); + getApi().setRepeatMode(id, HeosConstants.REPEAT_ONE); } else if (HeosConstants.HEOS_UI_OFF.equalsIgnoreCase(command.toString())) { - api.setRepeatMode(id, HeosConstants.OFF); + getApi().setRepeatMode(id, HeosConstants.OFF); } } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerShuffleMode.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerShuffleMode.java index 2bbf8c2717331..00a991d0745ad 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerShuffleMode.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerShuffleMode.java @@ -12,49 +12,63 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; import org.openhab.binding.heos.internal.resources.HeosConstants; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerShuffleMode} handles the SchuffelModechannel command * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ -public class HeosChannelHandlerShuffleMode extends HeosChannelHandler { +@NonNullByDefault +public class HeosChannelHandlerShuffleMode extends BaseHeosChannelHandler { + private final HeosEventListener eventListener; - public HeosChannelHandlerShuffleMode(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerShuffleMode(HeosEventListener eventListener, HeosBridgeHandler bridge) { + super(bridge); + this.eventListener = eventListener; } @Override - protected void handleCommandPlayer() { - handleCommand(); + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { + handleCommand(command, id); } @Override - protected void handleCommandGroup() { - handleCommand(); + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + + handleCommand(command, id); } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // Do nothing } - private void handleCommand() { + private void handleCommand(Command command, String id) throws IOException, ReadException { if (command instanceof RefreshType) { - api.getHeosPlayerShuffleMode(id); + eventListener.playerStateChangeEvent(getApi().getPlayMode(id)); return; } - if (OnOffType.ON.equals(command)) { - api.setShuffleMode(id, HeosConstants.ON); - } else if (OnOffType.OFF.equals(command)) { - api.setShuffleMode(id, HeosConstants.OFF); + if (command == OnOffType.ON) { + getApi().setShuffleMode(id, HeosConstants.ON); + } else if (command == OnOffType.OFF) { + getApi().setShuffleMode(id, HeosConstants.OFF); } } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerStation.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerStation.java deleted file mode 100644 index 622c85eb2e308..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerStation.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerStation} handles the refresh commands - * coming from the implementing thing - * - * @author Johannes Einig - Initial contribution - */ -public class HeosChannelHandlerStation extends HeosChannelHandler { - - public HeosChannelHandlerStation(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - // No such channel on bridge - } - - private void handleCommand() { - if (command instanceof RefreshType) { - api.getNowPlayingMediaStation(id); - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerTitle.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerTitle.java deleted file mode 100644 index cfcd92df6c60f..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerTitle.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerTitle} handles the refresh commands - * coming from the implementing thing - * - * @author Johannes Einig - Initial contribution - */ -public class HeosChannelHandlerTitle extends HeosChannelHandler { - - public HeosChannelHandlerTitle(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - // No such channel on bridge - } - - private void handleCommand() { - if (command instanceof RefreshType) { - api.getNowPlayingMediaSong(id); - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerType.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerType.java deleted file mode 100644 index b3b11c7dbeac7..0000000000000 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerType.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.heos.internal.handler; - -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; - -/** - * The {@link HeosChannelHandlerType} handles the refresh commands - * coming from the implementing thing - * - * @author Johannes Einig - Initial contribution - */ -public class HeosChannelHandlerType extends HeosChannelHandler { - - public HeosChannelHandlerType(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); - } - - @Override - protected void handleCommandPlayer() { - handleCommand(); - } - - @Override - protected void handleCommandGroup() { - handleCommand(); - } - - @Override - protected void handleCommandBridge() { - // No such channel on bridge - } - - private void handleCommand() { - if (command instanceof RefreshType) { - api.getNowPlayingMediaType(id); - } - } -} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerVolume.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerVolume.java index 2387acf2ec6b9..c3b2ef31ec144 100644 --- a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerVolume.java +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosChannelHandlerVolume.java @@ -12,61 +12,74 @@ */ package org.openhab.binding.heos.internal.handler; +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.heos.handler.HeosBridgeHandler; -import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; /** * The {@link HeosChannelHandlerVolume} handles the Volume channel command * from the implementing thing. * * @author Johannes Einig - Initial contribution - * */ +@NonNullByDefault +public class HeosChannelHandlerVolume extends BaseHeosChannelHandler { + private final HeosEventListener eventListener; -public class HeosChannelHandlerVolume extends HeosChannelHandler { - - public HeosChannelHandlerVolume(HeosBridgeHandler bridge, HeosFacade api) { - super(bridge, api); + public HeosChannelHandlerVolume(HeosEventListener eventListener, HeosBridgeHandler bridge) { + super(bridge); + this.eventListener = eventListener; } @Override - protected void handleCommandPlayer() { + public void handlePlayerCommand(Command command, String id, ThingUID uid) throws IOException, ReadException { if (command instanceof RefreshType) { - api.getHeosPlayerVolume(id); + eventListener.playerStateChangeEvent(getApi().getPlayerVolume(id)); return; } if (command instanceof IncreaseDecreaseType) { - if (IncreaseDecreaseType.INCREASE.equals(command)) { - api.increaseVolume(id); + if (IncreaseDecreaseType.INCREASE == command) { + getApi().increaseVolume(id); } else { - api.decreaseVolume(id); + getApi().decreaseVolume(id); } } else { - api.setVolume(command.toString(), id); + getApi().setVolume(command.toString(), id); } } @Override - protected void handleCommandGroup() { + public void handleGroupCommand(Command command, @Nullable String id, ThingUID uid, + HeosGroupHandler heosGroupHandler) throws IOException, ReadException { + if (id == null) { + throw new HeosNotFoundException(); + } + if (command instanceof RefreshType) { - api.getHeosGroupVolume(id); + eventListener.playerStateChangeEvent(getApi().getGroupVolume(id)); return; } if (command instanceof IncreaseDecreaseType) { - if (IncreaseDecreaseType.INCREASE.equals(command)) { - api.increaseGroupVolume(id); + if (IncreaseDecreaseType.INCREASE == command) { + getApi().increaseGroupVolume(id); } else { - api.decreaseGroupVolume(id); + getApi().decreaseGroupVolume(id); } } else { - api.volumeGroup(command.toString(), id); + getApi().volumeGroup(command.toString(), id); } } @Override - protected void handleCommandBridge() { + public void handleBridgeCommand(Command command, ThingUID uid) { // not used on bridge } } diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosDynamicStateDescriptionProvider.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosDynamicStateDescriptionProvider.java new file mode 100644 index 0000000000000..eb73e33650822 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosDynamicStateDescriptionProvider.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import java.util.List; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.binding.BaseDynamicStateDescriptionProvider; +import org.eclipse.smarthome.core.thing.type.DynamicStateDescriptionProvider; +import org.eclipse.smarthome.core.types.StateOption; +import org.openhab.binding.heos.internal.json.payload.BrowseResult; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.json.payload.YesNoEnum; +import org.osgi.service.component.annotations.Component; + +/** + * Dynamically create the users list of favorites and playlists. + * + * @author Martin van Wingerden - Initial contribution + */ +@Component(service = { DynamicStateDescriptionProvider.class, HeosDynamicStateDescriptionProvider.class }) +@NonNullByDefault +public class HeosDynamicStateDescriptionProvider extends BaseDynamicStateDescriptionProvider { + + String getValueByLabel(ChannelUID channelUID, String input) { + Optional optionalValueByLabel = channelOptionsMap.get(channelUID).stream() + .filter(o -> input.equals(o.getLabel())).map(StateOption::getValue).findFirst(); + + // if no match was found we assume that it already was a value and not a label + return optionalValueByLabel.orElse(input); + } + + public void setFavorites(ChannelUID channelUID, List favorites) { + setBrowseResultList(channelUID, favorites, d -> d.mediaId); + } + + public void setPlaylists(ChannelUID channelUID, List playLists) { + setBrowseResultList(channelUID, playLists, d -> d.containerId); + } + + private void setBrowseResultList(ChannelUID channelUID, List playlists, + Function function) { + setStateOptions(channelUID, + playlists.stream().filter(browseResult -> browseResult.playable == YesNoEnum.YES) + .map(browseResult -> getStateOption(function, browseResult)).filter(Optional::isPresent) + .map(Optional::get).collect(Collectors.toList())); + } + + private Optional getStateOption(Function function, + BrowseResult browseResult) { + @Nullable + String identifier = function.apply(browseResult); + if (identifier != null) { + return Optional.of(new StateOption(identifier, browseResult.name)); + } else { + return Optional.empty(); + } + } + + public void setQueue(ChannelUID channelUID, List queue) { + setStateOptions(channelUID, + queue.stream().map(m -> new StateOption(String.valueOf(m.queueId), m.combinedSongArtist())) + .collect(Collectors.toList())); + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosGroupHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosGroupHandler.java new file mode 100644 index 0000000000000..947de1e31b887 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosGroupHandler.java @@ -0,0 +1,301 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import static org.openhab.binding.heos.internal.HeosBindingConstants.*; +import static org.openhab.binding.heos.internal.handler.FutureUtil.cancel; +import static org.openhab.binding.heos.internal.json.dto.HeosEvent.PLAYER_VOLUME_CHANGED; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.library.types.PlayPauseType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.heos.internal.configuration.GroupConfiguration; +import org.openhab.binding.heos.internal.exception.HeosFunctionalException; +import org.openhab.binding.heos.internal.exception.HeosNotConnectedException; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.json.dto.HeosCommunicationAttribute; +import org.openhab.binding.heos.internal.json.dto.HeosEventObject; +import org.openhab.binding.heos.internal.json.dto.HeosResponseObject; +import org.openhab.binding.heos.internal.json.payload.Group; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.resources.HeosGroup; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link HeosGroupHandler} handles the actions for a HEOS group. + * Channel commands are received and send to the dedicated channels + * + * @author Johannes Einig - Initial contribution + */ +@NonNullByDefault +public class HeosGroupHandler extends HeosThingBaseHandler { + private final Logger logger = LoggerFactory.getLogger(HeosGroupHandler.class); + + private @NonNullByDefault({}) GroupConfiguration configuration; + private @Nullable String gid; + + private boolean blockInitialization; + private @Nullable Future scheduledStartupFuture; + + public HeosGroupHandler(Thing thing, HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider) { + super(thing, heosDynamicStateDescriptionProvider); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // The GID is null if there is no group online with the groupMemberHash + // Only commands from the UNGROUP channel are passed through + // to activate the group if it is offline + if (gid != null || CH_ID_UNGROUP.equals(channelUID.getId())) { + @Nullable + HeosChannelHandler channelHandler = getHeosChannelHandler(channelUID); + if (channelHandler != null) { + try { + @Nullable + String id = getMaybeId(channelUID, command); + channelHandler.handleGroupCommand(command, id, thing.getUID(), this); + handleSuccess(); + } catch (IOException | ReadException e) { + handleError(e); + } + } + } + } + + @Nullable + private String getMaybeId(ChannelUID channelUID, Command command) throws HeosNotFoundException { + if (isCreateGroupRequest(channelUID, command)) { + return null; + } else { + return getId(); + } + } + + private boolean isCreateGroupRequest(ChannelUID channelUID, Command command) { + return CH_ID_UNGROUP.equals(channelUID.getId()) && OnOffType.ON == command; + } + + /** + * Initialize the HEOS group. Starts an extra thread to avoid blocking + * during start up phase. Gathering all information can take longer + * than 5 seconds which can throw an error within the openHAB system. + */ + @Override + public synchronized void initialize() { + super.initialize(); + + configuration = thing.getConfiguration().as(GroupConfiguration.class); + + // Prevents that initialize() is called multiple times if group goes online + blockInitialization = true; + + scheduledStartUp(); + } + + @Override + public void dispose() { + cancel(scheduledStartupFuture); + super.dispose(); + } + + @Override + public String getId() throws HeosNotFoundException { + @Nullable + String localGroupId = this.gid; + if (localGroupId == null) { + throw new HeosNotFoundException(); + } + return localGroupId; + } + + public String getGroupMemberHash() { + return HeosGroup.calculateGroupMemberHash(configuration.members); + } + + public String[] getGroupMemberPidList() { + return configuration.members.split(";"); + } + + @Override + public void setNotificationSoundVolume(PercentType volume) { + super.setNotificationSoundVolume(volume); + try { + getApiConnection().volumeGroup(volume.toString(), getId()); + } catch (IOException | ReadException e) { + logger.warn("Failed to set notification volume", e); + } + } + + @Override + public void playerStateChangeEvent(HeosEventObject eventObject) { + if (ThingStatus.UNINITIALIZED == getThing().getStatus()) { + logger.debug("Can't Handle Event. Group {} not initialized. Status is: {}", getConfig().get(PROP_NAME), + getThing().getStatus()); + return; + } + + @Nullable + String localGid = this.gid; + @Nullable + String eventGroupId = eventObject.getAttribute(HeosCommunicationAttribute.GROUP_ID); + @Nullable + String eventPlayerId = eventObject.getAttribute(HeosCommunicationAttribute.PLAYER_ID); + if (localGid == null || !(localGid.equals(eventGroupId) || localGid.equals(eventPlayerId))) { + return; + } + + if (PLAYER_VOLUME_CHANGED.equals(eventObject.command)) { + logger.debug("Ignoring player-volume changes for groups"); + return; + } + + handleThingStateUpdate(eventObject); + } + + @Override + public void playerStateChangeEvent(HeosResponseObject responseObject) throws HeosFunctionalException { + if (ThingStatus.UNINITIALIZED == getThing().getStatus()) { + logger.debug("Can't Handle Event. Group {} not initialized. Status is: {}", getConfig().get(PROP_NAME), + getThing().getStatus()); + return; + } + + @Nullable + String localGid = this.gid; + if (localGid == null || !localGid.equals(responseObject.getAttribute(HeosCommunicationAttribute.GROUP_ID))) { + return; + } + + handleThingStateUpdate(responseObject); + } + + @Override + public void playerMediaChangeEvent(String pid, Media media) { + if (!pid.equals(gid)) { + return; + } + + handleThingMediaUpdate(media); + } + + /** + * Sets the status of the HEOS group to OFFLINE. + * Also sets the UNGROUP channel to OFF and the CONTROL + * channel to PAUSE + */ + @Override + public void setStatusOffline() { + logger.debug("Status was set offline"); + try { + getApiConnection().unregisterForChangeEvents(this); + } catch (HeosNotConnectedException e) { + logger.debug("Not connected, failed to unregister"); + } + updateState(CH_ID_UNGROUP, OnOffType.OFF); + updateState(CH_ID_CONTROL, PlayPauseType.PAUSE); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DISABLED, "Group is not available on HEOS system"); + } + + @Override + public void setStatusOnline() { + if (!blockInitialization) { + initialize(); + } else { + logger.debug("Not initializing from setStatusOnline ({}, {})", thing.getStatus(), blockInitialization); + } + } + + private void updateConfiguration(String groupId, Group group) { + Map prop = new HashMap<>(); + prop.put(PROP_NAME, group.name); + prop.put(PROP_GROUP_MEMBERS, group.getGroupMemberIds()); + prop.put(PROP_GROUP_LEADER, group.getLeaderId()); + prop.put(PROP_GROUP_HASH, HeosGroup.calculateGroupMemberHash(group)); + prop.put(PROP_GID, groupId); + updateProperties(prop); + } + + private void scheduledStartUp() { + cancel(scheduledStartupFuture); + scheduledStartupFuture = scheduler.submit(this::delayedInitialize); + } + + private void delayedInitialize() { + @Nullable + HeosBridgeHandler bridgeHandler = this.bridgeHandler; + + if (bridgeHandler == null) { + logger.debug("Bridge handler not found, rescheduling"); + scheduledStartUp(); + return; + } + + if (bridgeHandler.isLoggedIn()) { + handleDynamicStatesSignedIn(); + } + + bridgeHandler.addGroupHandlerInformation(this); + // Checks if there is a group online with the same group member hash. + // If not setting the group offline. + @Nullable + String groupId = bridgeHandler.getActualGID(HeosGroup.calculateGroupMemberHash(configuration.members)); + if (groupId == null) { + blockInitialization = false; + setStatusOffline(); + } else { + try { + refreshPlayState(groupId); + + HeosResponseObject response = getApiConnection().getGroupInfo(groupId); + @Nullable + Group group = response.payload; + if (group == null) { + throw new IllegalStateException("Invalid group response received"); + } + + gid = groupId; + updateConfiguration(groupId, group); + updateStatus(ThingStatus.ONLINE); + updateState(CH_ID_UNGROUP, OnOffType.ON); + blockInitialization = false; + } catch (IOException | ReadException | IllegalStateException e) { + logger.debug("Failed initializing, will retry", e); + cancel(scheduledStartupFuture, false); + scheduledStartupFuture = scheduler.schedule(this::delayedInitialize, 30, TimeUnit.SECONDS); + } + } + } + + @Override + void refreshPlayState(String id) throws IOException, ReadException { + super.refreshPlayState(id); + + handleThingStateUpdate(getApiConnection().getGroupMuteState(id)); + handleThingStateUpdate(getApiConnection().getGroupVolume(id)); + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosPlayerHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosPlayerHandler.java new file mode 100644 index 0000000000000..3247d03db171d --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosPlayerHandler.java @@ -0,0 +1,184 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import static org.openhab.binding.heos.internal.HeosBindingConstants.*; +import static org.openhab.binding.heos.internal.handler.FutureUtil.cancel; +import static org.openhab.binding.heos.internal.json.dto.HeosCommunicationAttribute.PLAYER_ID; +import static org.openhab.binding.heos.internal.json.dto.HeosEvent.GROUP_VOLUME_CHANGED; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.heos.internal.configuration.PlayerConfiguration; +import org.openhab.binding.heos.internal.exception.HeosFunctionalException; +import org.openhab.binding.heos.internal.json.dto.HeosErrorCode; +import org.openhab.binding.heos.internal.json.dto.HeosEventObject; +import org.openhab.binding.heos.internal.json.dto.HeosResponseObject; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.json.payload.Player; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link HeosPlayerHandler} handles the actions for a HEOS player. + * Channel commands are received and send to the dedicated channels + * + * @author Johannes Einig - Initial contribution + */ +@NonNullByDefault +public class HeosPlayerHandler extends HeosThingBaseHandler { + private final Logger logger = LoggerFactory.getLogger(HeosPlayerHandler.class); + + private @NonNullByDefault({}) String pid; + private @Nullable Future scheduledFuture; + + public HeosPlayerHandler(Thing thing, HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider) { + super(thing, heosDynamicStateDescriptionProvider); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + @Nullable + HeosChannelHandler channelHandler = getHeosChannelHandler(channelUID); + if (channelHandler != null) { + try { + channelHandler.handlePlayerCommand(command, getId(), thing.getUID()); + handleSuccess(); + } catch (IOException | ReadException e) { + handleError(e); + } + } + } + + @Override + public void initialize() { + super.initialize(); + + PlayerConfiguration configuration = thing.getConfiguration().as(PlayerConfiguration.class); + pid = configuration.pid; + + cancel(scheduledFuture); + scheduledFuture = scheduler.submit(this::delayedInitialize); + } + + private synchronized void delayedInitialize() { + try { + refreshPlayState(pid); + + handleThingStateUpdate(getApiConnection().getPlayerInfo(pid)); + + updateStatus(ThingStatus.ONLINE); + } catch (HeosFunctionalException e) { + if (e.getCode() == HeosErrorCode.INVALID_ID) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.GONE, e.getCode().toString()); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getCode().toString()); + } + } catch (IOException | ReadException e) { + logger.debug("Failed to initialize, will try again", e); + cancel(scheduledFuture, false); + scheduledFuture = scheduler.schedule(this::delayedInitialize, 3, TimeUnit.SECONDS); + } + } + + @Override + void refreshPlayState(String id) throws IOException, ReadException { + super.refreshPlayState(id); + + handleThingStateUpdate(getApiConnection().getPlayerMuteState(id)); + handleThingStateUpdate(getApiConnection().getPlayerVolume(id)); + } + + @Override + public void dispose() { + cancel(scheduledFuture); + super.dispose(); + } + + @Override + public String getId() { + return pid; + } + + @Override + public void setNotificationSoundVolume(PercentType volume) { + } + + @Override + public void playerStateChangeEvent(HeosEventObject eventObject) { + if (!pid.equals(eventObject.getAttribute(PLAYER_ID))) { + return; + } + + if (GROUP_VOLUME_CHANGED == eventObject.command) { + logger.debug("Ignoring group-volume changes for players"); + return; + } + + handleThingStateUpdate(eventObject); + } + + @Override + public void playerStateChangeEvent(HeosResponseObject responseObject) throws HeosFunctionalException { + if (!pid.equals(responseObject.getAttribute(PLAYER_ID))) { + return; + } + + handleThingStateUpdate(responseObject); + } + + @Override + public void playerMediaChangeEvent(String eventPid, Media media) { + if (!pid.equals(eventPid)) { + return; + } + + handleThingMediaUpdate(media); + } + + @Override + public void setStatusOffline() { + updateStatus(ThingStatus.OFFLINE); + } + + @Override + public void setStatusOnline() { + updateStatus(ThingStatus.ONLINE); + } + + public static void propertiesFromPlayer(Map prop, Player player) { + prop.put(PROP_NAME, player.name); + prop.put(PROP_PID, String.valueOf(player.playerId)); + prop.put(Thing.PROPERTY_MODEL_ID, player.model); + prop.put(Thing.PROPERTY_FIRMWARE_VERSION, player.version); + prop.put(PROP_NETWORK, player.network); + prop.put(PROP_IP, player.ip); + @Nullable + String serialNumber = player.serial; + if (serialNumber != null) { + prop.put(Thing.PROPERTY_SERIAL_NUMBER, serialNumber); + } + } +} diff --git a/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosThingBaseHandler.java b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosThingBaseHandler.java new file mode 100644 index 0000000000000..369c7dec99ed5 --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/main/java/org/openhab/binding/heos/internal/handler/HeosThingBaseHandler.java @@ -0,0 +1,516 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.handler; + +import static org.eclipse.smarthome.core.thing.ThingStatus.*; +import static org.openhab.binding.heos.internal.HeosBindingConstants.*; +import static org.openhab.binding.heos.internal.handler.FutureUtil.cancel; +import static org.openhab.binding.heos.internal.json.dto.HeosCommandGroup.GROUP; +import static org.openhab.binding.heos.internal.json.dto.HeosCommandGroup.PLAYER; +import static org.openhab.binding.heos.internal.json.dto.HeosCommunicationAttribute.*; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import javax.measure.quantity.Time; + +import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.*; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; +import org.eclipse.smarthome.core.thing.*; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.UnDefType; +import org.eclipse.smarthome.io.net.http.HttpUtil; +import org.openhab.binding.heos.internal.HeosChannelHandlerFactory; +import org.openhab.binding.heos.internal.api.HeosFacade; +import org.openhab.binding.heos.internal.exception.HeosFunctionalException; +import org.openhab.binding.heos.internal.exception.HeosNotConnectedException; +import org.openhab.binding.heos.internal.exception.HeosNotFoundException; +import org.openhab.binding.heos.internal.json.dto.*; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.json.payload.Player; +import org.openhab.binding.heos.internal.resources.HeosEventListener; +import org.openhab.binding.heos.internal.resources.Telnet.ReadException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link HeosThingBaseHandler} class is the base Class all HEOS handler have to extend. + * It provides basic command handling and common needed methods. + * + * @author Johannes Einig - Initial contribution + */ +@NonNullByDefault +public abstract class HeosThingBaseHandler extends BaseThingHandler implements HeosEventListener { + private final Logger logger = LoggerFactory.getLogger(HeosThingBaseHandler.class); + private final HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider; + private final ChannelUID favoritesChannelUID; + private final ChannelUID playlistsChannelUID; + private final ChannelUID queueChannelUID; + + private @Nullable HeosChannelHandlerFactory channelHandlerFactory; + protected @Nullable HeosBridgeHandler bridgeHandler; + + private String notificationVolume = "0"; + + private int failureCount; + private @Nullable Future scheduleQueueFetchFuture; + private @Nullable Future handleDynamicStatesFuture; + + HeosThingBaseHandler(Thing thing, HeosDynamicStateDescriptionProvider heosDynamicStateDescriptionProvider) { + super(thing); + this.heosDynamicStateDescriptionProvider = heosDynamicStateDescriptionProvider; + favoritesChannelUID = new ChannelUID(thing.getUID(), CH_ID_FAVORITES); + playlistsChannelUID = new ChannelUID(thing.getUID(), CH_ID_PLAYLISTS); + queueChannelUID = new ChannelUID(thing.getUID(), CH_ID_QUEUE); + } + + @Override + public void initialize() { + @Nullable + Bridge bridge = getBridge(); + @Nullable + HeosBridgeHandler localBridgeHandler; + if (bridge != null) { + localBridgeHandler = (HeosBridgeHandler) bridge.getHandler(); + if (localBridgeHandler != null) { + bridgeHandler = localBridgeHandler; + channelHandlerFactory = localBridgeHandler.getChannelHandlerFactory(); + } else { + updateStatus(OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + return; + } + } else { + logger.warn("No Bridge set within child handler"); + updateStatus(OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + return; + } + + try { + getApiConnection().registerForChangeEvents(this); + cancel(scheduleQueueFetchFuture); + scheduleQueueFetchFuture = scheduler.submit(this::fetchQueueFromPlayer); + + if (localBridgeHandler.isLoggedIn()) { + scheduleImmediatelyHandleDynamicStatesSignedIn(); + } + } catch (HeosNotConnectedException e) { + updateStatus(OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + } + } + + void handleSuccess() { + failureCount = 0; + updateStatus(ONLINE); + } + + void handleError(Exception e) { + logger.debug("Failed to handle player/group command", e); + failureCount++; + + if (failureCount > FAILURE_COUNT_LIMIT) { + updateStatus(OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Failed to handle command: " + e.getMessage()); + } + } + + public HeosFacade getApiConnection() throws HeosNotConnectedException { + @Nullable + HeosBridgeHandler localBridge = bridgeHandler; + if (localBridge != null) { + return localBridge.getApiConnection(); + } + throw new HeosNotConnectedException(); + } + + public abstract String getId() throws HeosNotFoundException; + + public abstract void setStatusOffline(); + + public abstract void setStatusOnline(); + + public PercentType getNotificationSoundVolume() { + return PercentType.valueOf(notificationVolume); + } + + public void setNotificationSoundVolume(PercentType volume) { + notificationVolume = volume.toString(); + } + + @Nullable + HeosChannelHandler getHeosChannelHandler(ChannelUID channelUID) { + @Nullable + HeosChannelHandlerFactory localChannelHandlerFactory = this.channelHandlerFactory; + return localChannelHandlerFactory != null ? localChannelHandlerFactory.getChannelHandler(channelUID, this, null) + : null; + } + + @Override + public void bridgeChangeEvent(String event, boolean success, Object command) { + logger.debug("BridgeChangeEvent: {}", command); + if (HeosEvent.USER_CHANGED == command) { + handleDynamicStatesSignedIn(); + } + + if (EVENT_TYPE_EVENT.equals(event)) { + if (HeosEvent.GROUPS_CHANGED == command) { + fetchQueueFromPlayer(); + } else if (CONNECTION_RESTORED.equals(command)) { + try { + refreshPlayState(getId()); + } catch (IOException | ReadException e) { + logger.debug("Failed to refreshPlayState", e); + } + } + } + } + + void scheduleImmediatelyHandleDynamicStatesSignedIn() { + cancel(handleDynamicStatesFuture); + handleDynamicStatesFuture = scheduler.submit(this::handleDynamicStatesSignedIn); + } + + void handleDynamicStatesSignedIn() { + try { + heosDynamicStateDescriptionProvider.setFavorites(favoritesChannelUID, getApiConnection().getFavorites()); + heosDynamicStateDescriptionProvider.setPlaylists(playlistsChannelUID, getApiConnection().getPlaylists()); + } catch (IOException | ReadException e) { + logger.debug("Failed to set favorites / playlists, rescheduling", e); + cancel(handleDynamicStatesFuture, false); + handleDynamicStatesFuture = scheduler.schedule(this::handleDynamicStatesSignedIn, 30, TimeUnit.SECONDS); + } + } + + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + if (ThingStatus.OFFLINE.equals(bridgeStatusInfo.getStatus())) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + } else if (ThingStatus.ONLINE.equals(bridgeStatusInfo.getStatus())) { + updateStatus(ThingStatus.ONLINE); + } else if (ThingStatus.UNINITIALIZED.equals(bridgeStatusInfo.getStatus())) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } + + /** + * Dispose the handler and unregister the handler + * form Change Events + */ + @Override + public void dispose() { + try { + logger.debug("Disposing this: {}", this); + getApiConnection().unregisterForChangeEvents(this); + } catch (HeosNotConnectedException e) { + logger.trace("No connection available while trying to unregister"); + } + + cancel(scheduleQueueFetchFuture); + cancel(handleDynamicStatesFuture); + } + + /** + * Plays a media file from an external source. Can be + * used for audio sink function + * + * @param urlStr The external URL where the file is located + * @throws ReadException + * @throws IOException + */ + public void playURL(String urlStr) throws IOException, ReadException { + try { + URL url = new URL(urlStr); + getApiConnection().playURL(getId(), url); + } catch (MalformedURLException e) { + logger.debug("Command '{}' is not a proper URL. Error: {}", urlStr, e.getMessage()); + } + } + + /** + * Handles the updates send from the HEOS system to + * the binding. To receive updates the handler has + * to register itself via {@link HeosFacade} via the method: + * {@link HeosFacade#registerForChangeEvents(HeosEventListener)} + * + * @param eventObject containing information about the even which was sent to us by the HEOS device + */ + protected void handleThingStateUpdate(HeosEventObject eventObject) { + updateStatus(ONLINE, ThingStatusDetail.NONE, "Receiving events"); + + @Nullable + HeosEvent command = eventObject.command; + + if (command == null) { + logger.debug("Ignoring event with null command"); + return; + } + + switch (command) { + + case PLAYER_STATE_CHANGED: + playerStateChanged(eventObject); + break; + + case PLAYER_VOLUME_CHANGED: + case GROUP_VOLUME_CHANGED: + @Nullable + String level = eventObject.getAttribute(LEVEL); + if (level != null) { + notificationVolume = level; + updateState(CH_ID_VOLUME, PercentType.valueOf(level)); + updateState(CH_ID_MUTE, OnOffType.from(eventObject.getBooleanAttribute(MUTE))); + } + break; + + case SHUFFLE_MODE_CHANGED: + handleShuffleMode(eventObject); + break; + + case PLAYER_NOW_PLAYING_PROGRESS: + @Nullable + Long position = eventObject.getNumericAttribute(CURRENT_POSITION); + @Nullable + Long duration = eventObject.getNumericAttribute(DURATION); + if (position != null && duration != null) { + updateState(CH_ID_CUR_POS, quantityFromMilliSeconds(position)); + updateState(CH_ID_DURATION, quantityFromMilliSeconds(duration)); + } + break; + + case REPEAT_MODE_CHANGED: + handleRepeatMode(eventObject); + break; + + case PLAYER_PLAYBACK_ERROR: + updateStatus(UNKNOWN, ThingStatusDetail.NONE, eventObject.getAttribute(ERROR)); + break; + + case PLAYER_QUEUE_CHANGED: + fetchQueueFromPlayer(); + break; + + case SOURCES_CHANGED: + // we are not yet handling the actual sources, although we might want to do that in the future + logger.trace("Ignoring {}, support might be added in the future", command); + break; + + case GROUPS_CHANGED: + case PLAYERS_CHANGED: + case PLAYER_NOW_PLAYING_CHANGED: + case USER_CHANGED: + logger.trace("Ignoring {}, will be handled inside HeosEventController", command); + break; + } + } + + private QuantityType diff --git a/bundles/org.openhab.binding.heos/src/main/resources/ESH-INF/thing/HeosSystem.xml b/bundles/org.openhab.binding.heos/src/main/resources/ESH-INF/thing/HeosSystem.xml index 22b21bc5c2ecd..30a5e14cf126c 100644 --- a/bundles/org.openhab.binding.heos/src/main/resources/ESH-INF/thing/HeosSystem.xml +++ b/bundles/org.openhab.binding.heos/src/main/resources/ESH-INF/thing/HeosSystem.xml @@ -11,7 +11,7 @@ - Role + vendor network-address @@ -30,7 +30,7 @@ Password for login to the HEOS account false - + false seconds @@ -41,4 +41,3 @@ - diff --git a/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/HeosJsonParserEventTest.java b/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/HeosJsonParserEventTest.java new file mode 100644 index 0000000000000..80a43e6c8c1be --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/HeosJsonParserEventTest.java @@ -0,0 +1,288 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.json; + +import static java.lang.Long.valueOf; +import static org.junit.Assert.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Test; +import org.openhab.binding.heos.internal.json.dto.HeosCommunicationAttribute; +import org.openhab.binding.heos.internal.json.dto.HeosEvent; +import org.openhab.binding.heos.internal.json.dto.HeosEventObject; + +/** + * Tests to validate the functioning of the HeosJsonParser specifically for event objects + * + * @author Martin van Wingerden - Initial Contribution + */ +@NonNullByDefault +public class HeosJsonParserEventTest { + + private final HeosJsonParser subject = new HeosJsonParser(); + + @Test + public void event_now_playing_changed() { + HeosEventObject event = subject.parseEvent( + "{\"heos\": {\"command\": \"event/player_now_playing_changed\", \"message\": \"pid=1679855527\"}}"); + + assertEquals(HeosEvent.PLAYER_NOW_PLAYING_CHANGED, event.command); + assertEquals("event/player_now_playing_changed", event.rawCommand); + assertEquals(valueOf(1679855527), event.getNumericAttribute(HeosCommunicationAttribute.PLAYER_ID)); + } + + @Test + public void event_now_playing_progress() { + HeosEventObject event = subject.parseEvent( + "{\"heos\": {\"command\": \"event/player_now_playing_progress\", \"message\": \"pid=1679855527&cur_pos=224848000&duration=0\"}}"); + + assertEquals(HeosEvent.PLAYER_NOW_PLAYING_PROGRESS, event.command); + assertEquals("event/player_now_playing_progress", event.rawCommand); + assertEquals(valueOf(1679855527), event.getNumericAttribute(HeosCommunicationAttribute.PLAYER_ID)); + assertEquals(valueOf(224848000), event.getNumericAttribute(HeosCommunicationAttribute.CURRENT_POSITION)); + assertEquals(valueOf(0), event.getNumericAttribute(HeosCommunicationAttribute.DURATION)); + } + + @Test + public void event_state_changed() { + HeosEventObject event = subject.parseEvent( + "{\"heos\": {\"command\": \"event/player_state_changed\", \"message\": \"pid=1679855527&state=play\"}}"); + + assertEquals(HeosEvent.PLAYER_STATE_CHANGED, event.command); + assertEquals("event/player_state_changed", event.rawCommand); + assertEquals(valueOf(1679855527), event.getNumericAttribute(HeosCommunicationAttribute.PLAYER_ID)); + assertEquals("play", event.getAttribute(HeosCommunicationAttribute.STATE)); + } + + @Test + public void event_playback_error() { + HeosEventObject event = subject.parseEvent( + "{\"heos\": {\"command\": \"event/player_playback_error\", \"message\": \"pid=1679855527&error=Could Not Download\"}}"); + + assertEquals(HeosEvent.PLAYER_PLAYBACK_ERROR, event.command); + assertEquals("event/player_playback_error", event.rawCommand); + assertEquals(valueOf(1679855527), event.getNumericAttribute(HeosCommunicationAttribute.PLAYER_ID)); + assertEquals("Could Not Download", event.getAttribute(HeosCommunicationAttribute.ERROR)); + } + + @Test + public void event_volume_changed() { + HeosEventObject event = subject.parseEvent( + "{\"heos\": {\"command\": \"event/player_volume_changed\", \"message\": \"pid=1958912779&level=23&mute=off\"}}"); + + assertEquals(HeosEvent.PLAYER_VOLUME_CHANGED, event.command); + assertEquals("event/player_volume_changed", event.rawCommand); + assertEquals(valueOf(1958912779), event.getNumericAttribute(HeosCommunicationAttribute.PLAYER_ID)); + assertEquals(valueOf(23), event.getNumericAttribute(HeosCommunicationAttribute.LEVEL)); + assertFalse(event.getBooleanAttribute(HeosCommunicationAttribute.MUTE)); + } + + @Test + public void event_shuffle_mode_changed() { + HeosEventObject event = subject.parseEvent( + "{\"heos\": {\"command\": \"event/shuffle_mode_changed\", \"message\": \"pid=-831584083&shuffle=on\"}}"); + + assertEquals(HeosEvent.SHUFFLE_MODE_CHANGED, event.command); + assertEquals("event/shuffle_mode_changed", event.rawCommand); + assertEquals(valueOf(-831584083), event.getNumericAttribute(HeosCommunicationAttribute.PLAYER_ID)); + assertTrue(event.getBooleanAttribute(HeosCommunicationAttribute.SHUFFLE)); + } + + @Test + public void event_sources_changed() { + HeosEventObject event = subject.parseEvent("{\"heos\": {\"command\": \"event/sources_changed\"}}"); + + assertEquals(HeosEvent.SOURCES_CHANGED, event.command); + assertEquals("event/sources_changed", event.rawCommand); + } + + @Test + public void event_user_changed() { + HeosEventObject event = subject.parseEvent( + "{\"heos\": {\"command\": \"event/user_changed\", \"message\": \"signed_in&un=martinvw@mtin.nl\"}}"); + + assertEquals(HeosEvent.USER_CHANGED, event.command); + assertEquals("event/user_changed", event.rawCommand); + assertTrue(event.hasAttribute(HeosCommunicationAttribute.SIGNED_IN)); + assertEquals("martinvw@mtin.nl", event.getAttribute(HeosCommunicationAttribute.USERNAME)); + } + + @Test + public void event_unknown_event() { + HeosEventObject event = subject.parseEvent("{\"heos\": {\"command\": \"event/does_not_exist\"}}"); + + assertNull(event.command); + assertEquals("event/does_not_exist", event.rawCommand); + } + + @Test + public void event_duplicate_attributes() { + HeosEventObject event = subject.parseEvent( + "{\"heos\": {\"command\": \"event/does_not_exist\", \"message\": \"signed_in&un=test1&un=test2\"}}"); + + // the first one is ignored but it does not crash + assertEquals("test2", event.getAttribute(HeosCommunicationAttribute.USERNAME)); + } + + @Test + public void event_non_numeric() { + HeosEventObject event = subject + .parseEvent("{\"heos\": {\"command\": \"event/does_not_exist\", \"message\": \"pid=test\"}}"); + + // the first one is ignored but it does not crash + assertNull(event.getNumericAttribute(HeosCommunicationAttribute.PLAYER_ID)); + } + + @Test + public void event_numeric_missing() { + HeosEventObject event = subject.parseEvent("{\"heos\": {\"command\": \"event/does_not_exist\"}}"); + + // the first one is ignored but it does not crash + assertNull(event.getAttribute(HeosCommunicationAttribute.PLAYER_ID)); + } + + /* + * + * {"heos": {"command": "browse/browse", "result": "success", "message": "command under process&sid=1025"}} + * {"heos": {"command": "browse/browse", "result": "success", "message": "command under process&sid=1028"}} + * {"heos": {"command": "browse/browse", "result": "success", "message": "sid=1025&returned=6&count=6"}, "payload": + * [{"container": "yes", "type": "playlist", "cid": "132562", "playable": "yes", "name": + * "Maaike Ouboter - En hoe het dan ook weer dag wordt", "image_url": ""}, {"container": "yes", "type": "playlist", + * "cid": "132563", "playable": "yes", "name": "Maaike Ouboter - Vanaf nu is het van jou", "image_url": ""}, + * {"container": "yes", "type": "playlist", "cid": "162887", "playable": "yes", "name": "Easy listening", + * "image_url": ""}, {"container": "yes", "type": "playlist", "cid": "174461", "playable": "yes", "name": + * "Nieuwe muziek 5-2019", "image_url": ""}, {"container": "yes", "type": "playlist", "cid": "194000", "playable": + * "yes", "name": "Nieuwe muziek 2019-05", "image_url": ""}, {"container": "yes", "type": "playlist", "cid": + * "194001", "playable": "yes", "name": "Clean Bandit", "image_url": ""}]} + * {"heos": {"command": "browse/browse", "result": "success", "message": "sid=1028&returned=3&count=3"}, "payload": + * [{"container": "no", "mid": "s6707", "type": "station", "playable": "yes", "name": + * "NPO 3FM 96.8 (Top 40 %26 Pop Music)", "image_url": + * "http://cdn-profiles.tunein.com/s6707/images/logoq.png?t=636268"}, {"container": "no", "mid": "s2967", "type": + * "station", "playable": "yes", "name": "Classic FM Nederland (Classical Music)", "image_url": + * "http://cdn-radiotime-logos.tunein.com/s2967q.png"}, {"container": "no", "mid": "s1993", "type": "station", + * "playable": "yes", "name": "BNR Nieuwsradio", "image_url": "http://cdn-radiotime-logos.tunein.com/s1993q.png"}], + * "options": [{"browse": [{"id": 20, "name": "Remove from HEOS Favorites"}]}]} + * {"heos": {"command": "event/user_changed", "message": "signed_in&un=martinvw@mtin.nl"}} + * {"heos": {"command": "group/get_groups", "result": "success", "message": ""}, "payload": []} + * {"heos": {"command": "player/get_mute", "result": "fail", "message": "eid=2&text=ID Not Valid&pid=null"}} + * {"heos": {"command": "player/get_mute", "result": "success", "message": "pid=1958912779&state=off"}} + * {"heos": {"command": "player/get_mute", "result": "success", "message": "pid=1958912779&state=on"}} + * {"heos": {"command": "player/get_mute", "result": "success", "message": "pid=-831584083&state=off"}} + * {"heos": {"command": "player/get_mute", "result": "success", "message": "pid=-831584083&state=on"}} + * {"heos": {"command": "player/get_now_playing_media", "result": "fail", "message": + * "eid=2&text=ID Not Valid&pid=null"}} + * {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=1679855527"}, + * "payload": {"type": "song", "song": "", "album": "", "artist": "", "image_url": "", "album_id": "1", "mid": "1", + * "qid": 1, "sid": 1024}, "options": []} + * {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=1958912779"}, + * "payload": {"type": "song", "song": "Solo (feat. Demi Lovato)", "album": "What Is Love? (Deluxe)", "artist": + * "Clean Bandit", "image_url": + * "http://192.168.1.230:8015//m-browsableMediaUri/getImageFromTag/mnt/326C72A3E307501E47DE2B0F47D90EB8/Clean%20Bandit/What%20Is%20Love_%20(Deluxe)/03%20Solo%20(feat.%20Demi%20Lovato).m4a", + * "album_id": "", "mid": + * "http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/Clean+Bandit/What+Is+Love_+(Deluxe)/03+Solo+(feat.+Demi+Lovato).m4a", + * "qid": 1, "sid": 1024}, "options": []} + * {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=1958912779"}, + * "payload": {"type": "station", "song": "HEOS Bar - HDMI 2", "station": "HEOS Bar - HDMI 2", "album": "", + * "artist": "", "image_url": "", "album_id": "inputs", "mid": "inputs/hdmi_in_2", "qid": 1, "sid": 1027}, + * "options": []} + * {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=1958912779"}, + * "payload": {"type": "station", "song": "HEOS Bar - HDMI 3", "station": "HEOS Bar - HDMI 3", "album": "", + * "artist": "", "image_url": "", "album_id": "inputs", "mid": "inputs/hdmi_in_3", "qid": 1, "sid": 1027}, + * "options": []} + * {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=-831584083"}, + * "payload": {"type": "song", "song": "Applejack", "album": + * "The Real... Dolly Parton: The Ultimate Dolly Parton Collection", "artist": "Dolly Parton", "image_url": + * "http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/getImageFromTag/Dolly%20Parton/The%20Real%20Dolly%20Parton%20%5bDisc%202%5d/2-07%20Applejack.m4a", + * "album_id": "m-1c176905-f6c7-d168-dc35-86b4735c5976/alb/a-418", "mid": + * "m-1c176905-f6c7-d168-dc35-86b4735c5976/alb/a-418/t-4150", "qid": 43, "sid": 1024}, "options": []} + * {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=-831584083"}, + * "payload": {"type": "song", "song": "Dancing Queen", "album": "ABBA Gold: Greatest Hits", "artist": "ABBA", + * "image_url": + * "http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/getImageFromTag/ABBA/ABBA%20Gold_%20Greatest%20Hits/01%20Dancing%20Queen%201.m4a", + * "album_id": "m-1c176905-f6c7-d168-dc35-86b4735c5976/alb/a-398", "mid": + * "m-1c176905-f6c7-d168-dc35-86b4735c5976/alb/a-398/t-4237", "qid": 1, "sid": 1024}, "options": []} + * {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=-831584083"}, + * "payload": {"type": "song", "song": "D.I.V.O.R.C.E.", "album": + * "The Real... Dolly Parton: The Ultimate Dolly Parton Collection", "artist": "Dolly Parton", "image_url": + * "http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/getImageFromTag/Dolly%20Parton/The%20Real%20Dolly%20Parton%20%5bDisc%201%5d/1-03%20D.I.V.O.R.C.E.m4a", + * "album_id": "m-1c176905-f6c7-d168-dc35-86b4735c5976/alb/a-417", "mid": + * "m-1c176905-f6c7-d168-dc35-86b4735c5976/alb/a-417/t-4138", "qid": 22, "sid": 1024}, "options": []} + * {"heos": {"command": "player/get_now_playing_media", "result": "success", "message": "pid=-831584083"}, + * "payload": {"type": "song", "song": "Homeward Bound", "album": "The Very Best Of Art Garfunkel: Across America", + * "artist": "Art Garfunkel", "image_url": + * "http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/getImageFromTag/Art%20Garfunkel/The%20Very%20Best%20Of%20Art%20Garfunkel_%20Across%20A/06%20-%20Art%20Garfunkel%20-%20Homeward%20Bound.mp3", + * "album_id": "m-1c176905-f6c7-d168-dc35-86b4735c5976/alb/a-127", "mid": + * "m-1c176905-f6c7-d168-dc35-86b4735c5976/alb/a-127/t-1385", "qid": 80, "sid": 1024}, "options": []} + * {"heos": {"command": "player/get_player_info", "result": "success", "message": "pid=1958912779"}, "payload": + * {"name": "HEOS Bar", "pid": 1958912779, "model": "HEOS Bar", "version": "1.520.200", "ip": "192.168.1.195", + * "network": "wired", "lineout": 0, "serial": "ADAG9180917029"}} + * {"heos": {"command": "player/get_player_info", "result": "success", "message": "pid=-831584083"}, "payload": + * {"name": "Kantoor HEOS 3", "pid": -831584083, "model": "HEOS 3", "version": "1.520.200", "ip": "192.168.1.230", + * "network": "wired", "lineout": 0, "serial": "ACNG9180110887"}} + * {"heos": {"command": "player/get_players", "result": "success", "message": ""}, "payload": [{"name": "HEOS Bar", + * "pid": 1958912779, "model": "HEOS Bar", "version": "1.520.200", "ip": "192.168.1.195", "network": "wired", + * "lineout": 0, "serial": "ADAG9180917029"}, {"name": "Kantoor HEOS 3", "pid": -831584083, "model": "HEOS 3", + * "version": "1.520.200", "ip": "192.168.1.230", "network": "wired", "lineout": 0, "serial": "ACNG9180110887"}]} + * {"heos": {"command": "player/get_players", "result": "success", "message": ""}, "payload": [{"name": + * "Kantoor HEOS 3", "pid": -831584083, "model": "HEOS 3", "version": "1.520.200", "ip": "192.168.1.230", "network": + * "wired", "lineout": 0, "serial": "ACNG9180110887"}, {"name": "HEOS Bar", "pid": 1958912779, "model": "HEOS Bar", + * "version": "1.520.200", "ip": "192.168.1.195", "network": "wired", "lineout": 0, "serial": "ADAG9180917029"}]} + * {"heos": {"command": "player/get_play_mode", "result": "fail", "message": "eid=2&text=ID Not Valid&pid=null"}} + * {"heos": {"command": "player/get_play_mode", "result": "success", "message": + * "pid=1958912779&repeat=off&shuffle=off"}} + * {"heos": {"command": "player/get_play_mode", "result": "success", "message": + * "pid=-831584083&repeat=off&shuffle=on"}} + * {"heos": {"command": "player/get_play_state", "result": "fail", "message": "eid=2&text=ID Not Valid&pid=null"}} + * {"heos": {"command": "player/get_play_state", "result": "success", "message": "pid=1958912779&state=stop"}} + * {"heos": {"command": "player/get_play_state", "result": "success", "message": "pid=-831584083&state=pause"}} + * {"heos": {"command": "player/get_play_state", "result": "success", "message": "pid=-831584083&state=play"}} + * {"heos": {"command": "player/get_play_state", "result": "success", "message": "pid=-831584083&state=stop"}} + * {"heos": {"command": "player/get_volume", "result": "fail", "message": "eid=2&text=ID Not Valid&pid=null"}} + * {"heos": {"command": "player/get_volume", "result": "success", "message": "pid=1958912779&level=14"}} + * {"heos": {"command": "player/get_volume", "result": "success", "message": "pid=1958912779&level=21"}} + * {"heos": {"command": "player/get_volume", "result": "success", "message": "pid=1958912779&level=23"}} + * {"heos": {"command": "player/get_volume", "result": "success", "message": "pid=-831584083&level=12"}} + * {"heos": {"command": "player/get_volume", "result": "success", "message": "pid=-831584083&level=15"}} + * {"heos": {"command": "player/play_next", "result": "success", "message": "pid=-831584083"}} + * {"heos": {"command": "player/play_previous", "result": "success", "message": "pid=-831584083"}} + * {"heos": {"command": "player/set_mute", "result": "success", "message": "pid=1958912779&state=off"}} + * {"heos": {"command": "player/set_mute", "result": "success", "message": "pid=1958912779&state=on"}} + * {"heos": {"command": "player/set_mute", "result": "success", "message": "pid=-831584083&state=off"}} + * {"heos": {"command": "player/set_mute", "result": "success", "message": "pid=-831584083&state=on"}} + * {"heos": {"command": "player/set_play_mode", "result": "success", "message": "pid=-831584083&shuffle=off"}} + * {"heos": {"command": "player/set_play_mode", "result": "success", "message": "pid=-831584083&shuffle=on"}} + * {"heos": {"command": "player/set_play_state", "result": "success", "message": "pid=-831584083&state=pause"}} + * {"heos": {"command": "player/set_play_state", "result": "success", "message": "pid=-831584083&state=play"}} + * {"heos": {"command": "player/set_volume", "result": "fail", "message": + * "eid=9&text=Out of range&pid=-831584083&level=OFF"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=1958912779&level=14"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=1958912779&level=17"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=-831584083&level=10"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=-831584083&level=12"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=-831584083&level=14"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=-831584083&level=15"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=-831584083&level=16"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=-831584083&level=18"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=-831584083&level=21"}} + * {"heos": {"command": "player/set_volume", "result": "success", "message": "pid=-831584083&level=4"}} + * {"heos": {"command": "player/volume_down", "result": "success", "message": "pid=-831584083&step=1"}} + * {"heos": {"command": "system/heart_beat", "result": "success", "message": ""}} + * {"heos": {"command": "system/register_for_change_events", "result": "success", "message": "enable=off"}} + * {"heos": {"command": "system/register_for_change_events", "result": "success", "message": "enable=on"}} + * {"heos": {"command": "system/register_for_change_events", "reult": "success", "message": "enable=on"}} + * {"heos": {"command": "system/sign_in", "result": "success", "message": + * "command under process&un=martinvw@mtin.nl&pw=Pl7WUFC61Q7zdQD5"}} + * {"heos": {"command": "system/sign_in", "result": "success", "message": "signed_in&un=martinvw@mtin.nl"}} + * + */ +} diff --git a/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/HeosJsonParserResponseTest.java b/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/HeosJsonParserResponseTest.java new file mode 100644 index 0000000000000..97ca0cd761faf --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/HeosJsonParserResponseTest.java @@ -0,0 +1,311 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.json; + +import static org.junit.Assert.*; +import static org.openhab.binding.heos.internal.json.dto.HeosCommunicationAttribute.*; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Test; +import org.openhab.binding.heos.internal.json.dto.HeosCommand; +import org.openhab.binding.heos.internal.json.dto.HeosCommandGroup; +import org.openhab.binding.heos.internal.json.dto.HeosErrorCode; +import org.openhab.binding.heos.internal.json.dto.HeosResponseObject; +import org.openhab.binding.heos.internal.json.payload.BrowseResult; +import org.openhab.binding.heos.internal.json.payload.BrowseResultType; +import org.openhab.binding.heos.internal.json.payload.Group; +import org.openhab.binding.heos.internal.json.payload.GroupPlayerRole; +import org.openhab.binding.heos.internal.json.payload.Media; +import org.openhab.binding.heos.internal.json.payload.Player; +import org.openhab.binding.heos.internal.json.payload.YesNoEnum; + +/** + * Tests to validate the functioning of the HeosJsonParser specifically for response objects + * + * @author Martin van Wingerden - Initial Contribution + */ +@NonNullByDefault +public class HeosJsonParserResponseTest { + + private final HeosJsonParser subject = new HeosJsonParser(); + + @Test + public void sign_in() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"system/sign_in\", \"result\": \"success\", \"message\": \"signed_in&un=test@example.org\"}}", + Void.class); + + assertEquals(HeosCommandGroup.SYSTEM, response.heosCommand.commandGroup); + assertEquals(HeosCommand.SIGN_IN, response.heosCommand.command); + assertTrue(response.result); + + assertEquals("test@example.org", response.getAttribute(USERNAME)); + assertTrue(response.hasAttribute(SIGNED_IN)); + } + + @Test + public void sign_in_under_process() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"system/sign_in\", \"message\": \"command under process\"}}", Void.class); + + assertEquals(HeosCommandGroup.SYSTEM, response.heosCommand.commandGroup); + assertEquals(HeosCommand.SIGN_IN, response.heosCommand.command); + assertFalse(response.result); + assertFalse(response.isFinished()); + } + + @Test + public void sign_in_failed() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"system/sign_in\", \"message\": \"eid=10&text=User not found\"}}", + Void.class); + + assertEquals(HeosCommandGroup.SYSTEM, response.heosCommand.commandGroup); + assertEquals(HeosCommand.SIGN_IN, response.heosCommand.command); + assertFalse(response.result); + assertTrue(response.isFinished()); + + assertEquals(HeosErrorCode.USER_NOT_FOUND, response.getError().code); + } + + @Test + public void get_mute() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"player/get_mute\", \"result\": \"success\", \"message\": \"pid=1958912779&state=on\"}}", + Void.class); + + assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup); + assertEquals(HeosCommand.GET_MUTE, response.heosCommand.command); + assertTrue(response.result); + + assertEquals(Long.valueOf(1958912779), response.getNumericAttribute(PLAYER_ID)); + assertTrue(response.getBooleanAttribute(STATE)); + } + + @Test + public void get_mute_error() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"player/get_mute\", \"result\": \"fail\", \"message\": \"eid=2&text=ID Not Valid&pid=null\"}}", + Void.class); + + assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup); + assertEquals(HeosCommand.GET_MUTE, response.heosCommand.command); + assertFalse(response.result); + + assertEquals(HeosErrorCode.INVALID_ID, response.getError().code); + } + + @Test + public void browse_browse_under_process() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"browse/browse\", \"result\": \"success\", \"message\": \"command under process&sid=1025\"}}", + Void.class); + + assertEquals(HeosCommandGroup.BROWSE, response.heosCommand.commandGroup); + assertEquals(HeosCommand.BROWSE, response.heosCommand.command); + assertTrue(response.result); + + assertEquals(Long.valueOf(1025), response.getNumericAttribute(SOURCE_ID)); + assertFalse(response.isFinished()); + } + + @Test + public void incorrect_level() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"player/set_volume\", \"result\": \"fail\", \"message\": \"eid=9&text=Parameter out of range&pid=-831584083&level=OFF\"}}", + Void.class); + + assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup); + assertEquals(HeosCommand.SET_VOLUME, response.heosCommand.command); + assertFalse(response.result); + + assertEquals(HeosErrorCode.PARAMETER_OUT_OF_RANGE, response.getError().code); + assertEquals("#9: Parameter out of range", response.getError().code.toString()); + } + + @Test + public void get_players() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"player/get_players\", \"result\": \"success\", \"message\": \"\"}, \"payload\": [" + + "{\"name\": \"Kantoor HEOS 3\", \"pid\": -831584083, \"model\": \"HEOS 3\", \"version\": \"1.520.200\", \"ip\": \"192.168.1.230\", \"network\": \"wired\", \"lineout\": 0, \"serial\": \"ACNG9180110887\"}, " + + "{\"name\": \"HEOS Bar\", \"pid\": 1958912779, \"model\": \"HEOS Bar\", \"version\": \"1.520.200\", \"ip\": \"192.168.1.195\", \"network\": \"wired\", \"lineout\": 0, \"serial\": \"ADAG9180917029\"}]}", + Player[].class); + + assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup); + assertEquals(HeosCommand.GET_PLAYERS, response.heosCommand.command); + assertTrue(response.result); + + assertEquals(2, response.payload.length); + Player player0 = response.payload[0]; + + assertEquals("Kantoor HEOS 3", player0.name); + assertEquals(-831584083, player0.playerId); + assertEquals("HEOS 3", player0.model); + assertEquals("1.520.200", player0.version); + assertEquals("192.168.1.230", player0.ip); + assertEquals("wired", player0.network); + assertEquals(0, player0.lineout); + assertEquals("ACNG9180110887", player0.serial); + + Player player1 = response.payload[1]; + + assertEquals("HEOS Bar", player1.name); + assertEquals(1958912779, player1.playerId); + assertEquals("HEOS Bar", player1.model); + assertEquals("1.520.200", player1.version); + assertEquals("192.168.1.195", player1.ip); + assertEquals("wired", player1.network); + assertEquals(0, player1.lineout); + assertEquals("ADAG9180917029", player1.serial); + } + + @Test + public void get_player_info() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"player/get_player_info\", \"result\": \"success\", \"message\": \"pid=1958912779\"}, \"payload\": {\"name\": \"HEOS Bar\", \"pid\": 1958912779, \"model\": \"HEOS Bar\", \"version\": \"1.520.200\", \"ip\": \"192.168.1.195\", \"network\": \"wired\", \"lineout\": 0, \"serial\": \"ADAG9180917029\"}}", + Player.class); + + assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup); + assertEquals(HeosCommand.GET_PLAYER_INFO, response.heosCommand.command); + assertTrue(response.result); + + assertEquals("HEOS Bar", response.payload.name); + assertEquals(1958912779, response.payload.playerId); + assertEquals("HEOS Bar", response.payload.model); + assertEquals("1.520.200", response.payload.version); + assertEquals("192.168.1.195", response.payload.ip); + assertEquals("wired", response.payload.network); + assertEquals(0, response.payload.lineout); + assertEquals("ADAG9180917029", response.payload.serial); + } + + @Test + public void get_now_playing_media() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"player/get_now_playing_media\", \"result\": \"success\", \"message\": \"pid=1958912779\"}, \"payload\": " + + "{\"type\": \"song\", \"song\": \"Solo (feat. Demi Lovato)\", \"album\": \"What Is Love? (Deluxe)\", \"artist\": \"Clean Bandit\", \"image_url\": \"http://192.168.1.230:8015//m-browsableMediaUri/getImageFromTag/mnt/326C72A3E307501E47DE2B0F47D90EB8/Clean%20Bandit/What%20Is%20Love_%20(Deluxe)/03%20Solo%20(feat.%20Demi%20Lovato).m4a\", \"album_id\": \"\", \"mid\": \"http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/Clean+Bandit/What+Is+Love_+(Deluxe)/03+Solo+(feat.+Demi+Lovato).m4a\", \"qid\": 1, \"sid\": 1024}, \"options\": []}\n", + Media.class); + + assertEquals(HeosCommandGroup.PLAYER, response.heosCommand.commandGroup); + assertEquals(HeosCommand.GET_NOW_PLAYING_MEDIA, response.heosCommand.command); + assertTrue(response.result); + + assertEquals(Long.valueOf(1958912779), response.getNumericAttribute(PLAYER_ID)); + + assertEquals("song", response.payload.type); + assertEquals("Solo (feat. Demi Lovato)", response.payload.song); + assertEquals("What Is Love? (Deluxe)", response.payload.album); + assertEquals("Clean Bandit", response.payload.artist); + assertEquals( + "http://192.168.1.230:8015//m-browsableMediaUri/getImageFromTag/mnt/326C72A3E307501E47DE2B0F47D90EB8/Clean%20Bandit/What%20Is%20Love_%20(Deluxe)/03%20Solo%20(feat.%20Demi%20Lovato).m4a", + response.payload.imageUrl); + assertEquals("", response.payload.albumId); + assertEquals( + "http://192.168.1.230:8015/m-1c176905-f6c7-d168-dc35-86b4735c5976/Clean+Bandit/What+Is+Love_+(Deluxe)/03+Solo+(feat.+Demi+Lovato).m4a", + response.payload.mediaId); + assertEquals(1, response.payload.queueId); + assertEquals(1024, response.payload.sourceId); + } + + @Test + public void browse_playlist() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"browse/browse\", \"result\": \"success\", \"message\": \"sid=1025&returned=6&count=6\"}, \"payload\": [" + + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"132562\", \"playable\": \"yes\", \"name\": \"Maaike Ouboter - En hoe het dan ook weer dag wordt\", \"image_url\": \"\"}, " + + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"132563\", \"playable\": \"yes\", \"name\": \"Maaike Ouboter - Vanaf nu is het van jou\", \"image_url\": \"\"}, " + + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"162887\", \"playable\": \"yes\", \"name\": \"Easy listening\", \"image_url\": \"\"}, " + + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"174461\", \"playable\": \"yes\", \"name\": \"Nieuwe muziek 5-2019\", \"image_url\": \"\"}, " + + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"194000\", \"playable\": \"yes\", \"name\": \"Nieuwe muziek 2019-05\", \"image_url\": \"\"}, " + + "{\"container\": \"yes\", \"type\": \"playlist\", \"cid\": \"194001\", \"playable\": \"yes\", \"name\": \"Clean Bandit\", \"image_url\": \"\"}]}", + BrowseResult[].class); + + assertEquals(HeosCommandGroup.BROWSE, response.heosCommand.commandGroup); + assertEquals(HeosCommand.BROWSE, response.heosCommand.command); + assertTrue(response.result); + + assertEquals(Long.valueOf(1025), response.getNumericAttribute(SOURCE_ID)); + assertEquals(Long.valueOf(6), response.getNumericAttribute(RETURNED)); + assertEquals(Long.valueOf(6), response.getNumericAttribute(COUNT)); + + BrowseResult result = response.payload[5]; + + assertEquals(YesNoEnum.YES, result.container); + assertEquals(BrowseResultType.PLAYLIST, result.type); + assertEquals(YesNoEnum.YES, result.playable); + assertEquals("194001", result.containerId); + assertEquals("Clean Bandit", result.name); + assertEquals("", result.imageUrl); + } + + @Test + public void browse_favorites() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"browse/browse\", \"result\": \"success\", \"message\": \"sid=1028&returned=3&count=3\"}, \"payload\": [" + + "{\"container\": \"no\", \"mid\": \"s6707\", \"type\": \"station\", \"playable\": \"yes\", \"name\": \"NPO 3FM 96.8 (Top 40 %26 Pop Music)\", \"image_url\": \"http://cdn-profiles.tunein.com/s6707/images/logoq.png?t=636268\"}, " + + "{\"container\": \"no\", \"mid\": \"s2967\", \"type\": \"station\", \"playable\": \"yes\", \"name\": \"Classic FM Nederland (Classical Music)\", \"image_url\": \"http://cdn-radiotime-logos.tunein.com/s2967q.png\"}, " + + "{\"container\": \"no\", \"mid\": \"s1993\", \"type\": \"station\", \"playable\": \"yes\", \"name\": \"BNR Nieuwsradio\", \"image_url\": \"http://cdn-radiotime-logos.tunein.com/s1993q.png\"}], " + + "\"options\": [{\"browse\": [{\"id\": 20, \"name\": \"Remove from HEOS Favorites\"}]}]}", + BrowseResult[].class); + + assertEquals(HeosCommandGroup.BROWSE, response.heosCommand.commandGroup); + assertEquals(HeosCommand.BROWSE, response.heosCommand.command); + assertTrue(response.result); + + assertEquals(Long.valueOf(1028), response.getNumericAttribute(SOURCE_ID)); + assertEquals(Long.valueOf(3), response.getNumericAttribute(RETURNED)); + assertEquals(Long.valueOf(3), response.getNumericAttribute(COUNT)); + + BrowseResult result = response.payload[0]; + + assertEquals(YesNoEnum.NO, result.container); + assertEquals("s6707", result.mediaId); + assertEquals(BrowseResultType.STATION, result.type); + assertEquals(YesNoEnum.YES, result.playable); + assertEquals("NPO 3FM 96.8 (Top 40 %26 Pop Music)", result.name); + assertEquals("http://cdn-profiles.tunein.com/s6707/images/logoq.png?t=636268", result.imageUrl); + + // TODO validate options + } + + @Test + public void get_groups() { + HeosResponseObject response = subject.parseResponse( + "{\"heos\": {\"command\": \"group/get_groups\", \"result\": \"success\", \"message\": \"\"}, \"payload\": [ " + + "{\"name\": \"Group 1\", \"gid\": \"214243242\", \"players\": [ {\"name\": \"HEOS 1\", \"pid\": \"2142443242\", \"role\": \"leader\"}, {\"name\": \"HEOS 3\", \"pid\": \"32432423432\", \"role\": \"member\"}, {\"name\": \"HEOS 5\", \"pid\": \"342423564\", \"role\": \"member\"}]}, " + + "{\"name\": \"Group 2\", \"gid\": \"2142432342\", \"players\": [ {\"name\": \"HEOS 3\", \"pid\": \"32432423432\", \"role\": \"member\"}, {\"name\": \"HEOS 5\", \"pid\": \"342423564\", \"role\": \"member\"}]}]}", + Group[].class); + + assertEquals(HeosCommandGroup.GROUP, response.heosCommand.commandGroup); + assertEquals(HeosCommand.GET_GROUPS, response.heosCommand.command); + assertTrue(response.result); + + Group group = response.payload[0]; + + assertEquals("Group 1", group.name); + assertEquals("214243242", group.id); + + List players = group.players; + + Group.Player player0 = players.get(0); + assertEquals("HEOS 1", player0.name); + assertEquals("2142443242", player0.id); + assertEquals(GroupPlayerRole.LEADER, player0.role); + + Group.Player player1 = players.get(1); + assertEquals("HEOS 3", player1.name); + assertEquals("32432423432", player1.id); + assertEquals(GroupPlayerRole.MEMBER, player1.role); + } +} diff --git a/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/dto/HeosCommandTupleTest.java b/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/dto/HeosCommandTupleTest.java new file mode 100644 index 0000000000000..0e6acdd6f904e --- /dev/null +++ b/bundles/org.openhab.binding.heos/src/test/java/org/openhab/binding/heos/internal/json/dto/HeosCommandTupleTest.java @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.heos.internal.json.dto; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.openhab.binding.heos.internal.json.dto.HeosCommand.*; +import static org.openhab.binding.heos.internal.json.dto.HeosCommandGroup.SYSTEM; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Test; + +/** + * Tests to validate the functioning of the HeosCommandTuple + * + * @author Martin van Wingerden - Initial Contribution + */ +@NonNullByDefault +public class HeosCommandTupleTest { + @Test + public void system() { + assertMatches("system/check_account", SYSTEM, CHECK_ACCOUNT); + assertMatches("system/sign_in", SYSTEM, SIGN_IN); + assertMatches("system/sign_out", SYSTEM, SIGN_OUT); + assertMatches("system/register_for_change_events", SYSTEM, REGISTER_FOR_CHANGE_EVENTS); + assertMatches("system/heart_beat", SYSTEM, HEART_BEAT); + assertMatches("system/prettify_json_response", SYSTEM, PRETTIFY_JSON_RESPONSE); + } + + @Test + public void browse() { + assertMatches("browse/browse", HeosCommandGroup.BROWSE, HeosCommand.BROWSE); + assertMatches("browse/get_music_sources", HeosCommandGroup.BROWSE, HeosCommand.GET_MUSIC_SOURCES); + assertMatches("browse/get_source_info", HeosCommandGroup.BROWSE, HeosCommand.GET_SOURCE_INFO); + assertMatches("browse/get_search_criteria", HeosCommandGroup.BROWSE, HeosCommand.GET_SEARCH_CRITERIA); + assertMatches("browse/search", HeosCommandGroup.BROWSE, HeosCommand.SEARCH); + assertMatches("browse/play_stream", HeosCommandGroup.BROWSE, HeosCommand.PLAY_STREAM); + assertMatches("browse/play_preset", HeosCommandGroup.BROWSE, HeosCommand.PLAY_PRESET); + assertMatches("browse/play_input", HeosCommandGroup.BROWSE, HeosCommand.PLAY_INPUT); + assertMatches("browse/play_stream", HeosCommandGroup.BROWSE, HeosCommand.PLAY_STREAM); + assertMatches("browse/add_to_queue", HeosCommandGroup.BROWSE, HeosCommand.ADD_TO_QUEUE); + assertMatches("browse/rename_playlist", HeosCommandGroup.BROWSE, HeosCommand.RENAME_PLAYLIST); + assertMatches("browse/delete_playlist", HeosCommandGroup.BROWSE, HeosCommand.DELETE_PLAYLIST); + assertMatches("browse/retrieve_metadata", HeosCommandGroup.BROWSE, HeosCommand.RETRIEVE_METADATA); + } + + @Test + public void player() { + assertMatches("player/get_players", HeosCommandGroup.PLAYER, HeosCommand.GET_PLAYERS); + assertMatches("player/get_player_info", HeosCommandGroup.PLAYER, HeosCommand.GET_PLAYER_INFO); + assertMatches("player/get_play_state", HeosCommandGroup.PLAYER, HeosCommand.GET_PLAY_STATE); + assertMatches("player/set_play_state", HeosCommandGroup.PLAYER, HeosCommand.SET_PLAY_STATE); + assertMatches("player/get_now_playing_media", HeosCommandGroup.PLAYER, HeosCommand.GET_NOW_PLAYING_MEDIA); + assertMatches("player/get_volume", HeosCommandGroup.PLAYER, HeosCommand.GET_VOLUME); + assertMatches("player/set_volume", HeosCommandGroup.PLAYER, HeosCommand.SET_VOLUME); + assertMatches("player/volume_up", HeosCommandGroup.PLAYER, HeosCommand.VOLUME_UP); + assertMatches("player/volume_down", HeosCommandGroup.PLAYER, HeosCommand.VOLUME_DOWN); + assertMatches("player/get_mute", HeosCommandGroup.PLAYER, HeosCommand.GET_MUTE); + assertMatches("player/set_mute", HeosCommandGroup.PLAYER, HeosCommand.SET_MUTE); + assertMatches("player/toggle_mute", HeosCommandGroup.PLAYER, HeosCommand.TOGGLE_MUTE); + assertMatches("player/get_play_mode", HeosCommandGroup.PLAYER, HeosCommand.GET_PLAY_MODE); + assertMatches("player/set_play_mode", HeosCommandGroup.PLAYER, HeosCommand.SET_PLAY_MODE); + assertMatches("player/get_queue", HeosCommandGroup.PLAYER, HeosCommand.GET_QUEUE); + assertMatches("player/play_queue", HeosCommandGroup.PLAYER, HeosCommand.PLAY_QUEUE); + assertMatches("player/remove_from_queue", HeosCommandGroup.PLAYER, HeosCommand.REMOVE_FROM_QUEUE); + assertMatches("player/save_queue", HeosCommandGroup.PLAYER, HeosCommand.SAVE_QUEUE); + assertMatches("player/clear_queue", HeosCommandGroup.PLAYER, HeosCommand.CLEAR_QUEUE); + assertMatches("player/move_queue_item", HeosCommandGroup.PLAYER, HeosCommand.MOVE_QUEUE_ITEM); + assertMatches("player/play_next", HeosCommandGroup.PLAYER, HeosCommand.PLAY_NEXT); + assertMatches("player/play_previous", HeosCommandGroup.PLAYER, HeosCommand.PLAY_PREVIOUS); + assertMatches("player/set_quickselect", HeosCommandGroup.PLAYER, HeosCommand.SET_QUICKSELECT); + assertMatches("player/play_quickselect", HeosCommandGroup.PLAYER, HeosCommand.PLAY_QUICKSELECT); + assertMatches("player/get_quickselects", HeosCommandGroup.PLAYER, HeosCommand.GET_QUICKSELECTS); + assertMatches("player/check_update", HeosCommandGroup.PLAYER, HeosCommand.CHECK_UPDATE); + } + + @Test + public void group() { + assertMatches("group/get_groups", HeosCommandGroup.GROUP, HeosCommand.GET_GROUPS); + assertMatches("group/get_group_info", HeosCommandGroup.GROUP, HeosCommand.GET_GROUP_INFO); + assertMatches("group/set_group", HeosCommandGroup.GROUP, HeosCommand.SET_GROUP); + assertMatches("group/get_volume", HeosCommandGroup.GROUP, HeosCommand.GET_VOLUME); + assertMatches("group/set_volume", HeosCommandGroup.GROUP, HeosCommand.SET_VOLUME); + assertMatches("group/volume_up", HeosCommandGroup.GROUP, HeosCommand.VOLUME_UP); + assertMatches("group/volume_down", HeosCommandGroup.GROUP, HeosCommand.VOLUME_DOWN); + assertMatches("group/get_mute", HeosCommandGroup.GROUP, HeosCommand.GET_MUTE); + assertMatches("group/set_mute", HeosCommandGroup.GROUP, HeosCommand.SET_MUTE); + assertMatches("group/toggle_mute", HeosCommandGroup.GROUP, HeosCommand.TOGGLE_MUTE); + } + + private void assertMatches(String command, HeosCommandGroup commandGroup, HeosCommand heosCommand) { + HeosCommandTuple tuple = HeosCommandTuple.valueOf(command); + + assertNotNull(tuple); + assertEquals(commandGroup, tuple.commandGroup); + assertEquals(heosCommand, tuple.command); + } + + /** + * "browse/browse" + * "group/get_groups" + * "player/get_mute" + * "player/get_now_playing_media" + * "player/get_player_info" + * "player/get_players" + * "player/get_play_mode" + * "player/get_play_state" + * "player/get_volume" + * "player/play_next" + * "player/play_previous" + * "player/set_mute" + * "player/set_play_mode" + * "player/set_play_state" + * "player/set_volume" + * "player/volume_down" + * "system/heart_beat" + * "system/register_for_change_events" + * "system/sign_in" + */ +} diff --git a/bundles/org.openhab.binding.homematic/pom.xml b/bundles/org.openhab.binding.homematic/pom.xml index 0d747b6958928..66fc62816e8b5 100644 --- a/bundles/org.openhab.binding.homematic/pom.xml +++ b/bundles/org.openhab.binding.homematic/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.homematic diff --git a/bundles/org.openhab.binding.homematic/src/main/feature/feature.xml b/bundles/org.openhab.binding.homematic/src/main/feature/feature.xml index 3ad5dd134c26e..e461c67038373 100644 --- a/bundles/org.openhab.binding.homematic/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.homematic/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.homematic/${project.version} - + + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.homematic/${project.version} + diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/HomematicBindingConstants.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/HomematicBindingConstants.java index 870bec74486aa..a17366053cfa6 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/HomematicBindingConstants.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/HomematicBindingConstants.java @@ -26,7 +26,7 @@ public class HomematicBindingConstants { public static final String BINDING_ID = "homematic"; public static final ThingTypeUID THING_TYPE_BRIDGE = new ThingTypeUID(BINDING_ID, "bridge"); public static final String CONFIG_DESCRIPTION_URI_CHANNEL = "channel-type:homematic:config"; - + /** * A thing's config-description-uri is generally composed as follows:
* {@link #CONFIG_DESCRIPTION_URI_THING_PREFIX}:{@link ThingTypeUID} @@ -64,7 +64,7 @@ public class HomematicBindingConstants { public static final String PROPERTY_BATTERY_TYPE = "batteryType"; public static final String PROPERTY_AES_KEY = "aesKey"; public static final String PROPERTY_DYNAMIC_FUNCTION_FORMAT = "dynamicFunction-%d"; - + public static final int INSTALL_MODE_NORMAL = 1; public static final int CONFIGURATION_CHANNEL_NUMBER = -1; diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/AbstractHomematicGateway.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/AbstractHomematicGateway.java index 2aaeba067de40..340bf933ce41d 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/AbstractHomematicGateway.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/AbstractHomematicGateway.java @@ -970,6 +970,5 @@ private void handleInvalidConnection(String cause) throws IOException { startClients(); startServers(); } - } } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/CcuGateway.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/CcuGateway.java index 255e5787d6562..e209d8f07219b 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/CcuGateway.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/CcuGateway.java @@ -237,5 +237,4 @@ private Map loadTclRegaScripts() throws IOException { throw new IOException("The resource homematic/tclrega-scripts.xml could not be loaded!", e); } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/DefaultGateway.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/DefaultGateway.java index cf1ae7dc20752..cc3ef2e2ed2af 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/DefaultGateway.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/DefaultGateway.java @@ -57,5 +57,4 @@ protected void executeScript(HmDatapoint dp) throws IOException { protected void loadDeviceNames(Collection devices) throws IOException { // not supported } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomegearGateway.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomegearGateway.java index a31c78d56e423..0861582d0b1f6 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomegearGateway.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomegearGateway.java @@ -57,5 +57,4 @@ protected void executeScript(HmDatapoint dp) throws IOException { protected void loadDeviceNames(Collection devices) throws IOException { getRpcClient(getDefaultInterface()).loadDeviceNames(getDefaultInterface(), devices); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGateway.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGateway.java index 48934a45c5df3..cd0a058ad9aa3 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGateway.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGateway.java @@ -98,13 +98,13 @@ public void sendDatapoint(HmDatapoint dp, HmDatapointConfig dpConfig, Object new * Returns the id of the HomematicGateway. */ public String getId(); - + /** * Set install mode of homematic controller. During install mode the * controller will accept any device (normal mode) * * @param enable true will start install mode, whereas false - * will stop it + * will stop it * @param seconds specify how long the install mode should last * @throws IOException if RpcClient fails to propagate command */ @@ -139,5 +139,4 @@ public void sendDatapoint(HmDatapoint dp, HmDatapointConfig dpConfig, Object new * @param defer true will delete the device once it becomes available. */ public void deleteDevice(String address, boolean reset, boolean force, boolean defer); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGatewayAdapter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGatewayAdapter.java index 1fcf4e13c8556..8bc6774ae7026 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGatewayAdapter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGatewayAdapter.java @@ -72,5 +72,4 @@ public interface HomematicGatewayAdapter { * Called when a new value for the duty cycle of the gateway has been received. */ public void onDutyCycleRatioUpdate(int dutyCycleRatio); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGatewayFactory.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGatewayFactory.java index afb4f6be8dc18..aa78b2127ba83 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGatewayFactory.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/HomematicGatewayFactory.java @@ -30,8 +30,7 @@ public class HomematicGatewayFactory { * Creates the HomematicGateway. */ public static HomematicGateway createGateway(String id, HomematicConfig config, - HomematicGatewayAdapter gatewayAdapter, HttpClient httpClient) - throws IOException { + HomematicGatewayAdapter gatewayAdapter, HttpClient httpClient) throws IOException { loadGatewayInfo(config, id, httpClient); if (config.getGatewayInfo().isCCU()) { return new CcuGateway(id, config, gatewayAdapter, httpClient); @@ -53,5 +52,4 @@ private static void loadGatewayInfo(HomematicConfig config, String id, HttpClien rpcClient.dispose(); } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/BinRpcClient.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/BinRpcClient.java index 474ddc45143f0..544651391df1d 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/BinRpcClient.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/BinRpcClient.java @@ -99,5 +99,4 @@ private Object[] sendMessage(int port, RpcRequest request, int rpcRetryC } } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java index 8a5deeaad214d..686ecd6a5377e 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/RpcClient.java @@ -52,6 +52,7 @@ public abstract class RpcClient { private final Logger logger = LoggerFactory.getLogger(RpcClient.class); protected static final int MAX_RPC_RETRY = 1; + protected static final int RESP_BUFFER_SIZE = 8192; protected HomematicConfig config; @@ -462,5 +463,4 @@ private String getChannelSuffix(HmChannel channel) { private boolean isConfigurationChannel(HmChannel channel) { return channel.getNumber() == CONFIGURATION_CHANNEL_NUMBER; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/UnknownParameterSetException.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/UnknownParameterSetException.java index f34b7488861eb..702fdc7538e40 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/UnknownParameterSetException.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/UnknownParameterSetException.java @@ -26,5 +26,4 @@ public class UnknownParameterSetException extends IOException { public UnknownParameterSetException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/UnknownRpcFailureException.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/UnknownRpcFailureException.java index 1e6a850dd880d..997c3ede7f558 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/UnknownRpcFailureException.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/UnknownRpcFailureException.java @@ -26,5 +26,4 @@ public class UnknownRpcFailureException extends IOException { public UnknownRpcFailureException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java index 4a4ec3b659e6a..5aa5d1cd08793 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/client/XmlRpcClient.java @@ -13,13 +13,17 @@ package org.openhab.binding.homematic.internal.communicator.client; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.util.BytesContentProvider; +import org.eclipse.jetty.client.util.InputStreamResponseListener; import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpStatus; import org.openhab.binding.homematic.internal.common.HomematicConfig; import org.openhab.binding.homematic.internal.communicator.message.RpcRequest; import org.openhab.binding.homematic.internal.communicator.message.XmlRpcRequest; @@ -79,17 +83,31 @@ private synchronized Object[] sendMessage(int port, RpcRequest request, if (port == config.getGroupPort()) { url += "/groups"; } - ContentResponse response = httpClient.POST(url).content(content) - .timeout(config.getTimeout(), TimeUnit.SECONDS) - .header(HttpHeader.CONTENT_TYPE, "text/xml;charset=" + config.getEncoding()).send(); - + InputStreamResponseListener respListener = new InputStreamResponseListener(); + httpClient.POST(url).content(content) + .header(HttpHeader.CONTENT_TYPE, "text/xml;charset=" + config.getEncoding()).send(respListener); + Response resp = respListener.get(config.getTimeout(), TimeUnit.SECONDS); + ByteArrayOutputStream respData = new ByteArrayOutputStream(RESP_BUFFER_SIZE); + int httpStatus = resp.getStatus(); + if (httpStatus == HttpStatus.OK_200) { + byte[] recvBuffer = new byte[RESP_BUFFER_SIZE]; + InputStream input = respListener.getInputStream(); + while (true) { + int read = input.read(recvBuffer); + if (read == -1) { + break; + } + respData.write(recvBuffer, 0, read); + } + } else { + logger.warn("XmlRpcRequest failure, status code: {} / request was: {}", httpStatus, request); + resp.abort(new Exception()); + } if (logger.isTraceEnabled()) { - String result = new String(response.getContent(), config.getEncoding()); - logger.trace("Client XmlRpcResponse (port {}):\n{}", port, result); + logger.trace("Client XmlRpcResponse: (port {}):\n{}", port, respData.toString(config.getEncoding())); } - - Object[] data = new XmlRpcResponse(new ByteArrayInputStream(response.getContent()), - config.getEncoding()).getResponseData(); + Object[] data = new XmlRpcResponse(new ByteArrayInputStream(respData.toByteArray()), config.getEncoding()) + .getResponseData(); return new RpcResponseParser(request).parse(data); } catch (UnknownRpcFailureException | UnknownParameterSetException ex) { throw ex; diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/RpcResponse.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/RpcResponse.java index 0e5d17e924372..7536a1bca5340 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/RpcResponse.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/RpcResponse.java @@ -28,5 +28,4 @@ public interface RpcResponse { * Returns the decoded data. */ public Object[] getResponseData(); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/RpcUtils.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/RpcUtils.java index 3d9f6928e97fa..b893f2fd821f0 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/RpcUtils.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/RpcUtils.java @@ -94,5 +94,4 @@ private static void dumpMap(Map c, StringBuilder sb, int indent) { sb.append("}\n"); } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/XmlRpcResponse.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/XmlRpcResponse.java index b08c5f199542b..1a526fd27482d 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/XmlRpcResponse.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/message/XmlRpcResponse.java @@ -170,6 +170,5 @@ public void endElement(String uri, String localName, String qName) throws SAXExc public void characters(char[] ch, int start, int length) throws SAXException { tagValue.append(new String(ch, start, length)); } - } } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/CcuParamsetDescriptionParser.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/CcuParamsetDescriptionParser.java index aa1bebd943698..f3aff9106bdd1 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/CcuParamsetDescriptionParser.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/CcuParamsetDescriptionParser.java @@ -55,5 +55,4 @@ private String[] toOptionList(String options) { String[] result = StringUtils.splitByWholeSeparatorPreserveAllTokens(options, ";"); return result == null || result.length == 0 ? null : result; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/CommonRpcParser.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/CommonRpcParser.java index c04a2841c2534..63a4fd243362a 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/CommonRpcParser.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/CommonRpcParser.java @@ -175,8 +175,7 @@ protected HmDatapoint assembleDatapoint(String name, String unit, String type, S HmValueType valueType = HmValueType.parse(type); if (valueType == null || valueType == HmValueType.UNKNOWN) { throw new IOException("Unknown datapoint type: " + type); - } - else if (valueType == HmValueType.FLOAT && dp.getUnit() == null + } else if (valueType == HmValueType.FLOAT && dp.getUnit() == null && dp.getName().matches("\\w*_TEMPERATURE(_\\w.*|$)")) { logger.debug("No unit information found for temperature datapoint {}, assuming Number:Temperature", dp.getName()); @@ -226,5 +225,4 @@ protected Object convertToType(String value) { return value; } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/DeleteDevicesParser.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/DeleteDevicesParser.java index bdf68514ffc2f..8ebf0a273ab02 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/DeleteDevicesParser.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/DeleteDevicesParser.java @@ -41,5 +41,4 @@ public List parse(Object[] message) throws IOException { } return adresses; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/DisplayOptionsParser.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/DisplayOptionsParser.java index d6334331c06cc..bf5070a46c074 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/DisplayOptionsParser.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/DisplayOptionsParser.java @@ -187,5 +187,4 @@ public int getUnit() { public List getSymbols() { return symbols; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/GetAllScriptsParser.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/GetAllScriptsParser.java index 108c2a17950bc..c7023de6f76a6 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/GetAllScriptsParser.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/GetAllScriptsParser.java @@ -44,5 +44,4 @@ public Void parse(Object[] message) throws IOException { } return null; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/GetAllSystemVariablesParser.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/GetAllSystemVariablesParser.java index 366a25af3960b..419be602e879f 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/GetAllSystemVariablesParser.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/GetAllSystemVariablesParser.java @@ -67,5 +67,4 @@ private HmValueType guessType(Object value) { return HmValueType.STRING; } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/NewDevicesParser.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/NewDevicesParser.java index 50b5bc1d176fc..c334159e59a7a 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/NewDevicesParser.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/NewDevicesParser.java @@ -44,5 +44,4 @@ public List parse(Object[] message) throws IOException { } return adresses; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/RpcParser.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/RpcParser.java index cd04e66fcb959..e1a1d45d039c1 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/RpcParser.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/parser/RpcParser.java @@ -25,5 +25,4 @@ public interface RpcParser { * Parses the message returns the result. */ public R parse(M message) throws IOException; - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/BinRpcNetworkService.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/BinRpcNetworkService.java index 34d88ac18701c..65e7b5100a400 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/BinRpcNetworkService.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/BinRpcNetworkService.java @@ -100,5 +100,4 @@ public void shutdown() { // ignore } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcEventListener.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcEventListener.java index 724828e7db70e..8885cbae5446d 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcEventListener.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcEventListener.java @@ -37,5 +37,4 @@ public interface RpcEventListener { * Called when devices has been deleted from the Homeamtic gateway. */ public void deleteDevices(List addresses); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcResponseHandler.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcResponseHandler.java index c70b4ead2cecc..df003324d78e9 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcResponseHandler.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcResponseHandler.java @@ -138,5 +138,4 @@ private T handleDeleteDevice(Object[] message) throws IOException { * Creates a typed RpcRequest. */ protected abstract RpcRequest createRpcRequest(); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcServer.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcServer.java index e54dc019a4d32..937c35377254e 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcServer.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/RpcServer.java @@ -30,5 +30,4 @@ public interface RpcServer { * Stops the rpc server. */ public void shutdown(); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/XmlRpcServer.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/XmlRpcServer.java index 1b2ebee4ec5d1..484c33114111c 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/XmlRpcServer.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/server/XmlRpcServer.java @@ -135,5 +135,4 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques baseRequest.setHandled(true); } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/AbstractVirtualDatapointHandler.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/AbstractVirtualDatapointHandler.java index 98de6118bd5a7..b84e412f0c76f 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/AbstractVirtualDatapointHandler.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/AbstractVirtualDatapointHandler.java @@ -78,5 +78,4 @@ protected HmDatapoint addDatapoint(HmChannel channel, HmDatapoint dp) { channel.addDatapoint(dp); return dp; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/BatteryTypeVirtualDatapointHandler.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/BatteryTypeVirtualDatapointHandler.java index a11eb02fc4f70..0576a376017d3 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/BatteryTypeVirtualDatapointHandler.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/BatteryTypeVirtualDatapointHandler.java @@ -40,7 +40,8 @@ public BatteryTypeVirtualDatapointHandler() { try (InputStream stream = bundle.getResource("homematic/batteries.properties").openStream()) { batteries.load(stream); } catch (IllegalStateException | IOException e) { - logger.warn("The resource homematic/batteries.properties could not be loaded! Battery types not available", e); + logger.warn("The resource homematic/batteries.properties could not be loaded! Battery types not available", + e); } } @@ -56,5 +57,4 @@ public void initialize(HmDevice device) { addDatapoint(device, 0, getName(), HmValueType.STRING, batteryType, true); } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/FirmwareVirtualDatapointHandler.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/FirmwareVirtualDatapointHandler.java index 6ee0aa06ab6e3..814e62cd4ece8 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/FirmwareVirtualDatapointHandler.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/FirmwareVirtualDatapointHandler.java @@ -34,5 +34,4 @@ public void initialize(HmDevice device) { addDatapoint(device, 0, getName(), HmValueType.STRING, device.getFirmware(), true); } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/InstallModeVirtualDatapoint.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/InstallModeVirtualDatapoint.java index 9a1177f5838f0..d3cd9b20e5bfa 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/InstallModeVirtualDatapoint.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/InstallModeVirtualDatapoint.java @@ -71,5 +71,4 @@ private Integer getDuration(HmChannel channel) { return dpDuration == null || dpDuration.getValue() == null || dpDuration.getType() != HmValueType.INTEGER ? 60 : ((Number) dpDuration.getValue()).intValue(); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ReloadFromGatewayVirtualDatapointHandler.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ReloadFromGatewayVirtualDatapointHandler.java index 8e83bd2cc0e68..e84a36fb9ec1d 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ReloadFromGatewayVirtualDatapointHandler.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ReloadFromGatewayVirtualDatapointHandler.java @@ -57,5 +57,4 @@ public void handleCommand(VirtualGateway gateway, HmDatapoint dp, HmDatapointCon } } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ReloadRssiVirtualDatapointHandler.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ReloadRssiVirtualDatapointHandler.java index abaee59bc7492..c5264d0b5f95e 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ReloadRssiVirtualDatapointHandler.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/communicator/virtual/ReloadRssiVirtualDatapointHandler.java @@ -59,5 +59,4 @@ public void handleCommand(VirtualGateway gateway, HmDatapoint dp, HmDatapointCon } } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterException.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterException.java index 106f10ba35815..6b44bf5565908 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterException.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterException.java @@ -23,5 +23,4 @@ public class ConverterException extends Exception { public ConverterException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterFactory.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterFactory.java index 7ff04eaa67bc0..f900da991d2f5 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterFactory.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterFactory.java @@ -79,5 +79,4 @@ public static TypeConverter createConverter(String itemType) throws Converter } return converter; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterTypeException.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterTypeException.java index d8160049ab523..6a996ad36f853 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterTypeException.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/ConverterTypeException.java @@ -23,5 +23,4 @@ public class ConverterTypeException extends ConverterException { public ConverterTypeException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/StateInvertInfo.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/StateInvertInfo.java index 6bc11c4334cad..d53813f1f2759 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/StateInvertInfo.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/StateInvertInfo.java @@ -53,5 +53,4 @@ public boolean isToInvert(HmDatapoint dp) { return dpDeviceType.startsWith(deviceType); } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/TypeConverter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/TypeConverter.java index 75107b1ffba47..d7488e42d3ec9 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/TypeConverter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/TypeConverter.java @@ -32,5 +32,4 @@ public interface TypeConverter { * Converts a Homematic value to a openHAB type. */ public T convertFromBinding(HmDatapoint dp) throws ConverterException; - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/AbstractTypeConverter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/AbstractTypeConverter.java index 8100916d3f626..bb10d280ed261 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/AbstractTypeConverter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/AbstractTypeConverter.java @@ -191,5 +191,4 @@ protected enum LogLevel { INFO, DEBUG } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/DecimalTypeConverter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/DecimalTypeConverter.java index b76625df4c0ba..1d0b3301ac28b 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/DecimalTypeConverter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/DecimalTypeConverter.java @@ -51,5 +51,4 @@ protected DecimalType fromBinding(HmDatapoint dp) throws ConverterException { } return new DecimalType(round(number.doubleValue())); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/OnOffTypeConverter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/OnOffTypeConverter.java index d762db79dd928..f11b3b7f088e5 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/OnOffTypeConverter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/OnOffTypeConverter.java @@ -51,5 +51,4 @@ protected OnOffType fromBinding(HmDatapoint dp) throws ConverterException { private boolean isInvert(HmDatapoint dp) { return DATAPOINT_NAME_SENSOR.equals(dp.getName()) || isStateInvertDatapoint(dp); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/OpenClosedTypeConverter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/OpenClosedTypeConverter.java index fb7951f8a3e9b..a5b8d6e942349 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/OpenClosedTypeConverter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/OpenClosedTypeConverter.java @@ -52,5 +52,4 @@ protected OpenClosedType fromBinding(HmDatapoint dp) throws ConverterException { private boolean isInvert(HmDatapoint dp) { return !DATAPOINT_NAME_SENSOR.equals(dp.getName()) && !isStateInvertDatapoint(dp); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/QuantityTypeConverter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/QuantityTypeConverter.java index f0c1c9800177e..4a1f90d8e9e16 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/QuantityTypeConverter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/QuantityTypeConverter.java @@ -146,5 +146,4 @@ protected LogLevel getDefaultLogLevelForTypeConverter() { // increase logging verbosity for this type of converter return LogLevel.DEBUG; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/StringTypeConverter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/StringTypeConverter.java index 761dcef2b0cbe..54bb532537704 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/StringTypeConverter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/converter/type/StringTypeConverter.java @@ -61,5 +61,4 @@ protected StringType fromBinding(HmDatapoint dp) throws ConverterException { return new StringType(value); } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryService.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryService.java index 6420f4ad51f75..686c23ee541ce 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryService.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/HomematicDeviceDiscoveryService.java @@ -245,5 +245,4 @@ public void deviceDiscovered(HmDevice device) { .withRepresentationProperty(Thing.PROPERTY_SERIAL_NUMBER).withTTL(timeToLive).build(); thingDiscovered(discoveryResult); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/eq3udp/Eq3UdpResponse.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/eq3udp/Eq3UdpResponse.java index 03fea63cddedf..8660bc7c46865 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/eq3udp/Eq3UdpResponse.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/discovery/eq3udp/Eq3UdpResponse.java @@ -89,5 +89,4 @@ public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("deviceTypeId", deviceTypeId) .append("serialNumber", serialNumber).toString(); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/handler/GatewayNotAvailableException.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/handler/GatewayNotAvailableException.java index 87d2c121f2668..c77dc2e4c015a 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/handler/GatewayNotAvailableException.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/handler/GatewayNotAvailableException.java @@ -23,5 +23,4 @@ public class GatewayNotAvailableException extends Exception { public GatewayNotAvailableException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/handler/HomematicBridgeHandler.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/handler/HomematicBridgeHandler.java index d01545526d88b..a14cb70199433 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/handler/HomematicBridgeHandler.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/handler/HomematicBridgeHandler.java @@ -260,7 +260,7 @@ public HomematicGateway getGateway() { * Updates the thing for the given Homematic device. */ private void updateThing(HmDevice device) { - Thing hmThing = getThingByUID(UidUtils.generateThingUID(device, getThing())); + Thing hmThing = getThing().getThing(UidUtils.generateThingUID(device, getThing())); if (hmThing != null) { HomematicThingHandler thingHandler = (HomematicThingHandler) hmThing.getHandler(); if (thingHandler != null) { @@ -274,7 +274,7 @@ private void updateThing(HmDevice device) { @Override public void onStateUpdated(HmDatapoint dp) { - Thing hmThing = getThingByUID(UidUtils.generateThingUID(dp.getChannel().getDevice(), getThing())); + Thing hmThing = getThing().getThing(UidUtils.generateThingUID(dp.getChannel().getDevice(), getThing())); if (hmThing != null) { final ThingStatus status = hmThing.getStatus(); if (status == ThingStatus.ONLINE || status == ThingStatus.OFFLINE) { @@ -288,7 +288,7 @@ public void onStateUpdated(HmDatapoint dp) { @Override public HmDatapointConfig getDatapointConfig(HmDatapoint dp) { - Thing hmThing = getThingByUID(UidUtils.generateThingUID(dp.getChannel().getDevice(), getThing())); + Thing hmThing = getThing().getThing(UidUtils.generateThingUID(dp.getChannel().getDevice(), getThing())); if (hmThing != null) { HomematicThingHandler thingHandler = (HomematicThingHandler) hmThing.getHandler(); if (thingHandler != null) { @@ -310,7 +310,7 @@ public void onDeviceDeleted(HmDevice device) { discoveryService.deviceRemoved(device); updateThing(device); - Thing hmThing = getThingByUID(UidUtils.generateThingUID(device, getThing())); + Thing hmThing = getThing().getThing(UidUtils.generateThingUID(device, getThing())); if (hmThing != null && hmThing.getHandler() != null) { ((HomematicThingHandler) hmThing.getHandler()).deviceRemoved(); } @@ -334,7 +334,7 @@ public void onDeviceLoaded(HmDevice device) { discoveryService.deviceDiscovered(device); } - Thing hmThing = getThingByUID(UidUtils.generateThingUID(device, getThing())); + Thing hmThing = getThing().getThing(UidUtils.generateThingUID(device, getThing())); if (hmThing != null) { HomematicThingHandler thingHandler = (HomematicThingHandler) hmThing.getHandler(); if (thingHandler != null) { @@ -426,5 +426,4 @@ public void deleteFromGateway(String address, boolean reset, boolean force, bool getGateway().deleteDevice(address, reset, force, defer); }); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/misc/DelayedExecuter.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/misc/DelayedExecuter.java index e47dcbc6267f3..e34037af380f4 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/misc/DelayedExecuter.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/misc/DelayedExecuter.java @@ -84,7 +84,5 @@ public void stop() { public interface DelayedExecuterCallback { public void execute() throws IOException, HomematicClientException; - } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmChannel.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmChannel.java index b5e95843f5257..f2250a9d45411 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmChannel.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmChannel.java @@ -219,5 +219,4 @@ public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("number", number).append("type", type) .append("initialized", initialized).toString(); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmDatapoint.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmDatapoint.java index e39dbde088cfb..97c6207e49bb3 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmDatapoint.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmDatapoint.java @@ -438,5 +438,4 @@ public String toString() { .append("description", description).append("info", info).append("paramsetType", paramsetType) .append("virtual", virtual).append("trigger", trigger).toString(); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmDatapointConfig.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmDatapointConfig.java index 100b22eacd8a8..8ca63574cc741 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmDatapointConfig.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmDatapointConfig.java @@ -57,5 +57,4 @@ public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("delay", delay) .append("receiveDelay", receiveDelay).toString(); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmRssiInfo.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmRssiInfo.java index 2df0935f75fd0..43ce6340ff7b4 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmRssiInfo.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmRssiInfo.java @@ -68,5 +68,4 @@ public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).append("address", address) .append("device", device).append("peer", peer).toString(); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmValueType.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmValueType.java index 8033442617a09..e0aa4cb3f06e0 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmValueType.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/HmValueType.java @@ -51,5 +51,4 @@ public static HmValueType parse(String type) { return UNKNOWN; } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScript.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScript.java index 01c37743a618c..f8510106eb263 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScript.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScript.java @@ -27,5 +27,4 @@ public class TclScript { public String name; public String data; - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScriptDataList.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScriptDataList.java index f020aea430ab2..552bfaa18b82c 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScriptDataList.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScriptDataList.java @@ -35,5 +35,4 @@ public class TclScriptDataList { public List getEntries() { return entries; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScriptList.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScriptList.java index 47e3cad06c2e3..d64b4402e109f 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScriptList.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/model/TclScriptList.java @@ -36,5 +36,4 @@ public class TclScriptList { public List getScripts() { return scripts; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelGroupTypeProvider.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelGroupTypeProvider.java index 7369abf843852..6d6d158f689e8 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelGroupTypeProvider.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelGroupTypeProvider.java @@ -42,5 +42,4 @@ public interface HomematicChannelGroupTypeProvider extends ChannelGroupTypeProvi * before */ public ChannelGroupType getInternalChannelGroupType(ChannelGroupTypeUID channelGroupTypeUID); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelGroupTypeProviderImpl.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelGroupTypeProviderImpl.java index 53b9449235a04..32dfbc2a8afdd 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelGroupTypeProviderImpl.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelGroupTypeProviderImpl.java @@ -87,5 +87,4 @@ public Collection getChannelGroupTypes(Locale locale) { public void addChannelGroupType(ChannelGroupType channelGroupType) { channelGroupTypesByUID.put(channelGroupType.getUID(), channelGroupType); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelTypeProvider.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelTypeProvider.java index d7c57e78daca5..5338d32d77122 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelTypeProvider.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelTypeProvider.java @@ -42,5 +42,4 @@ public interface HomematicChannelTypeProvider extends ChannelTypeProvider { * before */ public ChannelType getInternalChannelType(ChannelTypeUID channelTypeUID); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelTypeProviderImpl.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelTypeProviderImpl.java index d3e7ec7b1ae12..1f8153b28c303 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelTypeProviderImpl.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicChannelTypeProviderImpl.java @@ -88,5 +88,4 @@ public ChannelType getInternalChannelType(ChannelTypeUID channelTypeUID) { public void addChannelType(ChannelType channelType) { channelTypesByUID.put(channelType.getUID(), channelType); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicConfigDescriptionProvider.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicConfigDescriptionProvider.java index 9bd53bb063f2c..4206962689c3e 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicConfigDescriptionProvider.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicConfigDescriptionProvider.java @@ -42,7 +42,7 @@ public interface HomematicConfigDescriptionProvider extends ConfigDescriptionPro @Override @Nullable ConfigDescription getConfigDescription(URI uri, @Nullable Locale locale); - + /** * Use this method to lookup a ConfigDescription which was generated by the * homematic binding. Other than {@link #getConfigDescription(URI, Locale)} diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicConfigDescriptionProviderImpl.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicConfigDescriptionProviderImpl.java index 832d17d5831d1..d5b4e7370602e 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicConfigDescriptionProviderImpl.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicConfigDescriptionProviderImpl.java @@ -88,5 +88,4 @@ public ConfigDescription getInternalConfigDescription(URI uri) { public void addConfigDescription(ConfigDescription configDescription) { configDescriptionsByURI.put(configDescription.getUID(), configDescription); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicThingTypeProvider.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicThingTypeProvider.java index 0034c6ba3dc67..e35bedbd0ee8d 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicThingTypeProvider.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicThingTypeProvider.java @@ -27,7 +27,7 @@ public interface HomematicThingTypeProvider extends ThingTypeProvider { * Adds the ThingType to this provider. */ public void addThingType(ThingType thingType); - + /** * Use this method to lookup a ThingType which was generated by the * homematic binding. Other than {@link #getThingType(ThingTypeUID, Locale)} @@ -42,5 +42,4 @@ public interface HomematicThingTypeProvider extends ThingTypeProvider { * before */ public ThingType getInternalThingType(ThingTypeUID thingTypeUID); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicTypeGenerator.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicTypeGenerator.java index d8c5c980207c1..43ba6b4b22e80 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicTypeGenerator.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicTypeGenerator.java @@ -35,5 +35,4 @@ public interface HomematicTypeGenerator { * different datapoints which may cause warnings in the logfile. */ public void validateFirmwares(); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicTypeGeneratorImpl.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicTypeGeneratorImpl.java index 2073998cad525..83b35f70acf13 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicTypeGeneratorImpl.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/HomematicTypeGeneratorImpl.java @@ -376,5 +376,4 @@ private URI getConfigDescriptionURI(HmDevice device) { public static boolean isIgnoredDatapoint(HmDatapoint dp) { return StringUtils.indexOfAny(dp.getName(), IGNORE_DATAPOINT_NAMES) != -1; } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/MetadataUtils.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/MetadataUtils.java index f588d7b23ef8b..55f2f75cd0ebf 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/MetadataUtils.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/MetadataUtils.java @@ -392,5 +392,4 @@ public static String getCategory(HmDatapoint dp, String itemType) { return null; } } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/UidUtils.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/UidUtils.java index 865608f09eeab..32c378d92a47d 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/UidUtils.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/internal/type/UidUtils.java @@ -93,5 +93,4 @@ public static HmDatapointInfo createHmDatapointInfo(ChannelUID channelUID) { public static String getHomematicAddress(Thing thing) { return thing.getUID().getId(); } - } diff --git a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/type/HomematicThingTypeExcluder.java b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/type/HomematicThingTypeExcluder.java index aff40d532b363..822a853d07499 100644 --- a/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/type/HomematicThingTypeExcluder.java +++ b/bundles/org.openhab.binding.homematic/src/main/java/org/openhab/binding/homematic/type/HomematicThingTypeExcluder.java @@ -89,5 +89,4 @@ public interface HomematicThingTypeExcluder { * excluded */ public boolean isConfigDescriptionExcluded(URI configDescriptionURI); - } diff --git a/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/binding/binding.xml index d7d5ed926cd41..0927c2f831e97 100644 --- a/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Homematic Binding diff --git a/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/config/config.xml index 73290511a1adf..48eefe98637ed 100644 --- a/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/config/config.xml @@ -1,12 +1,14 @@ - - Delays transmission of a command to the Homematic gateway, duplicate commands are filtered out (in seconds) + Delays transmission of a command to the Homematic gateway, duplicate commands are filtered out (in + seconds) 0.0 diff --git a/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/thing/bridge.xml index 7d86ee2afd455..6910f697118da 100644 --- a/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.homematic/src/main/resources/ESH-INF/thing/bridge.xml @@ -10,7 +10,7 @@ The Homematic bridge represents a Homematic gateway - + serialNumber @@ -44,11 +44,13 @@ - Callback port of the binding's XML-RPC server. If no value is specified, xmlCallbackPort starts with 9125 and counts up + Callback port of the binding's XML-RPC server. If no value is specified, xmlCallbackPort starts with + 9125 and counts up - Callback port of the binding's BIN-RPC server. If no value is specified, xmlCallbackPort starts with 9126 and counts up + Callback port of the binding's BIN-RPC server. If no value is specified, xmlCallbackPort starts with + 9126 and counts up @@ -105,13 +107,16 @@ - If set to true, devices are unpaired from the gateway when their corresponding things are removed. The option "factoryResetOnDeletion" also unpairs a device, so in order to avoid unpairing on deletion, both options need to be set to false! + If set to true, devices are unpaired from the gateway when their corresponding things are removed. The + option "factoryResetOnDeletion" also unpairs a device, so in order to avoid unpairing on deletion, both options + need to be set to false! true false - If set to true, devices are factory reset when their corresponding things are removed. Due to the factory reset, the device will also be unpaired from the gateway, even if "unpairOnDeletion" is set to false! + If set to true, devices are factory reset when their corresponding things are removed. Due to the + factory reset, the device will also be unpaired from the gateway, even if "unpairOnDeletion" is set to false! true false @@ -123,6 +128,6 @@ Number Current duty cycle usage - + diff --git a/bundles/org.openhab.binding.homematic/src/main/resources/homematic/extra-descriptions.properties b/bundles/org.openhab.binding.homematic/src/main/resources/homematic/extra-descriptions.properties index 4e82249291dc2..a41fcfd79ebe3 100644 --- a/bundles/org.openhab.binding.homematic/src/main/resources/homematic/extra-descriptions.properties +++ b/bundles/org.openhab.binding.homematic/src/main/resources/homematic/extra-descriptions.properties @@ -58,6 +58,13 @@ HmIP-FROLL=Homematic IP Wireless Blind Actuator HmIP-BROLL=Homematic IP Wireless Blind Actuator for brand switches HmIP-BRC2=Homematic IP Wall-mount Remote Control for brand switches - 2 channels HmIP-MOD-TM=Homematic IP Garage Door Module +HmIP-SWD=Homematic IP Water Sensor +HmIP-BSL=Homematic IP Switch Actuator for brand switches – with signal lamp +HmIPW-DRS4=Homematic IP Wired Switch Actuator – 4 channels +HmIPW-DRS8=Homematic IP Wired Switch Actuator – 8 channels +HmIPW-DRAP=Homematic IP Wired Access Point DRAP +HmIPW-DRI16=Homematic IP Wired Input Module – 16 channels +HmIPW-DRI32=Homematic IP Wired Input Module – 32 channels # virtual datapoints DELETE_DEVICE_MODE=Deletemode diff --git a/bundles/org.openhab.binding.homematic/src/main/resources/homematic/extra-descriptions_de.properties b/bundles/org.openhab.binding.homematic/src/main/resources/homematic/extra-descriptions_de.properties index 78e9b8cd33ec4..ef936d9230c2d 100644 --- a/bundles/org.openhab.binding.homematic/src/main/resources/homematic/extra-descriptions_de.properties +++ b/bundles/org.openhab.binding.homematic/src/main/resources/homematic/extra-descriptions_de.properties @@ -58,6 +58,13 @@ HmIP-FROLL=Homematic IP Rolladenaktor HmIP-BROLL=Homematic IP Rolladenaktor fr Markenschalter HmIP-BRC2=Homematic IP Wandtaster fr Markenschalter - 2-fach HmIP-MOD-HomematicIP=Tormatic Modul +HmIP-SWD=Homematic IP Wassersensor +HmIP-BSL=Homematic IP Schaltaktor fr Markenschalter mit Signalleuchte +HmIPW-DRS4=Homematic IP Wired 4-fach-Schaltaktor +HmIPW-DRS8=Homematic IP Wired 8-fach-Schaltaktor +HmIPW-DRAP=Homematic IP Wired Access Point DRAP +HmIPW-DRI16=Homematic IP Wired 16-fach-Eingangsmodul +HmIPW-DRI32=Homematic IP Wired 32-fach-Eingangsmodul # Virtuelle Datenpunkte DELETE_DEVICE_MODE=Lschmodus diff --git a/bundles/org.openhab.binding.homematic/src/main/resources/homematic/tclrega-scripts.xml b/bundles/org.openhab.binding.homematic/src/main/resources/homematic/tclrega-scripts.xml index 836c333143959..cd7f81feca5d4 100644 --- a/bundles/org.openhab.binding.homematic/src/main/resources/homematic/tclrega-scripts.xml +++ b/bundles/org.openhab.binding.homematic/src/main/resources/homematic/tclrega-scripts.xml @@ -14,7 +14,7 @@ foreach (sys_var_id, dom.GetObject(ID_SYSTEM_VARIABLES).EnumUsedIDs()) { Write("' description='"); WriteXML(var_obj.DPInfo()); Write("' info='"); WriteXML(var_obj.Name()); Write("' value='"); WriteXML(var_obj.Value()); - + var var_type = "UNKNOWN"; if (var_obj.ValueType() == 2 ) { var_type = "BOOL"; } if (var_obj.ValueType() == 16 ) { var_type = "ENUM"; } @@ -97,8 +97,8 @@ Write(''); ]]> - - + - + + + diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java index 3979c6f9dc539..0ec108701d6a3 100644 --- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java +++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/communicator/virtual/ButtonDatapointTest.java @@ -143,7 +143,6 @@ public void eventReceived(HmDatapoint dp) throws IOException, HomematicClientExc if (dp.isPressDatapoint() && MiscUtils.isTrueValue(dp.getValue())) { disableDatapoint(dp); } - } private void disableDatapoint(HmDatapoint dp) { @@ -155,7 +154,5 @@ private void disableDatapoint(HmDatapoint dp) { } }).start(); } - } - } diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/BaseConverterTest.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/BaseConverterTest.java index 07cbbf7f9b262..380607a32e852 100644 --- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/BaseConverterTest.java +++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/BaseConverterTest.java @@ -40,5 +40,4 @@ public void setup() { stubChannel.setDevice(new HmDevice("LEQ123456", HmInterface.RF, "HM-STUB-DEVICE", "", "", "")); floatDp.setChannel(stubChannel); } - } diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/ConvertFromBindingTest.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/ConvertFromBindingTest.java index 2a9cead5fc0f5..7f3eb06ed14e5 100644 --- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/ConvertFromBindingTest.java +++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/ConvertFromBindingTest.java @@ -100,7 +100,5 @@ public void testQuantityTypeConverter() throws ConverterException { assertThat(((QuantityType) convertedState).doubleValue(), is(70.0)); assertThat(((QuantityType) convertedState).getUnit(), is(SmartHomeUnits.PERCENT)); assertThat(((QuantityType) convertedState).toUnit(SmartHomeUnits.ONE).doubleValue(), is(0.7)); - } - } diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/ConverterFactoryTest.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/ConverterFactoryTest.java index 52d257f52ae2b..be8fde7081032 100644 --- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/ConverterFactoryTest.java +++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/converter/ConverterFactoryTest.java @@ -42,5 +42,4 @@ public void testTypesOfCreatedConverters() throws ConverterException { assertThat(ConverterFactory.createConverter("Number:Temperature"), instanceOf(QuantityTypeConverter.class)); assertThat(ConverterFactory.createConverter("Number:Percent"), instanceOf(QuantityTypeConverter.class)); } - } diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/handler/SimplePortPoolTest.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/handler/SimplePortPoolTest.java index 1c336fd4f03e4..e22056af39c05 100644 --- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/handler/SimplePortPoolTest.java +++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/handler/SimplePortPoolTest.java @@ -21,13 +21,11 @@ import org.junit.Before; import org.junit.Test; -import org.openhab.binding.homematic.internal.handler.SimplePortPool; /** - * Tests for {@link SimplePortPool}. - * - * @author Florian Stolte - Initial Contribution + * Tests for {@link org.openhab.binding.homematic.internal.handler.SimplePortPool}. * + * @author Florian Stolte - Initial Contribution */ public class SimplePortPoolTest { diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/type/UidUtilsTest.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/type/UidUtilsTest.java index e6ddb1b54f038..a2e62cc3defaf 100644 --- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/type/UidUtilsTest.java +++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/internal/type/UidUtilsTest.java @@ -29,7 +29,6 @@ import org.openhab.binding.homematic.internal.model.HmDatapoint; import org.openhab.binding.homematic.internal.model.HmDatapointInfo; import org.openhab.binding.homematic.internal.model.HmDevice; -import org.openhab.binding.homematic.internal.type.UidUtils; /** * Tests for {@link UidUtilsTest}. @@ -114,5 +113,4 @@ public void testHomematicAddressIsGeneratedFromThingID() { assertThat(generatedAddress, is("ABC12345678")); } - } diff --git a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/test/util/RpcClientMockImpl.java b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/test/util/RpcClientMockImpl.java index 9f5be55e1f448..aa96a9ab509c6 100644 --- a/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/test/util/RpcClientMockImpl.java +++ b/bundles/org.openhab.binding.homematic/src/test/java/org/openhab/binding/homematic/test/util/RpcClientMockImpl.java @@ -82,7 +82,6 @@ public String createMessage() { public String getMethodName() { return methodName; } - }; } diff --git a/bundles/org.openhab.binding.hpprinter/README.md b/bundles/org.openhab.binding.hpprinter/README.md index 4c066efe193c6..55893a8d26b0a 100644 --- a/bundles/org.openhab.binding.hpprinter/README.md +++ b/bundles/org.openhab.binding.hpprinter/README.md @@ -1,4 +1,4 @@ -# HPPrinter Binding +# HP Printer Binding Get HP Printer statistics from an _Embedded Web Server_ over Network. @@ -19,7 +19,7 @@ The available settings are: | Usage Refresh Interval (seconds) | usageInterval | number | | 30 | | Status Refresh Interval (seconds) | statusInterval | number | | 4 | -An example configuration is below: +### Sample Configuration ``` Thing hpprinter:printer:djprinter "Printer" @ "Office" [ ipAddress="192.168.1.1", usageInterval="30", statusInterval="4" ] @@ -27,24 +27,67 @@ Thing hpprinter:printer:djprinter "Printer" @ "Office" [ ipAddress="192.168.1.1" ## Channels -| Channel | Name | Data Type | Dynamic | -| ------------------------------------------ | -------------------- | --------- | ------- | -| Printer Status | status | String | no | -| Black Colour Level | blackLevel | Number | no | -| Colour Level | colorLevel | Number | yes | -| Cyan Colour Level | cyanLevel | Number | yes | -| Magenta Colour Level | magentaLevel | Number | yes | -| Yellow Colour Level | yellowLevel | Number | yes | -| Black Marking Used | blackMarker | Number | yes | -| Colour Marking Used | colorMarker | Number | yes | -| Cyan Marking Used | cyanMarker | Number | yes | -| Magenta Marking Used | magentaMarker | Number | yes | -| Yellow Marking Used | yellowMarker | Number | yes | -| Total Number of Pages Printed | totalCount | Number | no | -| Total Number of Colour Pages Printed | totalColorCount | Number | yes | -| Total Number of Monochrome Pages Printed | totalMonochromeCount | Number | yes | -| Jam Events | jamEvents | Number | yes | -| Mispick Events | mispickEvents | Number | yes | -| Front Panel Cancel Count | fpCount | Number | yes | +| Channel | Name | Data Type | Dynamic | +| ------------------------------------------ | -------------------- | -------------------- | ------- | +| Printer Status | status | String | no | +| Black Colour Level | blackLevel | Number:Dimensionless | no | +| Colour Level | colorLevel | Number:Dimensionless | yes | +| Cyan Colour Level | cyanLevel | Number:Dimensionless | yes | +| Magenta Colour Level | magentaLevel | Number:Dimensionless | yes | +| Yellow Colour Level | yellowLevel | Number:Dimensionless | yes | +| Black Marking Used | blackMarker | Number:Volume | yes | +| Colour Marking Used | colorMarker | Number:Volume | yes | +| Cyan Marking Used | cyanMarker | Number:Volume | yes | +| Magenta Marking Used | magentaMarker | Number:Volume | yes | +| Yellow Marking Used | yellowMarker | Number:Volume | yes | +| Total Number of Pages Printed | totalCount | Number | no | +| Total Number of Colour Pages Printed | totalColorCount | Number | yes | +| Total Number of Monochrome Pages Printed | totalMonochromeCount | Number | yes | +| Jam Events | jamEvents | Number | yes | +| Mispick Events | mispickEvents | Number | yes | +| Front Panel Cancel Count | fpCount | Number | yes | > The `colorLevel` is used on Printers that have only a single colour cartridge instead of separate Cyan, Magenta and Yellow cartridges. + +### Sample Items + +``` +String PrinterStatus "Status" { channel="pprinter:printer:djprinter:status#status" } +Number PrinterTotalPages "Total Pages" { channel="hpprinter:printer:djprinter:usage#totalCount" } + +Number:Volume PrinterBlackMarkingUsed "Black Marking Used" { channel="hpprinter:printer:djprinter:usage#blackMarker" } +Number:Volume PrinterCyanMarkingUsed "Cyan Marking Used" { channel="hpprinter:printer:djprinter:usage#cyanMarker" } +Number:Volume PrinterMagentaMarkingUsed "Magenta Marking Used" { channel="hpprinter:printer:djprinter:usage#magentaMarker" } +Number:Volume PrinterYellowMarkingUsed "Yellow Marking Used" { channel="hpprinter:printer:djprinter:usage#yellowMarker" } + +Number:Dimensionless PrinterBlackLevel "Black Level" { channel="hpprinter:printer:djprinter:ink#blackLevel" } +Number:Dimensionless PrinterCyanLevel "Cyan Level" { channel="hpprinter:printer:djprinter:ink#cyanLevel" } +Number:Dimensionless PrinterMagentaLevel "Magenta Level" { channel="hpprinter:printer:djprinter:ink#magentaLevel" } +Number:Dimensionless PrinterYellowLevel "Yellow Level" { channel="hpprinter:printer:djprinter:ink#yellowLevel" } + +Number PrinterTotalColourPages "Total Colour Pages" { channel="hpprinter:printer:djprinter:usage#totalColorCount" } +Number PrinterTotalMonochromePages "Total Monochrome Pages" { channel="hpprinter:printer:djprinter:usage#totalMonochromeCount" } +Number PrinterJamEvents "Jam Events" { channel="hpprinter:printer:djprinter:usage#jamEvents" } +Number PrinterMispickEvents "Mispick Events" { channel="hpprinter:printer:djprinter:usage#mispickEvents" } +Number PrinterSubscriptionCount "Subscription Count" { channel="hpprinter:printer:djprinter:usage#subsciptionCount" } +``` + +### Sample Sitemap Items + +Black Ink displayed as a whole percentage - `60 %` + +``` +Text item=hpprinter_printer_djprinter_ink_blackLevel label="Black [%.0f %unit%]" +``` + +Black Marker displayed in millilitres - `21 ml` + +``` +Text item=hpprinter_printer_djprinter_usage_blackMarker label="Black Marker [%.0f %unit%]" +``` + +Black Marker displayed in litres - `0.021 l` + +``` +Text item=hpprinter_printer_djprinter_usage_blackMarker label="Black Marker [%.3f l]" +``` \ No newline at end of file diff --git a/bundles/org.openhab.binding.hpprinter/pom.xml b/bundles/org.openhab.binding.hpprinter/pom.xml index 83a7080bcd3a2..9b52c752e4e42 100644 --- a/bundles/org.openhab.binding.hpprinter/pom.xml +++ b/bundles/org.openhab.binding.hpprinter/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.hpprinter diff --git a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/HPPrinterBindingConstants.java b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/HPPrinterBindingConstants.java index af234f460c01e..c303905e423e7 100644 --- a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/HPPrinterBindingConstants.java +++ b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/HPPrinterBindingConstants.java @@ -36,6 +36,9 @@ public class HPPrinterBindingConstants { public static final Set SUPPORTED_THING_TYPES_UIDS = Stream.of(THING_PRINTER) .collect(Collectors.toSet()); + // ********** Channel Types ********** + public static final String CHAN_TYPE_CUMLMARK = "Number:Volume"; + public static final String CHAN_TYPE_INK = "Number:Dimensionless"; // ********** List of all Channel ids ********** public static final String CHANNEL_STATUS = "status"; diff --git a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPStatus.java b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPStatus.java index c35b77179f511..dc11211e02f51 100644 --- a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPStatus.java +++ b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPStatus.java @@ -32,12 +32,12 @@ public class HPStatus { private static final Map STATUS_MESSAGES = initializeStatus(); - private final @Nullable String printerStatus; + private final String printerStatus; public HPStatus(Document document) { NodeList nodes = document.getDocumentElement().getElementsByTagName("psdyn:Status"); - String localPrinterStatus = null; + String localPrinterStatus = "Unknown"; for (int i = 0; i < nodes.getLength(); i++) { Element element = (Element) nodes.item(i); String statusCategory = element.getElementsByTagName("pscat:StatusCategory").item(0).getTextContent(); @@ -51,18 +51,18 @@ public HPStatus(Document document) { private static Map initializeStatus() { Map statusMap = new HashMap<>(); - statusMap.put("processing", "Printing"); - statusMap.put("scanProcessing", "Scanning"); + statusMap.put("processing", "Printing..."); + statusMap.put("scanProcessing", "Scanning..."); statusMap.put("inPowerSave", "Power Save"); statusMap.put("ready", "Idle"); statusMap.put("initializing", "Initializing..."); statusMap.put("closeDoorOrCover", "Door/Cover Open"); - statusMap.put("inkSystemInitializing", "Loading Ink"); - statusMap.put("shuttingDown", "Shutting Down"); + statusMap.put("inkSystemInitializing", "Loading Ink..."); + statusMap.put("shuttingDown", "Shutting Down..."); return statusMap; } public @Nullable String getPrinterStatus() { - return STATUS_MESSAGES.get(printerStatus); + return printerStatus; } } diff --git a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPUsage.java b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPUsage.java index c773a0d1149bc..96a795cc420ad 100644 --- a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPUsage.java +++ b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPUsage.java @@ -216,5 +216,4 @@ public int getInkColor() { public float getInkColorMarking() { return inkColorMarking; } - } diff --git a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPWebServerClient.java b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPWebServerClient.java index c4dc4df8a990a..562fe81c6fda6 100644 --- a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPWebServerClient.java +++ b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/api/HPWebServerClient.java @@ -112,5 +112,4 @@ private synchronized Document getDocument(String contentAsString) InputSource source = new InputSource(new StringReader(contentAsString)); return builder.parse(source); } - } diff --git a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/binder/HPPrinterBinder.java b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/binder/HPPrinterBinder.java index 290ab8e242925..a7c1b113f2eb6 100644 --- a/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/binder/HPPrinterBinder.java +++ b/bundles/org.openhab.binding.hpprinter/src/main/java/org/openhab/binding/hpprinter/internal/binder/HPPrinterBinder.java @@ -36,6 +36,7 @@ import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; +import org.openhab.binding.hpprinter.internal.HPPrinterBindingConstants; import org.openhab.binding.hpprinter.internal.HPPrinterConfiguration; import org.openhab.binding.hpprinter.internal.api.HPProperties; import org.openhab.binding.hpprinter.internal.api.HPServerResult; @@ -116,7 +117,8 @@ public void dynamicallyAddChannels(ThingUID thingUid) { if (data.hasCumulativeMarking()) { channels.add(ChannelBuilder - .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_MARKING), CoreItemFactory.NUMBER) + .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_BLACK_MARKING), + HPPrinterBindingConstants.CHAN_TYPE_CUMLMARK) .withLabel("Black Marking Used").withDescription("The amount of Black Marking used") .withType(new ChannelTypeUID("hpprinter:cumlMarkingUsed")).build()); } @@ -126,13 +128,14 @@ public void dynamicallyAddChannels(ThingUID thingUid) { if (data.hasCumulativeMarking()) { channels.add(ChannelBuilder .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_COLOR_MARKING), - CoreItemFactory.NUMBER) + HPPrinterBindingConstants.CHAN_TYPE_CUMLMARK) .withLabel("Colour Marking Used").withDescription("The amount of Colour Marking used") .withType(new ChannelTypeUID("hpprinter:cumlMarkingUsed")).build()); } channels.add(ChannelBuilder - .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_COLOR_LEVEL), CoreItemFactory.NUMBER) + .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_COLOR_LEVEL), + HPPrinterBindingConstants.CHAN_TYPE_INK) .withLabel("Color Level").withDescription("Shows the amount of Colour Ink/Toner remaining") .withType(new ChannelTypeUID("hpprinter:inkLevel")).build()); @@ -155,36 +158,39 @@ public void dynamicallyAddChannels(ThingUID thingUid) { if (data.hasCumulativeMarking()) { channels.add(ChannelBuilder .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_CYAN_MARKING), - CoreItemFactory.NUMBER) + HPPrinterBindingConstants.CHAN_TYPE_CUMLMARK) .withLabel("Cyan Marking Used").withDescription("The amount of Cyan Marking used") .withType(new ChannelTypeUID("hpprinter:cumlMarkingUsed")).build()); channels.add(ChannelBuilder .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_MAGENTA_MARKING), - CoreItemFactory.NUMBER) + HPPrinterBindingConstants.CHAN_TYPE_CUMLMARK) .withLabel("Magenta Marking Used").withDescription("The amount of Magenta Marking used") .withType(new ChannelTypeUID("hpprinter:cumlMarkingUsed")).build()); channels.add(ChannelBuilder .create(new ChannelUID(thingUid, CGROUP_USAGE, CHANNEL_YELLOW_MARKING), - CoreItemFactory.NUMBER) + HPPrinterBindingConstants.CHAN_TYPE_CUMLMARK) .withLabel("Yellow Marking Used").withDescription("The amount of Yellow Marking used") .withType(new ChannelTypeUID("hpprinter:cumlMarkingUsed")).build()); } channels.add(ChannelBuilder - .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_CYAN_LEVEL), CoreItemFactory.NUMBER) + .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_CYAN_LEVEL), + HPPrinterBindingConstants.CHAN_TYPE_INK) .withLabel("Cyan Level").withDescription("Shows the amount of Cyan Ink/Toner remaining") .withType(new ChannelTypeUID("hpprinter:inkLevel")).build()); channels.add(ChannelBuilder - .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_MAGENTA_LEVEL), CoreItemFactory.NUMBER) + .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_MAGENTA_LEVEL), + HPPrinterBindingConstants.CHAN_TYPE_INK) .withLabel("Magenta Level") .withDescription("Shows the amount of Magenta Ink/Toner remaining") .withType(new ChannelTypeUID("hpprinter:inkLevel")).build()); channels.add(ChannelBuilder - .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_YELLOW_LEVEL), CoreItemFactory.NUMBER) + .create(new ChannelUID(thingUid, CGROUP_INK, CHANNEL_YELLOW_LEVEL), + HPPrinterBindingConstants.CHAN_TYPE_INK) .withLabel("Yellow Level").withDescription("Shows the amount of Yellow Ink/Toner remaining") .withType(new ChannelTypeUID("hpprinter:inkLevel")).build()); diff --git a/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/channel-groups.xml b/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/channel-groups.xml index fa2d768da05d6..313838d63bb8f 100644 --- a/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/channel-groups.xml +++ b/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/channel-groups.xml @@ -27,7 +27,7 @@ - + diff --git a/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/channel-types.xml index ab5725ea6ddad..5fb355b180668 100644 --- a/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/channel-types.xml @@ -7,34 +7,34 @@ Number:Dimensionless Shows the amount of Ink/Toner remaining - + Number Amount of pages. - + String Shows the estimated amount of pages remaining - + Number:Volume Shows the amount of Ink/Toner used - + String Printer Status - + diff --git a/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/thing-printer.xml b/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/thing-printer.xml index ccdad17744cbf..c25068ebfbe3f 100644 --- a/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/thing-printer.xml +++ b/bundles/org.openhab.binding.hpprinter/src/main/resources/ESH-INF/thing/thing-printer.xml @@ -8,15 +8,15 @@ An HP Printer. - - - + + + HP serialNumber - + diff --git a/bundles/org.openhab.binding.hue/README.md b/bundles/org.openhab.binding.hue/README.md index bc2c6ac88a9e4..93aeb290ff9a8 100644 --- a/bundles/org.openhab.binding.hue/README.md +++ b/bundles/org.openhab.binding.hue/README.md @@ -75,11 +75,13 @@ hue:0210:00178810d0dc:1 The thing type is the second string behind the first colon and in this example it is **0210**. +Finally, the Hue binding also supports the groups of lights and rooms set up on the Hue bridge. + ## Discovery The Hue bridge is discovered through UPnP in the local network. Once it is added as a Thing, its authentication button (in the middle) needs to be pressed in order to authorize the binding to access it. -Once the binding is authorized, it automatically reads all devices that are set up on the Hue bridge and puts them into the Inbox. +Once the binding is authorized, it automatically reads all devices and groups that are set up on the Hue bridge and puts them into the Inbox. ## Thing Configuration @@ -138,16 +140,36 @@ The following device types also have an optional configuration value to specify | fadetime | Fade time in Milliseconds to a new state (min="0", step="100", default="400") | +### Groups + +The groups are identified by the number that the Hue bridge assigns to them. +Thus, all it needs for manual configuration is this single value like + +``` +group kitchen-bulbs "Kitchen Lamps" @ "Kitchen" [ groupId="1" ] +``` + +You can freely choose the thing identifier (such as kitchen-bulbs), its name (such as "Kitchen Lamps") and the location (such as "Kitchen"). +The name will then be used e.g. by Paper UI to show the item. + +The group type also have an optional configuration value to specify the fade time in milliseconds for the transition to a new state. + +| Parameter | Description | +|-----------|-------------------------------------------------------------------------------| +| groupId | Number of the group provided by the Hue bridge. **Mandatory** | +| fadetime | Fade time in Milliseconds to a new state (min="0", step="100", default="400") | + + ## Channels The devices support some of the following channels: | Channel Type ID | Item Type | Description | Thing types supporting this channel | |-------------------|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------| -| switch | Switch | This channel supports switching the device on and off. | 0000, 0010 | -| color | Color | This channel supports full color control with hue, saturation and brightness values. | 0200, 0210 | -| brightness | Dimmer | This channel supports adjusting the brightness value. Note that this is not available, if the color channel is supported. | 0100, 0110, 0220 | -| color_temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | 0210, 0220 | +| switch | Switch | This channel supports switching the device on and off. | 0000, 0010, group | +| color | Color | This channel supports full color control with hue, saturation and brightness values. | 0200, 0210, group | +| brightness | Dimmer | This channel supports adjusting the brightness value. Note that this is not available, if the color channel is supported. | 0100, 0110, 0220, group | +| color_temperature | Dimmer | This channel supports adjusting the color temperature from cold (0%) to warm (100%). | 0210, 0220, group | | alert | String | This channel supports displaying alerts by flashing the bulb either once or multiple times. Valid values are: NONE, SELECT and LSELECT. | 0000, 0100, 0200, 0210, 0220 | | effect | Switch | This channel supports color looping. | 0200, 0210, 0220 | | dimmer_switch | Number | This channel shows which button was last pressed on the dimmer switch. | 0820 | @@ -236,12 +258,13 @@ And there is one Hue Motion Sensor (represented by three devices) and a Hue Dimm ``` Bridge hue:bridge:1 "Hue Bridge" [ ipAddress="192.168.0.64" ] { - 0210 bulb1 "Lamp 1" @ "Kitchen" [ lightId="1" ] - 0220 bulb2 "Lamp 2" @ "Kitchen" [ lightId="2" ] - 0106 light-level-sensor "Light-Sensor" @ "Entrance" [ sensorId="3" ] - 0107 motion-sensor "Motion-Sensor" @ "Entrance" [ sensorId="4" ] - 0302 temperature-sensor "Temp-Sensor" @ "Entrance" [ sensorId="5" ] - 0820 dimmer-switch "Dimmer-Switch" @ "Entrance" [ sensorId="6" ] + 0210 bulb1 "Lamp 1" @ "Kitchen" [ lightId="1" ] + 0220 bulb2 "Lamp 2" @ "Kitchen" [ lightId="2" ] + group kitchen-bulbs "Kitchen Lamps" @ "Kitchen" [ groupId="1" ] + 0106 light-level-sensor "Light-Sensor" @ "Entrance" [ sensorId="3" ] + 0107 motion-sensor "Motion-Sensor" @ "Entrance" [ sensorId="4" ] + 0302 temperature-sensor "Temp-Sensor" @ "Entrance" [ sensorId="5" ] + 0820 dimmer-switch "Dimmer-Switch" @ "Entrance" [ sensorId="6" ] } ``` @@ -261,6 +284,12 @@ Switch Light2_Toggle { channel="hue:0220:1:bulb2:brightness" } Dimmer Light2_Dimmer { channel="hue:0220:1:bulb2:brightness" } Dimmer Light2_ColorTemp { channel="hue:0220:1:bulb2:color_temperature" } +// Kitchen +Switch Kitchen_Switch { channel="hue:group:1:kitchen-bulbs:switch" } +Dimmer Kitchen_Dimmer { channel="hue:group:1:kitchen-bulbs:brightness" } +Color Kitchen_Color { channel="hue:group:1:kitchen-bulbs:color" } +Dimmer Kitchen_ColorTemp { channel="hue:group:1:kitchen-bulbs:color_temperature" } + // Light Level Sensor Number:Illuminance LightLevelSensorIlluminance { channel="hue:0106:1:light-level-sensor:illuminance" } @@ -296,6 +325,12 @@ sitemap demo label="Main Menu" Slider item= Light2_Dimmer Slider item= Light2_ColorTemp + // Kitchen + Switch item= Kitchen_Switch + Slider item= Kitchen_Dimmer + Colorpicker item= Kitchen_Color + Slider item= Kitchen_ColorTemp + // Motion Sensor Switch item=MotionSensorPresence Text item=MotionSensorLastUpdate diff --git a/bundles/org.openhab.binding.hue/pom.xml b/bundles/org.openhab.binding.hue/pom.xml index f2b44b5aa2645..5b723be42088c 100644 --- a/bundles/org.openhab.binding.hue/pom.xml +++ b/bundles/org.openhab.binding.hue/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.hue diff --git a/bundles/org.openhab.binding.hue/src/main/feature/feature.xml b/bundles/org.openhab.binding.hue/src/main/feature/feature.xml index 4fa260af97a0c..abc121f42ed8b 100644 --- a/bundles/org.openhab.binding.hue/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.hue/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.hue/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.hue/${project.version} + diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/ApiVersion.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/ApiVersion.java index 7efea2a71e6ac..a4e59c902626f 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/ApiVersion.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/ApiVersion.java @@ -91,7 +91,6 @@ public int compare(ApiVersion other) { } } return c; - } @Override @@ -132,5 +131,4 @@ public boolean equals(Object obj) { public String toString() { return major + "." + minor + "." + micro; } - } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/Config.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/Config.java index 8ecb909a756c7..cf3b84bf59a79 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/Config.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/Config.java @@ -196,5 +196,4 @@ public String getApiVersion() { } return apiversion; } - } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/FullGroup.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/FullGroup.java index 222929e27fc7e..f51b8974df21e 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/FullGroup.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/FullGroup.java @@ -12,17 +12,26 @@ */ package org.openhab.binding.hue.internal; +import java.lang.reflect.Type; import java.util.List; +import java.util.Map; + +import com.google.gson.reflect.TypeToken; /** * Detailed group information. * * @author Q42 - Initial contribution * @author Denis Dudnik - moved Jue library source code inside the smarthome Hue binding + * @author Laurent Garnier - field state added */ public class FullGroup extends Group { + public static final Type GSON_TYPE = new TypeToken>() { + }.getType(); + private State action; private List lights; + private State state; // Will not be set by hue API FullGroup() { } @@ -42,7 +51,16 @@ public State getAction() { * * @return lights in the group */ - public List getLights() { - return Util.idsToLights(lights); + public List getLights() { + return lights; + } + + /** + * Returns the current state of the group. + * + * @return current state + */ + public State getState() { + return state; } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/Group.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/Group.java index 1e2103e5168f7..f921af7a5bc6a 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/Group.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/Group.java @@ -12,27 +12,22 @@ */ package org.openhab.binding.hue.internal; -import java.lang.reflect.Type; -import java.util.Map; - -import com.google.gson.reflect.TypeToken; - /** * Basic group information. * * @author Q42 - Initial contribution * @author Denis Dudnik - moved Jue library source code inside the smarthome Hue binding + * @author Laurent Garnier - field type added */ public class Group { - public static final Type GSON_TYPE = new TypeToken>() { - }.getType(); - private String id; private String name; + private String type; Group() { this.id = "0"; this.name = "Lightset 0"; + this.type = "LightGroup"; } void setName(String name) { @@ -43,6 +38,10 @@ void setId(String id) { this.id = id; } + void setType(String type) { + this.type = type; + } + /** * Returns if the group can be modified. * Currently only returns false for the all lights pseudo group. @@ -70,4 +69,13 @@ public String getId() { public String getName() { return name; } + + /** + * Returns the tyoe of the group. + * + * @return type + */ + public String getType() { + return type; + } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueBindingConstants.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueBindingConstants.java index 7802c2e216b31..66eb7a84e89b0 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueBindingConstants.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueBindingConstants.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.hue.internal; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.ThingTypeUID; /** @@ -25,6 +26,7 @@ * @author Samuel Leisering - Added support for sensor API * @author Christoph Weitkamp - Added support for sensor API */ +@NonNullByDefault public class HueBindingConstants { public static final String BINDING_ID = "hue"; @@ -51,6 +53,8 @@ public class HueBindingConstants { public static final ThingTypeUID THING_TYPE_TEMPERATURE_SENSOR = new ThingTypeUID(BINDING_ID, "0302"); public static final ThingTypeUID THING_TYPE_LIGHT_LEVEL_SENSOR = new ThingTypeUID(BINDING_ID, "0106"); + public static final ThingTypeUID THING_TYPE_GROUP = new ThingTypeUID(BINDING_ID, "group"); + // List all channels public static final String CHANNEL_COLORTEMPERATURE = "color_temperature"; public static final String CHANNEL_COLOR = "color"; @@ -88,6 +92,7 @@ public class HueBindingConstants { public static final String PRODUCT_NAME = "productName"; public static final String UNIQUE_ID = "uniqueId"; public static final String FADETIME = "fadetime"; + public static final String GROUP_ID = "groupId"; public static final String NORMALIZE_ID_REGEX = "[^a-zA-Z0-9_]"; } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueBridge.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueBridge.java index 048d9ca4cfbf9..37f6ccac3627d 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueBridge.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueBridge.java @@ -55,6 +55,7 @@ * @author Andre Fuechsel - search for lights with given serial number added * @author Denis Dudnik - moved Jue library source code inside the smarthome Hue binding, minor code cleanup * @author Samuel Leisering - added cached config and API-Version + * @author Laurent Garnier - change the return type of getGroups */ @NonNullByDefault public class HueBridge { @@ -377,10 +378,10 @@ public CompletableFuture setSensorState(FullSensor sensor, StateUpdate u requireAuthentication(); String body = update.toJson(); - return http.putAsync(getRelativeURL("sensors/" + enc(sensor.getId()) + "/state"), body, update.getMessageDelay(), - scheduler); - } - + return http.putAsync(getRelativeURL("sensors/" + enc(sensor.getId()) + "/state"), body, + update.getMessageDelay(), scheduler); + } + /** * Changes the config of a sensor. * @@ -415,20 +416,23 @@ public Group getAllGroup() { * @return list of groups * @throws UnauthorizedException thrown if the user no longer exists */ - public List getGroups() throws IOException, ApiException { + public List getGroups() throws IOException, ApiException { requireAuthentication(); Result result = http.get(getRelativeURL("groups")); handleErrors(result); - Map groupMap = safeFromJson(result.getBody(), Group.GSON_TYPE); - ArrayList groupList = new ArrayList<>(); + Map groupMap = safeFromJson(result.getBody(), FullGroup.GSON_TYPE); + ArrayList groupList = new ArrayList<>(); - groupList.add(new Group()); + if (groupMap.get("0") == null) { + // Group 0 is not returned, we create it as in fact it exists + groupList.add(getGroup(new Group())); + } for (String id : groupMap.keySet()) { - Group group = groupMap.get(id); + FullGroup group = groupMap.get(id); group.setId(id); groupList.add(group); } @@ -601,13 +605,12 @@ public String setGroupAttributes(Group group, String name, List light * @throws UnauthorizedException thrown if the user no longer exists * @throws EntityNotAvailableException thrown if the specified group no longer exists */ - public void setGroupState(Group group, StateUpdate update) throws IOException, ApiException { + public CompletableFuture setGroupState(Group group, StateUpdate update) { requireAuthentication(); String body = update.toJson(); - Result result = http.put(getRelativeURL("groups/" + enc(group.getId()) + "/action"), body); - - handleErrors(result); + return http.putAsync(getRelativeURL("groups/" + enc(group.getId()) + "/action"), body, update.getMessageDelay(), + scheduler); } /** diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueConfigStatusMessage.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueConfigStatusMessage.java index 7ad0911e2f71e..6474fb38d9966 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueConfigStatusMessage.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueConfigStatusMessage.java @@ -25,5 +25,4 @@ public interface HueConfigStatusMessage { static final String IP_ADDRESS_MISSING = "missing-ip-address-configuration"; - } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueThingHandlerFactory.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueThingHandlerFactory.java index f8d997699524b..2c0bf3df8a545 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueThingHandlerFactory.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/HueThingHandlerFactory.java @@ -35,6 +35,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.openhab.binding.hue.internal.discovery.HueLightDiscoveryService; import org.openhab.binding.hue.internal.handler.HueBridgeHandler; +import org.openhab.binding.hue.internal.handler.HueGroupHandler; import org.openhab.binding.hue.internal.handler.HueLightHandler; import org.openhab.binding.hue.internal.handler.sensors.ClipHandler; import org.openhab.binding.hue.internal.handler.sensors.DimmerSwitchHandler; @@ -53,16 +54,17 @@ * @author Andre Fuechsel - implemented to use one discovery service per bridge * @author Samuel Leisering - Added support for sensor API * @author Christoph Weitkamp - Added support for sensor API + * @author Laurent Garnier - Added support for groups */ @NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.hue") public class HueThingHandlerFactory extends BaseThingHandlerFactory { - public static final Set SUPPORTED_THING_TYPES = Collections.unmodifiableSet(Stream - .of(HueBridgeHandler.SUPPORTED_THING_TYPES.stream(), HueLightHandler.SUPPORTED_THING_TYPES.stream(), + public static final Set SUPPORTED_THING_TYPES = Collections.unmodifiableSet( + Stream.of(HueBridgeHandler.SUPPORTED_THING_TYPES.stream(), HueLightHandler.SUPPORTED_THING_TYPES.stream(), DimmerSwitchHandler.SUPPORTED_THING_TYPES.stream(), TapSwitchHandler.SUPPORTED_THING_TYPES.stream(), PresenceHandler.SUPPORTED_THING_TYPES.stream(), TemperatureHandler.SUPPORTED_THING_TYPES.stream(), - LightLevelHandler.SUPPORTED_THING_TYPES.stream(), ClipHandler.SUPPORTED_THING_TYPES.stream()) - .flatMap(i -> i).collect(Collectors.toSet())); + LightLevelHandler.SUPPORTED_THING_TYPES.stream(), ClipHandler.SUPPORTED_THING_TYPES.stream(), + HueGroupHandler.SUPPORTED_THING_TYPES.stream()).flatMap(i -> i).collect(Collectors.toSet())); private final Map> discoveryServiceRegs = new HashMap<>(); @@ -82,6 +84,9 @@ public class HueThingHandlerFactory extends BaseThingHandlerFactory { || ClipHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { ThingUID hueSensorUID = getSensorUID(thingTypeUID, thingUID, configuration, bridgeUID); return super.createThing(thingTypeUID, configuration, hueSensorUID, bridgeUID); + } else if (HueGroupHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { + ThingUID hueGroupUID = getGroupUID(thingTypeUID, thingUID, configuration, bridgeUID); + return super.createThing(thingTypeUID, configuration, hueGroupUID, bridgeUID); } throw new IllegalArgumentException("The thing type " + thingTypeUID + " is not supported by the hue binding."); @@ -110,6 +115,15 @@ private ThingUID getSensorUID(ThingTypeUID thingTypeUID, @Nullable ThingUID thin } } + private ThingUID getGroupUID(ThingTypeUID thingTypeUID, @Nullable ThingUID thingUID, Configuration configuration, + @Nullable ThingUID bridgeUID) { + if (thingUID != null) { + return thingUID; + } else { + return getThingUID(thingTypeUID, configuration.get(GROUP_ID).toString(), bridgeUID); + } + } + private ThingUID getThingUID(ThingTypeUID thingTypeUID, String id, @Nullable ThingUID bridgeUID) { if (bridgeUID != null) { return new ThingUID(thingTypeUID, id, bridgeUID.getId()); @@ -138,6 +152,8 @@ private ThingUID getThingUID(ThingTypeUID thingTypeUID, String id, @Nullable Thi return new LightLevelHandler(thing); } else if (ClipHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { return new ClipHandler(thing); + } else if (HueGroupHandler.SUPPORTED_THING_TYPES.contains(thing.getThingTypeUID())) { + return new HueGroupHandler(thing); } else { return null; } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/State.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/State.java index dafd8c183f810..5faf630504ca5 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/State.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/State.java @@ -19,6 +19,7 @@ * * @author Q42 - Initial contribution * @author Denis Dudnik - moved Jue library source code inside the smarthome Hue binding + * @author Laurent Garnier - add few methods to update the object */ public class State { private boolean on; @@ -99,6 +100,10 @@ public boolean isOn() { return on; } + public void setOn(boolean on) { + this.on = on; + } + /** * Returns the brightness. * @@ -108,6 +113,10 @@ public int getBrightness() { return bri; } + public void setBri(int bri) { + this.bri = bri; + } + /** * Returns the hue. * @@ -117,6 +126,10 @@ public int getHue() { return hue; } + public void setHue(int hue) { + this.hue = hue; + } + /** * Returns the saturation. * @@ -126,6 +139,10 @@ public int getSaturation() { return sat; } + public void setSaturation(int sat) { + this.sat = sat; + } + /** * Returns the coordinates in CIE color space. * @@ -135,6 +152,10 @@ public float[] getXY() { return xy; } + public void setXY(float[] xy) { + this.xy = xy; + } + /** * Returns the color temperature. * @@ -144,6 +165,10 @@ public int getColorTemperature() { return ct; } + public void setColorTemperature(int ct) { + this.ct = ct; + } + /** * Returns the last alert mode set. * Future firmware updates may change this to actually report the current alert mode. @@ -169,6 +194,10 @@ public ColorMode getColorMode() { return ColorMode.valueOf(colormode.toUpperCase()); } + public void setColormode(ColorMode colormode) { + this.colormode = colormode.name(); + } + /** * Returns the current active effect. * diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/StateUpdate.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/StateUpdate.java index c8be2d4d2a479..0d92d5e7f15f7 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/StateUpdate.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/StateUpdate.java @@ -202,21 +202,20 @@ public StateUpdate setTransitionTime(long timeMillis) { * @param flag on if true, off otherwise * @return this object for chaining calls */ - + public StateUpdate setFlag(boolean flag) { commands.add(new Command("flag", flag)); return this; } - + /** * Set status of sensor. * - * @param status status + * @param status status * @return this object for chaining calls */ public StateUpdate setStatus(int status) { commands.add(new Command("status", status)); return this; } - } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/BridgeJsonParameters.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/BridgeJsonParameters.java index f78ab8f1b92ac..d759bb6be9a35 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/BridgeJsonParameters.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/BridgeJsonParameters.java @@ -57,5 +57,4 @@ public String getMacAddress() { public String getName() { return name; } - } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeDiscoveryParticipant.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeDiscoveryParticipant.java index 8e1cbadaf365b..ecca96b82ac05 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeDiscoveryParticipant.java @@ -84,5 +84,4 @@ public Set getSupportedThingTypeUIDs() { } return null; } - } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscovery.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscovery.java index dbaaeb25f531d..146d87f962aaa 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscovery.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueBridgeNupnpDiscovery.java @@ -182,5 +182,4 @@ private List getBridgeList() { protected String doGetRequest(String url) throws IOException { return HttpUtil.executeUrl("GET", url, REQUEST_TIMEOUT); } - } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueLightDiscoveryService.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueLightDiscoveryService.java index b2edab9984c61..13b25751cfb58 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueLightDiscoveryService.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/discovery/HueLightDiscoveryService.java @@ -32,20 +32,23 @@ import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.hue.internal.FullGroup; import org.openhab.binding.hue.internal.FullHueObject; import org.openhab.binding.hue.internal.FullLight; import org.openhab.binding.hue.internal.FullSensor; import org.openhab.binding.hue.internal.HueBridge; +import org.openhab.binding.hue.internal.handler.GroupStatusListener; import org.openhab.binding.hue.internal.handler.HueBridgeHandler; +import org.openhab.binding.hue.internal.handler.HueGroupHandler; import org.openhab.binding.hue.internal.handler.HueLightHandler; import org.openhab.binding.hue.internal.handler.LightStatusListener; import org.openhab.binding.hue.internal.handler.SensorStatusListener; +import org.openhab.binding.hue.internal.handler.sensors.ClipHandler; import org.openhab.binding.hue.internal.handler.sensors.DimmerSwitchHandler; import org.openhab.binding.hue.internal.handler.sensors.LightLevelHandler; import org.openhab.binding.hue.internal.handler.sensors.PresenceHandler; import org.openhab.binding.hue.internal.handler.sensors.TapSwitchHandler; import org.openhab.binding.hue.internal.handler.sensors.TemperatureHandler; -import org.openhab.binding.hue.internal.handler.sensors.ClipHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,15 +64,16 @@ * @author Samuel Leisering - Added support for sensor API * @author Christoph Weitkamp - Added support for sensor API * @author Meng Yiqi - Added support for CLIP sensor + * @author Laurent Garnier - Added support for groups */ @NonNullByDefault public class HueLightDiscoveryService extends AbstractDiscoveryService - implements LightStatusListener, SensorStatusListener { + implements LightStatusListener, SensorStatusListener, GroupStatusListener { public static final Set SUPPORTED_THING_TYPES = Collections.unmodifiableSet(Stream .of(HueLightHandler.SUPPORTED_THING_TYPES.stream(), DimmerSwitchHandler.SUPPORTED_THING_TYPES.stream(), TapSwitchHandler.SUPPORTED_THING_TYPES.stream(), PresenceHandler.SUPPORTED_THING_TYPES.stream(), TemperatureHandler.SUPPORTED_THING_TYPES.stream(), LightLevelHandler.SUPPORTED_THING_TYPES.stream(), - ClipHandler.SUPPORTED_THING_TYPES.stream()) + ClipHandler.SUPPORTED_THING_TYPES.stream(), HueGroupHandler.SUPPORTED_THING_TYPES.stream()) .flatMap(i -> i).collect(Collectors.toSet())); private final Logger logger = LoggerFactory.getLogger(HueLightDiscoveryService.class); @@ -105,6 +109,7 @@ public HueLightDiscoveryService(HueBridgeHandler hueBridgeHandler) { public void activate() { hueBridgeHandler.registerLightStatusListener(this); hueBridgeHandler.registerSensorStatusListener(this); + hueBridgeHandler.registerGroupStatusListener(this); } @Override @@ -112,7 +117,7 @@ public void deactivate() { removeOlderResults(new Date().getTime(), hueBridgeHandler.getThing().getUID()); hueBridgeHandler.unregisterLightStatusListener(this); hueBridgeHandler.unregisterSensorStatusListener(this); - + hueBridgeHandler.unregisterGroupStatusListener(this); } @Override @@ -130,6 +135,10 @@ public void startScan() { for (FullSensor s : sensors) { onSensorAddedInternal(s); } + List groups = hueBridgeHandler.getFullGroups(); + for (FullGroup g : groups) { + onGroupAddedInternal(g); + } // search for unpaired lights hueBridgeHandler.startSearch(); } @@ -137,7 +146,7 @@ public void startScan() { @Override protected synchronized void stopScan() { super.stopScan(); - removeOlderResults(getTimestampOfLastScan()); + removeOlderResults(getTimestampOfLastScan(), hueBridgeHandler.getThing().getUID()); } @Override @@ -257,7 +266,7 @@ public void onSensorRemoved(@Nullable HueBridge bridge, FullSensor sensor) { onSensorRemovedInternal(sensor); } - public void onSensorRemovedInternal(FullSensor sensor) { + private void onSensorRemovedInternal(FullSensor sensor) { ThingUID thingUID = getThingUID(sensor); if (thingUID != null) { @@ -269,4 +278,51 @@ public void onSensorRemovedInternal(FullSensor sensor) { public void onSensorStateChanged(@Nullable HueBridge bridge, FullSensor sensor) { // nothing to do } + + @Override + public void onGroupAdded(@Nullable HueBridge bridge, FullGroup group) { + onGroupAddedInternal(group); + } + + private void onGroupAddedInternal(FullGroup group) { + // Ignore the Hue Entertainment Areas + if ("Entertainment".equalsIgnoreCase(group.getType())) { + return; + } + + ThingUID bridgeUID = hueBridgeHandler.getThing().getUID(); + ThingUID thingUID = new ThingUID(THING_TYPE_GROUP, bridgeUID, group.getId()); + + Map properties = new HashMap<>(); + properties.put(GROUP_ID, group.getId()); + + String name = String.format("%s (%s)", "0".equals(group.getId()) ? "All lights" : group.getName(), + group.getType()); + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withThingType(THING_TYPE_GROUP) + .withProperties(properties).withBridge(bridgeUID).withRepresentationProperty(GROUP_ID).withLabel(name) + .build(); + + thingDiscovered(discoveryResult); + } + + @Override + public void onGroupGone(@Nullable HueBridge bridge, FullGroup group) { + onGroupRemovedInternal(group); + } + + @Override + public void onGroupRemoved(@Nullable HueBridge bridge, FullGroup group) { + onGroupRemovedInternal(group); + } + + private void onGroupRemovedInternal(FullGroup group) { + ThingUID bridgeUID = hueBridgeHandler.getThing().getUID(); + ThingUID thingUID = new ThingUID(THING_TYPE_GROUP, bridgeUID, group.getId()); + thingRemoved(thingUID); + } + + @Override + public void onGroupStateChanged(@Nullable HueBridge bridge, FullGroup group) { + // nothing to do + } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/GroupStatusListener.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/GroupStatusListener.java new file mode 100644 index 0000000000000..cccc27840134e --- /dev/null +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/GroupStatusListener.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hue.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.hue.internal.FullGroup; +import org.openhab.binding.hue.internal.HueBridge; + +/** + * The {@link GroupStatusListener} is notified when a group status has changed or a group has been removed or added. + * + * @author Laurent Garnier - Initial contribution + */ +@NonNullByDefault +public interface GroupStatusListener { + + /** + * This method is called whenever the state of the given group has changed. The new state can be obtained by + * {@link FullGroup#getState()}. + * + * @param bridge The bridge the changed group is connected to. + * @param group The group which received the state update. + */ + void onGroupStateChanged(@Nullable HueBridge bridge, FullGroup group); + + /** + * This method is called whenever a group is removed. + * + * @param bridge The bridge the removed group was connected to. + * @param group The removed group + */ + void onGroupRemoved(@Nullable HueBridge bridge, FullGroup group); + + /** + * This method is called whenever a group is reported as gone. + * + * @param bridge The bridge the reported group was connected to. + * @param group The group which is reported as gone. + */ + void onGroupGone(@Nullable HueBridge bridge, FullGroup group); + + /** + * This method is called whenever a group is added. + * + * @param bridge The bridge the added group was connected to. + * @param group The added group + */ + void onGroupAdded(@Nullable HueBridge bridge, FullGroup group); +} diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java index fb91d47756176..156eb98a8996f 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueBridgeHandler.java @@ -34,6 +34,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.config.core.status.ConfigStatusMessage; +import org.eclipse.smarthome.core.library.types.HSBType; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -46,6 +47,7 @@ import org.openhab.binding.hue.internal.Config; import org.openhab.binding.hue.internal.ConfigUpdate; import org.openhab.binding.hue.internal.FullConfig; +import org.openhab.binding.hue.internal.FullGroup; import org.openhab.binding.hue.internal.FullLight; import org.openhab.binding.hue.internal.FullSensor; import org.openhab.binding.hue.internal.HueBridge; @@ -75,12 +77,31 @@ * @author Denis Dudnik - switched to internally integrated source of Jue library * @author Samuel Leisering - Added support for sensor API * @author Christoph Weitkamp - Added support for sensor API + * @author Laurent Garnier - Added support for groups */ @NonNullByDefault public class HueBridgeHandler extends ConfigStatusBridgeHandler implements HueClient { - private long lightPollingInterval = TimeUnit.SECONDS.toSeconds(10); - private long sensorPollingInterval = TimeUnit.MILLISECONDS.toMillis(500); + public static final Set SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE); + + private static final String DEVICE_TYPE = "EclipseSmartHome"; + + private static enum StatusType { + ADDED, + REMOVED, + GONE, + CHANGED + } + + private final Logger logger = LoggerFactory.getLogger(HueBridgeHandler.class); + + private final Map lastLightStates = new ConcurrentHashMap<>(); + private final Map lastSensorStates = new ConcurrentHashMap<>(); + private final Map lastGroupStates = new ConcurrentHashMap<>(); + + private final List lightStatusListeners = new CopyOnWriteArrayList<>(); + private final List sensorStatusListeners = new CopyOnWriteArrayList<>(); + private final List groupStatusListeners = new CopyOnWriteArrayList<>(); final ReentrantLock pollingLock = new ReentrantLock(); @@ -148,32 +169,6 @@ private boolean isReachable(String ipAddress) { } } - private static final String STATE_ADDED = "added"; - private static final String STATE_GONE = "gone"; - private static final String STATE_CHANGED = "changed"; - - public static final Set SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE); - - private static final String DEVICE_TYPE = "EclipseSmartHome"; - - private final Logger logger = LoggerFactory.getLogger(HueBridgeHandler.class); - - private final Map lastLightStates = new ConcurrentHashMap<>(); - private final Map lastSensorStates = new ConcurrentHashMap<>(); - - private boolean lastBridgeConnectionState = false; - - private boolean propertiesInitializedSuccessfully = false; - - private final List lightStatusListeners = new CopyOnWriteArrayList<>(); - private final List sensorStatusListeners = new CopyOnWriteArrayList<>(); - - private @Nullable ScheduledFuture lightPollingJob; - private @Nullable ScheduledFuture sensorPollingJob; - - private @NonNullByDefault({}) HueBridge hueBridge = null; - private @NonNullByDefault({}) HueBridgeConfig hueBridgeConfig = null; - private final Runnable sensorPollingRunnable = new PollingRunnable() { @Override protected void doConnectedRun() throws IOException, ApiException { @@ -187,13 +182,12 @@ protected void doConnectedRun() throws IOException, ApiException { lastSensorStates.put(sensorId, sensor); if (!lastFullSensorState.equals(sensor.getState())) { logger.debug("Status update for Hue sensor '{}' detected: {}", sensorId, sensor.getState()); - notifySensorStatusListeners(sensor, STATE_CHANGED); + notifySensorStatusListeners(sensor, StatusType.CHANGED); } } else { lastSensorStates.put(sensorId, sensor); logger.debug("Hue sensor '{}' added.", sensorId); - notifySensorStatusListeners(sensor, STATE_ADDED); - + notifySensorStatusListeners(sensor, StatusType.ADDED); } } @@ -201,13 +195,7 @@ protected void doConnectedRun() throws IOException, ApiException { for (Entry fullSensorEntry : lastSensorStateCopy.entrySet()) { lastSensorStates.remove(fullSensorEntry.getKey()); logger.debug("Hue sensor '{}' removed.", fullSensorEntry.getKey()); - for (SensorStatusListener sensorStatusListener : sensorStatusListeners) { - try { - sensorStatusListener.onSensorRemoved(hueBridge, fullSensorEntry.getValue()); - } catch (Exception e) { - logger.error("An exception occurred while calling the Sensor Listeners", e); - } - } + notifySensorStatusListeners(fullSensorEntry.getValue(), StatusType.REMOVED); } } }; @@ -226,18 +214,17 @@ protected void doConnectedRun() throws IOException, ApiException { for (final FullLight fullLight : lights) { final String lightId = fullLight.getId(); + lastLightStates.put(lightId, fullLight); if (lastLightStateCopy.containsKey(lightId)) { final FullLight lastFullLight = lastLightStateCopy.remove(lightId); final State lastFullLightState = lastFullLight.getState(); - lastLightStates.put(lightId, fullLight); if (!lastFullLightState.equals(fullLight.getState())) { logger.debug("Status update for Hue light '{}' detected.", lightId); - notifyLightStatusListeners(fullLight, STATE_CHANGED); + notifyLightStatusListeners(fullLight, StatusType.CHANGED); } } else { - lastLightStates.put(lightId, fullLight); logger.debug("Hue light '{}' added.", lightId); - notifyLightStatusListeners(fullLight, STATE_ADDED); + notifyLightStatusListeners(fullLight, StatusType.ADDED); } } @@ -245,17 +232,94 @@ protected void doConnectedRun() throws IOException, ApiException { for (Entry fullLightEntry : lastLightStateCopy.entrySet()) { lastLightStates.remove(fullLightEntry.getKey()); logger.debug("Hue light '{}' removed.", fullLightEntry.getKey()); - for (LightStatusListener lightStatusListener : lightStatusListeners) { - try { - lightStatusListener.onLightRemoved(hueBridge, fullLightEntry.getValue()); - } catch (Exception e) { - logger.error("An exception occurred while calling the BridgeHeartbeatListener", e); + notifyLightStatusListeners(fullLightEntry.getValue(), StatusType.REMOVED); + } + + Map lastGroupStateCopy = new HashMap<>(lastGroupStates); + + for (final FullGroup fullGroup : hueBridge.getGroups()) { + State groupState = fullGroup.getState(); + boolean on = false; + int sumBri = 0; + int nbBri = 0; + State colorRef = null; + HSBType firstColorHsb = null; + for (String lightId : fullGroup.getLights()) { + FullLight light = lastLightStates.get(lightId); + if (light != null) { + final State lightState = light.getState(); + logger.trace("Group {}: light {}: on {} bri {} hue {} sat {} temp {} mode {} XY {}", + fullGroup.getName(), light.getName(), lightState.isOn(), lightState.getBrightness(), + lightState.getHue(), lightState.getSaturation(), lightState.getColorTemperature(), + lightState.getColorMode(), lightState.getXY()); + if (lightState.isOn()) { + on = true; + sumBri += lightState.getBrightness(); + nbBri++; + if (lightState.getColorMode() != null) { + HSBType lightHsb = LightStateConverter.toHSBType(lightState); + if (firstColorHsb == null) { + // first color light + firstColorHsb = lightHsb; + colorRef = lightState; + } else if (!lightHsb.equals(firstColorHsb)) { + colorRef = null; + } + } + } + } + } + groupState.setOn(on); + groupState.setBri(nbBri == 0 ? 0 : sumBri / nbBri); + if (colorRef != null) { + groupState.setColormode(colorRef.getColorMode()); + groupState.setHue(colorRef.getHue()); + groupState.setSaturation(colorRef.getSaturation()); + groupState.setColorTemperature(colorRef.getColorTemperature()); + groupState.setXY(colorRef.getXY()); + } + logger.trace("Group {} ({}): on {} bri {} hue {} sat {} temp {} mode {} XY {}", fullGroup.getName(), + fullGroup.getType(), groupState.isOn(), groupState.getBrightness(), groupState.getHue(), + groupState.getSaturation(), groupState.getColorTemperature(), groupState.getColorMode(), + groupState.getXY()); + String groupId = fullGroup.getId(); + lastGroupStates.put(groupId, fullGroup); + if (lastGroupStateCopy.containsKey(groupId)) { + final FullGroup lastFullGroup = lastGroupStateCopy.remove(groupId); + final State lastFullGroupState = lastFullGroup.getState(); + if (!lastFullGroupState.equals(fullGroup.getState())) { + logger.debug("Status update for Hue group '{}' detected.", groupId); + notifyGroupStatusListeners(fullGroup, StatusType.CHANGED); } + } else { + logger.debug("Hue group '{}' ({}) added (nb lights {}).", groupId, fullGroup.getName(), + fullGroup.getLights().size()); + notifyGroupStatusListeners(fullGroup, StatusType.ADDED); } } + + // Check for removed groups + for (Entry fullGroupEntry : lastGroupStateCopy.entrySet()) { + lastGroupStates.remove(fullGroupEntry.getKey()); + logger.debug("Hue group '{}' removed.", fullGroupEntry.getKey()); + notifyGroupStatusListeners(fullGroupEntry.getValue(), StatusType.REMOVED); + } } }; + private long lightPollingInterval = TimeUnit.SECONDS.toSeconds(10); + private long sensorPollingInterval = TimeUnit.MILLISECONDS.toMillis(500); + + private boolean lastBridgeConnectionState = false; + + private boolean propertiesInitializedSuccessfully = false; + + private @Nullable ScheduledFuture lightPollingJob; + private @Nullable ScheduledFuture sensorPollingJob; + + private @NonNullByDefault({}) HueBridge hueBridge = null; + private @NonNullByDefault({}) HueBridgeConfig hueBridgeConfig = null; + public HueBridgeHandler(Bridge bridge) { super(bridge); } @@ -279,7 +343,7 @@ public void updateLightState(FullLight light, StateUpdate stateUpdate) { return null; }); } else { - logger.warn("No bridge connected or selected. Cannot set light state."); + logger.debug("No bridge connected or selected. Cannot set light state."); } } @@ -297,7 +361,7 @@ public void updateSensorState(FullSensor sensor, StateUpdate stateUpdate) { return null; }); } else { - logger.warn("No bridge connected or selected. Cannot set sensor state."); + logger.debug("No bridge connected or selected. Cannot set sensor state."); } } @@ -315,7 +379,25 @@ public void updateSensorConfig(FullSensor sensor, ConfigUpdate configUpdate) { return null; }); } else { - logger.warn("No bridge connected or selected. Cannot set sensor config."); + logger.debug("No bridge connected or selected. Cannot set sensor config."); + } + } + + @Override + public void updateGroupState(FullGroup group, StateUpdate stateUpdate) { + if (hueBridge != null) { + hueBridge.setGroupState(group, stateUpdate).thenAccept(result -> { + try { + hueBridge.handleErrors(result); + } catch (Exception e) { + handleStateUpdateException(group, stateUpdate, e); + } + }).exceptionally(e -> { + handleStateUpdateException(group, stateUpdate, e); + return null; + }); + } else { + logger.debug("No bridge connected or selected. Cannot set group state."); } } @@ -333,7 +415,7 @@ private void handleStateUpdateException(FullLight light, StateUpdate stateUpdate updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } else if (e instanceof EntityNotAvailableException) { logger.debug("Error while accessing light: {}", e.getMessage(), e); - notifyLightStatusListeners(light, STATE_GONE); + notifyLightStatusListeners(light, StatusType.GONE); } else if (e instanceof ApiException) { // This should not happen - if it does, it is most likely some bug that should be reported. logger.warn("Error while accessing light: {}", e.getMessage(), e); @@ -347,7 +429,7 @@ private void handleStateUpdateException(FullSensor sensor, StateUpdate stateUpda updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } else if (e instanceof EntityNotAvailableException) { logger.debug("Error while accessing sensor: {}", e.getMessage(), e); - notifySensorStatusListeners(sensor, STATE_GONE); + notifySensorStatusListeners(sensor, StatusType.GONE); } else if (e instanceof ApiException) { // This should not happen - if it does, it is most likely some bug that should be reported. logger.warn("Error while accessing sensor: {}", e.getMessage(), e); @@ -356,12 +438,26 @@ private void handleStateUpdateException(FullSensor sensor, StateUpdate stateUpda } } + private void handleStateUpdateException(FullGroup group, StateUpdate stateUpdate, Throwable e) { + if (e instanceof IOException) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } else if (e instanceof EntityNotAvailableException) { + logger.debug("Error while accessing group: {}", e.getMessage(), e); + notifyGroupStatusListeners(group, StatusType.GONE); + } else if (e instanceof ApiException) { + // This should not happen - if it does, it is most likely some bug that should be reported. + logger.warn("Error while accessing group: {}", e.getMessage(), e); + } else if (e instanceof IllegalStateException) { + logger.trace("Error while accessing group: {}", e.getMessage()); + } + } + private void handleConfigUpdateException(FullSensor sensor, ConfigUpdate configUpdate, Throwable e) { if (e instanceof IOException) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } else if (e instanceof EntityNotAvailableException) { logger.debug("Error while accessing sensor: {}", e.getMessage(), e); - notifySensorStatusListeners(sensor, STATE_GONE); + notifySensorStatusListeners(sensor, StatusType.GONE); } else if (e instanceof ApiException) { // This should not happen - if it does, it is most likely some bug that should be reported. logger.warn("Error while accessing sensor: {}", e.getMessage(), e); @@ -427,7 +523,7 @@ public void initialize() { String ip = hueBridgeConfig.getIpAddress(); if (ip == null || ip.isEmpty()) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-no-ip-address"); } else { if (hueBridge == null) { @@ -440,18 +536,8 @@ public void initialize() { private synchronized void onUpdate() { if (hueBridge != null) { - // start light polling only if a light handler has been registered, otherwise stop polling - if (lightStatusListeners.isEmpty()) { - stopLightPolling(); - } else { - startLightPolling(); - } - // start sensor polling only if a sensor handler has been registered, otherwise stop polling - if (sensorStatusListeners.isEmpty()) { - stopSensorPolling(); - } else { - startSensorPolling(); - } + startLightPolling(); + startSensorPolling(); } } @@ -575,19 +661,19 @@ private void updateBridgeThingConfiguration(String userName) { private void handleAuthenticationFailure(Exception ex, String userName) { logger.warn("User {} is not authenticated on Hue bridge {}", userName, hueBridgeConfig.getIpAddress()); logger.warn("Please configure a valid user or remove user from configuration to generate a new one."); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-invalid-username"); } private void handleLinkButtonNotPressed(LinkButtonException ex) { logger.debug("Failed creating new user on Hue bridge: {}", ex.getMessage()); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-press-pairing-button"); } private void handleExceptionWhileCreatingUser(Exception ex) { logger.warn("Failed creating new user on Hue bridge", ex); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-creation-username"); } @@ -595,8 +681,6 @@ private void handleExceptionWhileCreatingUser(Exception ex) { public boolean registerLightStatusListener(LightStatusListener lightStatusListener) { boolean result = lightStatusListeners.add(lightStatusListener); if (result && hueBridge != null) { - // start light polling only if a light handler has been registered - startLightPolling(); // inform the listener initially about all lights and their states for (FullLight light : lastLightStates.values()) { lightStatusListener.onLightAdded(hueBridge, light); @@ -607,22 +691,13 @@ public boolean registerLightStatusListener(LightStatusListener lightStatusListen @Override public boolean unregisterLightStatusListener(LightStatusListener lightStatusListener) { - boolean result = lightStatusListeners.remove(lightStatusListener); - if (result) { - // stop stop light polling - if (lightStatusListeners.isEmpty()) { - stopLightPolling(); - } - } - return result; + return lightStatusListeners.remove(lightStatusListener); } @Override public boolean registerSensorStatusListener(SensorStatusListener sensorStatusListener) { boolean result = sensorStatusListeners.add(sensorStatusListener); if (result && hueBridge != null) { - // start sensor polling only if a sensor handler has been registered - startSensorPolling(); // inform the listener initially about all sensors and their states for (FullSensor sensor : lastSensorStates.values()) { sensorStatusListener.onSensorAdded(hueBridge, sensor); @@ -633,16 +708,26 @@ public boolean registerSensorStatusListener(SensorStatusListener sensorStatusLis @Override public boolean unregisterSensorStatusListener(SensorStatusListener sensorStatusListener) { - boolean result = sensorStatusListeners.remove(sensorStatusListener); - if (result) { - // stop sensor polling - if (sensorStatusListeners.isEmpty()) { - stopSensorPolling(); + return sensorStatusListeners.remove(sensorStatusListener); + } + + @Override + public boolean registerGroupStatusListener(GroupStatusListener groupStatusListener) { + boolean result = groupStatusListeners.add(groupStatusListener); + if (result && hueBridge != null) { + // inform the listener initially about all groups and their states + for (FullGroup group : lastGroupStates.values()) { + groupStatusListener.onGroupAdded(hueBridge, group); } } return result; } + @Override + public boolean unregisterGroupStatusListener(GroupStatusListener groupStatusListener) { + return groupStatusListeners.remove(groupStatusListener); + } + @Override public @Nullable FullLight getLightById(String lightId) { return lastLightStates.get(lightId); @@ -653,6 +738,11 @@ public boolean unregisterSensorStatusListener(SensorStatusListener sensorStatusL return lastSensorStates.get(sensorId); } + @Override + public @Nullable FullGroup getGroupById(String groupId) { + return lastGroupStates.get(groupId); + } + public List getFullLights() { List ret = withReAuthentication("search for new lights", () -> { return hueBridge.getFullLights(); @@ -667,6 +757,13 @@ public List getFullSensors() { return ret != null ? ret : Collections.emptyList(); } + public List getFullGroups() { + List ret = withReAuthentication("search for new groups", () -> { + return hueBridge.getGroups(); + }); + return ret != null ? ret : Collections.emptyList(); + } + public void startSearch() { withReAuthentication("start search mode", () -> { hueBridge.startSearch(); @@ -693,19 +790,19 @@ private T withReAuthentication(String taskDescription, Callable runnable) } } } catch (Exception e) { - logger.error("Bridge cannot {}.", taskDescription, e); + logger.debug("Bridge cannot {}.", taskDescription, e); } } return null; } /** - * Iterate through lightStatusListeners and notify them about a changed or added light state. + * Iterate through lightStatusListeners and notify them about a status change. * * @param fullLight - * @param type Can be "changed" if just a state has changed or "added" if this is a new light on the bridge. + * @param type the type of change */ - private void notifyLightStatusListeners(final FullLight fullLight, final String type) { + private void notifyLightStatusListeners(final FullLight fullLight, StatusType type) { if (lightStatusListeners.isEmpty()) { logger.debug("No light status listeners to notify of light change for light '{}'", fullLight.getId()); return; @@ -714,28 +811,28 @@ private void notifyLightStatusListeners(final FullLight fullLight, final String for (LightStatusListener lightStatusListener : lightStatusListeners) { try { switch (type) { - case STATE_ADDED: + case ADDED: logger.debug("Sending lightAdded for light '{}'", fullLight.getId()); lightStatusListener.onLightAdded(hueBridge, fullLight); break; - case STATE_GONE: + case REMOVED: + lightStatusListener.onLightRemoved(hueBridge, fullLight); + break; + case GONE: lightStatusListener.onLightGone(hueBridge, fullLight); break; - case STATE_CHANGED: + case CHANGED: logger.debug("Sending lightStateChanged for light '{}'", fullLight.getId()); lightStatusListener.onLightStateChanged(hueBridge, fullLight); break; - default: - throw new IllegalArgumentException( - "Could not notify lightStatusListeners for unknown event type " + type); } } catch (Exception e) { - logger.error("An exception occurred while calling the BridgeHeartbeatListener", e); + logger.debug("An exception occurred while calling the BridgeHeartbeatListener", e); } } } - private void notifySensorStatusListeners(final FullSensor fullSensor, final String type) { + private void notifySensorStatusListeners(final FullSensor fullSensor, StatusType type) { if (sensorStatusListeners.isEmpty()) { logger.debug("No sensor status listeners to notify of sensor change for sensor '{}'", fullSensor.getId()); return; @@ -744,23 +841,53 @@ private void notifySensorStatusListeners(final FullSensor fullSensor, final Stri for (SensorStatusListener sensorStatusListener : sensorStatusListeners) { try { switch (type) { - case STATE_ADDED: + case ADDED: logger.debug("Sending sensorAdded for sensor '{}'", fullSensor.getId()); sensorStatusListener.onSensorAdded(hueBridge, fullSensor); break; - case STATE_GONE: + case REMOVED: + sensorStatusListener.onSensorRemoved(hueBridge, fullSensor); + break; + case GONE: sensorStatusListener.onSensorGone(hueBridge, fullSensor); break; - case STATE_CHANGED: + case CHANGED: logger.debug("Sending sensorStateChanged for sensor '{}'", fullSensor.getId()); sensorStatusListener.onSensorStateChanged(hueBridge, fullSensor); break; - default: - throw new IllegalArgumentException( - "Could not notify sensorStatusListeners for unknown event type " + type); } } catch (Exception e) { - logger.error("An exception occurred while calling the Sensor Listeners", e); + logger.debug("An exception occurred while calling the Sensor Listeners", e); + } + } + } + + private void notifyGroupStatusListeners(final FullGroup fullGroup, StatusType type) { + if (groupStatusListeners.isEmpty()) { + logger.debug("No group status listeners to notify of group change for group '{}'", fullGroup.getId()); + return; + } + + for (GroupStatusListener groupStatusListener : groupStatusListeners) { + try { + switch (type) { + case ADDED: + logger.debug("Sending groupAdded for group '{}'", fullGroup.getId()); + groupStatusListener.onGroupAdded(hueBridge, fullGroup); + break; + case REMOVED: + groupStatusListener.onGroupRemoved(hueBridge, fullGroup); + break; + case GONE: + groupStatusListener.onGroupGone(hueBridge, fullGroup); + break; + case CHANGED: + logger.debug("Sending groupStateChanged for group '{}'", fullGroup.getId()); + groupStatusListener.onGroupStateChanged(hueBridge, fullGroup); + break; + } + } catch (Exception e) { + logger.debug("An exception occurred while calling the Group Listeners", e); } } } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueClient.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueClient.java index 6e2af114e41cb..1bd3c83d2142a 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueClient.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueClient.java @@ -15,6 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.hue.internal.ConfigUpdate; +import org.openhab.binding.hue.internal.FullGroup; import org.openhab.binding.hue.internal.FullLight; import org.openhab.binding.hue.internal.FullSensor; import org.openhab.binding.hue.internal.StateUpdate; @@ -25,6 +26,7 @@ * @author Simon Kaufmann - initial contribution and API * @author Samuel Leisering - Added support for sensor API * @author Christoph Weitkamp - Added support for sensor API + * @author Laurent Garnier - Added support for groups */ @NonNullByDefault public interface HueClient { @@ -61,6 +63,22 @@ public interface HueClient { */ boolean unregisterSensorStatusListener(SensorStatusListener sensorStatusListener); + /** + * Register a group status listener. + * + * @param groupStatusListener the group status listener + * @return {@code true} if the collection of listeners has changed as a result of this call + */ + boolean registerGroupStatusListener(GroupStatusListener groupStatusListener); + + /** + * Unregister a group status listener. + * + * @param groupStatusListener the group status listener + * @return {@code true} if the collection of listeners has changed as a result of this call + */ + boolean unregisterGroupStatusListener(GroupStatusListener groupStatusListener); + /** * Get the light by its ID. * @@ -79,6 +97,15 @@ public interface HueClient { @Nullable FullSensor getSensorById(String sensorId); + /** + * Get the group by its ID. + * + * @param groupId the group ID + * @return the full group representation of {@code null} if it could not be found + */ + @Nullable + FullGroup getGroupById(String groupId); + /** * Updates the given light. * @@ -102,4 +129,12 @@ public interface HueClient { * @param stateUpdate the state update */ void updateSensorState(FullSensor sensor, StateUpdate stateUpdate); + + /** + * Updates the given group. + * + * @param group the group to be updated + * @param stateUpdate the state update + */ + void updateGroupState(FullGroup group, StateUpdate stateUpdate); } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java new file mode 100644 index 0000000000000..a51e874e27908 --- /dev/null +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueGroupHandler.java @@ -0,0 +1,380 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.hue.internal.handler; + +import static org.openhab.binding.hue.internal.HueBindingConstants.*; + +import java.math.BigDecimal; +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.HSBType; +import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.hue.internal.FullGroup; +import org.openhab.binding.hue.internal.HueBridge; +import org.openhab.binding.hue.internal.State; +import org.openhab.binding.hue.internal.State.ColorMode; +import org.openhab.binding.hue.internal.StateUpdate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * {@link HueGroupHandler} is the handler for a hue group of lights. It uses the {@link HueClient} to execute the + * actual command. + * + * @author Laurent Garnier - Initial contribution + */ +@NonNullByDefault +public class HueGroupHandler extends BaseThingHandler implements GroupStatusListener { + public static final Set SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_GROUP); + + private final Logger logger = LoggerFactory.getLogger(HueGroupHandler.class); + + private @NonNullByDefault({}) String groupId; + + private @Nullable Integer lastSentColorTemp; + private @Nullable Integer lastSentBrightness; + + private long defaultFadeTime = 400; + + private @Nullable HueClient hueClient; + + public HueGroupHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + logger.debug("Initializing hue group handler."); + Bridge bridge = getBridge(); + initializeThing((bridge == null) ? null : bridge.getStatus()); + } + + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + logger.debug("bridgeStatusChanged {}", bridgeStatusInfo); + initializeThing(bridgeStatusInfo.getStatus()); + } + + private void initializeThing(@Nullable ThingStatus bridgeStatus) { + logger.debug("initializeThing thing {} bridge status {}", getThing().getUID(), bridgeStatus); + final String configGroupId = (String) getConfig().get(GROUP_ID); + if (configGroupId != null) { + BigDecimal time = (BigDecimal) getConfig().get(FADETIME); + if (time != null) { + defaultFadeTime = time.longValueExact(); + } + + groupId = configGroupId; + // note: this call implicitly registers our handler as a listener on the bridge + if (getHueClient() != null) { + if (bridgeStatus == ThingStatus.ONLINE) { + updateStatus(ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error-no-group-id"); + } + } + + @Override + public void dispose() { + logger.debug("Hue group handler disposes. Unregistering listener."); + if (groupId != null) { + HueClient bridgeHandler = getHueClient(); + if (bridgeHandler != null) { + bridgeHandler.unregisterGroupStatusListener(this); + hueClient = null; + } + groupId = null; + } + } + + protected synchronized @Nullable HueClient getHueClient() { + if (hueClient == null) { + Bridge bridge = getBridge(); + if (bridge == null) { + return null; + } + ThingHandler handler = bridge.getHandler(); + if (handler instanceof HueBridgeHandler) { + hueClient = (HueClient) handler; + hueClient.registerGroupStatusListener(this); + } else { + return null; + } + } + return hueClient; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + handleCommand(channelUID.getId(), command, defaultFadeTime); + } + + public void handleCommand(String channel, Command command, long fadeTime) { + HueClient bridgeHandler = getHueClient(); + if (bridgeHandler == null) { + logger.debug("hue bridge handler not found. Cannot handle command without bridge."); + return; + } + + FullGroup group = bridgeHandler.getGroupById(groupId); + if (group == null) { + logger.debug("hue group not known on bridge. Cannot handle command."); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error-wrong-group-id"); + return; + } + + StateUpdate groupState = null; + switch (channel) { + case CHANNEL_COLOR: + if (command instanceof HSBType) { + HSBType hsbCommand = (HSBType) command; + if (hsbCommand.getBrightness().intValue() == 0) { + groupState = LightStateConverter.toOnOffLightState(OnOffType.OFF); + } else { + groupState = LightStateConverter.toColorLightState(hsbCommand, group.getState()); + if (groupState != null) { + groupState.setTransitionTime(fadeTime); + } + } + } else if (command instanceof PercentType) { + groupState = LightStateConverter.toBrightnessLightState((PercentType) command); + if (groupState != null) { + groupState.setTransitionTime(fadeTime); + } + } else if (command instanceof OnOffType) { + groupState = LightStateConverter.toOnOffLightState((OnOffType) command); + } else if (command instanceof IncreaseDecreaseType) { + groupState = convertBrightnessChangeToStateUpdate((IncreaseDecreaseType) command, group); + if (groupState != null) { + groupState.setTransitionTime(fadeTime); + } + } + break; + case CHANNEL_COLORTEMPERATURE: + if (command instanceof PercentType) { + groupState = LightStateConverter.toColorTemperatureLightState((PercentType) command); + if (groupState != null) { + groupState.setTransitionTime(fadeTime); + } + } else if (command instanceof OnOffType) { + groupState = LightStateConverter.toOnOffLightState((OnOffType) command); + } else if (command instanceof IncreaseDecreaseType) { + groupState = convertColorTempChangeToStateUpdate((IncreaseDecreaseType) command, group); + if (groupState != null) { + groupState.setTransitionTime(fadeTime); + } + } + break; + case CHANNEL_BRIGHTNESS: + if (command instanceof PercentType) { + groupState = LightStateConverter.toBrightnessLightState((PercentType) command); + if (groupState != null) { + groupState.setTransitionTime(fadeTime); + } + } else if (command instanceof OnOffType) { + groupState = LightStateConverter.toOnOffLightState((OnOffType) command); + } else if (command instanceof IncreaseDecreaseType) { + groupState = convertBrightnessChangeToStateUpdate((IncreaseDecreaseType) command, group); + if (groupState != null) { + groupState.setTransitionTime(fadeTime); + } + } + if (groupState != null && lastSentColorTemp != null) { + // make sure that the light also has the latest color temp + // this might not have been yet set in the light, if it was off + groupState.setColorTemperature(lastSentColorTemp); + groupState.setTransitionTime(fadeTime); + } + break; + case CHANNEL_SWITCH: + if (command instanceof OnOffType) { + groupState = LightStateConverter.toOnOffLightState((OnOffType) command); + } + if (groupState != null && lastSentColorTemp != null) { + // make sure that the light also has the latest color temp + // this might not have been yet set in the light, if it was off + groupState.setColorTemperature(lastSentColorTemp); + groupState.setTransitionTime(fadeTime); + } + break; + default: + break; + } + if (groupState != null) { + // Cache values which we have sent + Integer tmpBrightness = groupState.getBrightness(); + if (tmpBrightness != null) { + lastSentBrightness = tmpBrightness; + } + Integer tmpColorTemp = groupState.getColorTemperature(); + if (tmpColorTemp != null) { + lastSentColorTemp = tmpColorTemp; + } + bridgeHandler.updateGroupState(group, groupState); + } else { + logger.debug("Command sent to an unknown channel id: {}:{}", getThing().getUID(), channel); + } + } + + private @Nullable StateUpdate convertColorTempChangeToStateUpdate(IncreaseDecreaseType command, FullGroup group) { + StateUpdate stateUpdate = null; + Integer currentColorTemp = getCurrentColorTemp(group.getState()); + if (currentColorTemp != null) { + int newColorTemp = LightStateConverter.toAdjustedColorTemp(command, currentColorTemp); + stateUpdate = new StateUpdate().setColorTemperature(newColorTemp); + } + return stateUpdate; + } + + private @Nullable Integer getCurrentColorTemp(@Nullable State groupState) { + Integer colorTemp = lastSentColorTemp; + if (colorTemp == null && groupState != null) { + colorTemp = groupState.getColorTemperature(); + } + return colorTemp; + } + + private @Nullable StateUpdate convertBrightnessChangeToStateUpdate(IncreaseDecreaseType command, FullGroup group) { + StateUpdate stateUpdate = null; + Integer currentBrightness = getCurrentBrightness(group.getState()); + if (currentBrightness != null) { + int newBrightness = LightStateConverter.toAdjustedBrightness(command, currentBrightness); + stateUpdate = createBrightnessStateUpdate(currentBrightness, newBrightness); + } + return stateUpdate; + } + + private @Nullable Integer getCurrentBrightness(@Nullable State groupState) { + Integer brightness = lastSentBrightness; + if (brightness == null && groupState != null) { + if (!groupState.isOn()) { + brightness = 0; + } else { + brightness = groupState.getBrightness(); + } + } + return brightness; + } + + private StateUpdate createBrightnessStateUpdate(int currentBrightness, int newBrightness) { + StateUpdate lightUpdate = new StateUpdate(); + if (newBrightness == 0) { + lightUpdate.turnOff(); + } else { + lightUpdate.setBrightness(newBrightness); + if (currentBrightness == 0) { + lightUpdate.turnOn(); + } + } + return lightUpdate; + } + + @Override + public void channelLinked(ChannelUID channelUID) { + HueClient handler = getHueClient(); + if (handler != null) { + FullGroup group = handler.getGroupById(groupId); + if (group != null) { + onGroupStateChanged(null, group); + } + } + } + + @Override + public void onGroupStateChanged(@Nullable HueBridge bridge, FullGroup group) { + logger.trace("onGroupStateChanged() was called for group {}", group.getId()); + + if (!group.getId().equals(groupId)) { + logger.trace("Received state change for another handler's group ({}). Will be ignored.", group.getId()); + return; + } + + lastSentColorTemp = null; + lastSentBrightness = null; + + updateStatus(ThingStatus.ONLINE); + + State state = group.getState(); + + logger.debug("onGroupStateChanged Group {}: on {} bri {} hue {} sat {} temp {} mode {} XY {}", group.getName(), + state.isOn(), state.getBrightness(), state.getHue(), state.getSaturation(), state.getColorTemperature(), + state.getColorMode(), state.getXY()); + + HSBType hsbType = LightStateConverter.toHSBType(state); + if (!state.isOn()) { + hsbType = new HSBType(hsbType.getHue(), hsbType.getSaturation(), new PercentType(0)); + } + updateState(CHANNEL_COLOR, hsbType); + + ColorMode colorMode = state.getColorMode(); + if (ColorMode.CT.equals(colorMode)) { + PercentType colorTempPercentType = LightStateConverter.toColorTemperaturePercentType(state); + updateState(CHANNEL_COLORTEMPERATURE, colorTempPercentType); + } else { + updateState(CHANNEL_COLORTEMPERATURE, UnDefType.NULL); + } + + PercentType brightnessPercentType = LightStateConverter.toBrightnessPercentType(state); + if (!state.isOn()) { + brightnessPercentType = new PercentType(0); + } + updateState(CHANNEL_BRIGHTNESS, brightnessPercentType); + + updateState(CHANNEL_SWITCH, state.isOn() ? OnOffType.ON : OnOffType.OFF); + } + + @Override + public void onGroupAdded(@Nullable HueBridge bridge, FullGroup group) { + if (group.getId().equals(groupId)) { + onGroupStateChanged(bridge, group); + } + } + + @Override + public void onGroupRemoved(@Nullable HueBridge bridge, FullGroup group) { + if (group.getId().equals(groupId)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "@text/offline.group-removed"); + } + } + + @Override + public void onGroupGone(@Nullable HueBridge bridge, FullGroup group) { + if (group.getId().equals(groupId)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.GONE, "@text/offline.group-removed"); + } + } +} diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java index 0db4ca9f844c5..4713caff03d76 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueLightHandler.java @@ -40,13 +40,13 @@ import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.UnDefType; -import org.openhab.binding.hue.internal.FullHueObject; import org.openhab.binding.hue.internal.FullLight; import org.openhab.binding.hue.internal.HueBridge; import org.openhab.binding.hue.internal.State; @@ -94,14 +94,13 @@ public class HueLightHandler extends BaseThingHandler implements LightStatusList private static final String OSRAM_PAR16_50_TW_MODEL_ID = "PAR16_50_TW"; - @NonNullByDefault({}) - private String lightId; + private final Logger logger = LoggerFactory.getLogger(HueLightHandler.class); + + private @NonNullByDefault({}) String lightId; private @Nullable Integer lastSentColorTemp; private @Nullable Integer lastSentBrightness; - private final Logger logger = LoggerFactory.getLogger(HueLightHandler.class); - // Flag to indicate whether the bulb is of type Osram par16 50 TW or not private boolean isOsramPar16 = false; @@ -124,6 +123,12 @@ public void initialize() { initializeThing((bridge == null) ? null : bridge.getStatus()); } + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + logger.debug("bridgeStatusChanged {}", bridgeStatusInfo); + initializeThing(bridgeStatusInfo.getStatus()); + } + private void initializeThing(@Nullable ThingStatus bridgeStatus) { logger.debug("initializeThing thing {} bridge status {}", getThing().getUID(), bridgeStatus); final String configLightId = (String) getConfig().get(LIGHT_ID); @@ -134,17 +139,17 @@ private void initializeThing(@Nullable ThingStatus bridgeStatus) { } lightId = configLightId; - // note: this call implicitly registers our handler as a listener on - // the bridge - if (getHueClient() != null) { + // note: this call implicitly registers our handler as a listener on the bridge + HueClient bridgeHandler = getHueClient(); + if (bridgeHandler != null) { if (bridgeStatus == ThingStatus.ONLINE) { - initializeProperties(); + initializeProperties(bridgeHandler.getLightById(lightId)); updateStatus(ThingStatus.ONLINE); } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); } } else { - updateStatus(ThingStatus.OFFLINE); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); } } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, @@ -152,34 +157,31 @@ private void initializeThing(@Nullable ThingStatus bridgeStatus) { } } - private synchronized void initializeProperties() { - if (!propertiesInitializedSuccessfully) { - FullHueObject fullLight = getLight(); - if (fullLight != null) { - Map properties = editProperties(); - String softwareVersion = fullLight.getSoftwareVersion(); - if (softwareVersion != null) { - properties.put(PROPERTY_FIRMWARE_VERSION, softwareVersion); - } - String modelId = fullLight.getNormalizedModelID(); - if (modelId != null) { - properties.put(PROPERTY_MODEL_ID, modelId); - String vendor = getVendor(modelId); - if (vendor != null) { - properties.put(PROPERTY_VENDOR, vendor); - } - } else { - properties.put(PROPERTY_VENDOR, fullLight.getManufacturerName()); - } - properties.put(PRODUCT_NAME, fullLight.getProductName()); - String uniqueID = fullLight.getUniqueID(); - if (uniqueID != null) { - properties.put(UNIQUE_ID, uniqueID); + private synchronized void initializeProperties(@Nullable FullLight fullLight) { + if (!propertiesInitializedSuccessfully && fullLight != null) { + Map properties = editProperties(); + String softwareVersion = fullLight.getSoftwareVersion(); + if (softwareVersion != null) { + properties.put(PROPERTY_FIRMWARE_VERSION, softwareVersion); + } + String modelId = fullLight.getNormalizedModelID(); + if (modelId != null) { + properties.put(PROPERTY_MODEL_ID, modelId); + String vendor = getVendor(modelId); + if (vendor != null) { + properties.put(PROPERTY_VENDOR, vendor); } - updateProperties(properties); - isOsramPar16 = OSRAM_PAR16_50_TW_MODEL_ID.equals(modelId); - propertiesInitializedSuccessfully = true; + } else { + properties.put(PROPERTY_VENDOR, fullLight.getManufacturerName()); + } + properties.put(PRODUCT_NAME, fullLight.getProductName()); + String uniqueID = fullLight.getUniqueID(); + if (uniqueID != null) { + properties.put(UNIQUE_ID, uniqueID); } + updateProperties(properties); + isOsramPar16 = OSRAM_PAR16_50_TW_MODEL_ID.equals(modelId); + propertiesInitializedSuccessfully = true; } } @@ -205,27 +207,19 @@ public void dispose() { } } - private @Nullable FullLight getLight() { - HueClient bridgeHandler = getHueClient(); - if (bridgeHandler != null) { - return bridgeHandler.getLightById(lightId); - } - return null; - } - @Override public void handleCommand(ChannelUID channelUID, Command command) { handleCommand(channelUID.getId(), command, defaultFadeTime); } public void handleCommand(String channel, Command command, long fadeTime) { - HueClient hueBridge = getHueClient(); - if (hueBridge == null) { + HueClient bridgeHandler = getHueClient(); + if (bridgeHandler == null) { logger.warn("hue bridge handler not found. Cannot handle command without bridge."); return; } - FullLight light = getLight(); + FullLight light = bridgeHandler.getLightById(lightId); if (light == null) { logger.debug("hue light not known on bridge. Cannot handle command."); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, @@ -349,7 +343,7 @@ public void handleCommand(String channel, Command command, long fadeTime) { if (tmpColorTemp != null) { lastSentColorTemp = tmpColorTemp; } - hueBridge.updateLightState(light, lightState); + bridgeHandler.updateLightState(light, lightState); } else { logger.warn("Command sent to an unknown channel id: {}:{}", getThing().getUID(), channel); } @@ -448,7 +442,7 @@ public void onLightStateChanged(@Nullable HueBridge bridge, FullLight fullLight) return; } - initializeProperties(); + initializeProperties(fullLight); lastSentColorTemp = null; lastSentBrightness = null; diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueSensorHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueSensorHandler.java index 520db00152ecc..8cef167dc7771 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueSensorHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/HueSensorHandler.java @@ -35,10 +35,10 @@ import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; -import org.openhab.binding.hue.internal.FullHueObject; import org.openhab.binding.hue.internal.FullSensor; import org.openhab.binding.hue.internal.HueBridge; import org.openhab.binding.hue.internal.SensorConfigUpdate; @@ -55,10 +55,10 @@ @NonNullByDefault public abstract class HueSensorHandler extends BaseThingHandler implements SensorStatusListener { - private @NonNullByDefault({}) String sensorId; - private final Logger logger = LoggerFactory.getLogger(HueSensorHandler.class); + private @NonNullByDefault({}) String sensorId; + private boolean configInitializedSuccessfully; private boolean propertiesInitializedSuccessfully; @@ -75,21 +75,28 @@ public void initialize() { initializeThing((bridge == null) ? null : bridge.getStatus()); } + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + logger.debug("bridgeStatusChanged {}", bridgeStatusInfo); + initializeThing(bridgeStatusInfo.getStatus()); + } + private void initializeThing(@Nullable ThingStatus bridgeStatus) { logger.debug("initializeThing thing {} bridge status {}", getThing().getUID(), bridgeStatus); final String configSensorId = (String) getConfig().get(SENSOR_ID); if (configSensorId != null) { sensorId = configSensorId; // note: this call implicitly registers our handler as a listener on the bridge - if (getHueClient() != null) { + HueClient bridgeHandler = getHueClient(); + if (bridgeHandler != null) { if (bridgeStatus == ThingStatus.ONLINE) { - initializeProperties(); + initializeProperties(bridgeHandler.getSensorById(sensorId)); updateStatus(ThingStatus.ONLINE); } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); } } else { - updateStatus(ThingStatus.OFFLINE); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); } } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, @@ -97,28 +104,25 @@ private void initializeThing(@Nullable ThingStatus bridgeStatus) { } } - private synchronized void initializeProperties() { - if (!propertiesInitializedSuccessfully) { - FullHueObject fullSensor = getSensor(); - if (fullSensor != null) { - Map properties = editProperties(); - String softwareVersion = fullSensor.getSoftwareVersion(); - if (softwareVersion != null) { - properties.put(PROPERTY_FIRMWARE_VERSION, softwareVersion); - } - String modelId = fullSensor.getNormalizedModelID(); - if (modelId != null) { - properties.put(PROPERTY_MODEL_ID, modelId); - } - properties.put(PROPERTY_VENDOR, fullSensor.getManufacturerName()); - properties.put(PRODUCT_NAME, fullSensor.getProductName()); - String uniqueID = fullSensor.getUniqueID(); - if (uniqueID != null) { - properties.put(UNIQUE_ID, uniqueID); - } - updateProperties(properties); - propertiesInitializedSuccessfully = true; + private synchronized void initializeProperties(@Nullable FullSensor fullSensor) { + if (!propertiesInitializedSuccessfully && fullSensor != null) { + Map properties = editProperties(); + String softwareVersion = fullSensor.getSoftwareVersion(); + if (softwareVersion != null) { + properties.put(PROPERTY_FIRMWARE_VERSION, softwareVersion); } + String modelId = fullSensor.getNormalizedModelID(); + if (modelId != null) { + properties.put(PROPERTY_MODEL_ID, modelId); + } + properties.put(PROPERTY_VENDOR, fullSensor.getManufacturerName()); + properties.put(PRODUCT_NAME, fullSensor.getProductName()); + String uniqueID = fullSensor.getUniqueID(); + if (uniqueID != null) { + properties.put(UNIQUE_ID, uniqueID); + } + updateProperties(properties); + propertiesInitializedSuccessfully = true; } } @@ -166,8 +170,13 @@ public void handleCommand(ChannelUID channelUID, Command command) { } public void handleCommand(String channel, Command command) { - // updateSensorState - FullSensor sensor = getSensor(); + HueClient bridgeHandler = getHueClient(); + if (bridgeHandler == null) { + logger.warn("hue bridge handler not found. Cannot handle command without bridge."); + return; + } + + FullSensor sensor = bridgeHandler.getSensorById(sensorId); if (sensor == null) { logger.debug("hue sensor not known on bridge. Cannot handle command."); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, @@ -175,12 +184,6 @@ public void handleCommand(String channel, Command command) { return; } - HueClient hueBridge = getHueClient(); - if (hueBridge == null) { - logger.warn("hue bridge handler not found. Cannot handle command without bridge."); - return; - } - StateUpdate sensorState = new StateUpdate(); switch (channel) { case STATE_STATUS: @@ -192,7 +195,7 @@ public void handleCommand(String channel, Command command) { } if (sensorState != null) { - hueBridge.updateSensorState(sensor, sensorState); + bridgeHandler.updateSensorState(sensor, sensorState); } else { logger.warn("Command sent to an unknown channel id: {}:{}", getThing().getUID(), channel); } @@ -235,7 +238,7 @@ public void onSensorStateChanged(@Nullable HueBridge bridge, FullSensor sensor) return; } - initializeProperties(); + initializeProperties(sensor); if (Boolean.TRUE.equals(sensor.getConfig().get(CONFIG_REACHABLE))) { updateStatus(ThingStatus.ONLINE); diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java index 3422660fa4759..5760a3346d11e 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/LightStateConverter.java @@ -21,10 +21,10 @@ import org.eclipse.smarthome.core.library.types.PercentType; import org.eclipse.smarthome.core.library.types.StringType; import org.openhab.binding.hue.internal.State; -import org.openhab.binding.hue.internal.StateUpdate; import org.openhab.binding.hue.internal.State.AlertMode; import org.openhab.binding.hue.internal.State.ColorMode; import org.openhab.binding.hue.internal.State.Effect; +import org.openhab.binding.hue.internal.StateUpdate; /** * The {@link LightStateConverter} is responsible for mapping Eclipse SmartHome @@ -310,5 +310,4 @@ private static int restrictToBounds(int percentValue) { } return percentValue; } - } diff --git a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/ClipHandler.java b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/ClipHandler.java index 3d383509e8acb..c0a81ec05388c 100644 --- a/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/ClipHandler.java +++ b/bundles/org.openhab.binding.hue/src/main/java/org/openhab/binding/hue/internal/handler/sensors/ClipHandler.java @@ -36,15 +36,16 @@ */ @NonNullByDefault public class ClipHandler extends HueSensorHandler { - public static final Set SUPPORTED_THING_TYPES = Stream.of(THING_TYPE_CLIP_GENERIC_STATUS, THING_TYPE_CLIP_GENERIC_FLAG).collect(Collectors.toSet()); - + public static final Set SUPPORTED_THING_TYPES = Stream + .of(THING_TYPE_CLIP_GENERIC_STATUS, THING_TYPE_CLIP_GENERIC_FLAG).collect(Collectors.toSet()); + public ClipHandler(Thing thing) { super(thing); } @Override protected SensorConfigUpdate doConfigurationUpdate(Map configurationParameters) { - return new SensorConfigUpdate(); + return new SensorConfigUpdate(); } protected void doSensorStateChanged(@Nullable HueBridge bridge, FullSensor sensor, Configuration config) { diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/binding/binding.xml index a8fc3b129f88d..a878d4fded24d 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,5 @@ - diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/i18n/hue.properties b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/i18n/hue.properties index cffd5faff1b9b..c5e822dfe0e39 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/i18n/hue.properties +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/i18n/hue.properties @@ -10,12 +10,15 @@ offline.conf-error-creation-username = Failed to create new user on Hue bridge. offline.bridge-connection-lost = Hue bridge connection lost. offline.conf-error-no-light-id = Light ID not available in configuration. offline.conf-error-no-sensor-id = Sensor ID not available in configuration. +offline.conf-error-no-group-id = Group ID not available in configuration. offline.conf-error-wrong-light-id = No light with given ID available on Hue bridge. offline.conf-error-wrong-sensor-id = No sensor with given ID available on Hue bridge. +offline.conf-error-wrong-group-id = No group with given ID available on Hue bridge. offline.light-not-reachable = Hue bridge reports light as not reachable. offline.sensor-not-reachable = Hue bridge reports sensor as not reachable. offline.light-removed = Hue bridge reports light as removed. offline.sensor-removed = Hue bridge reports sensor as removed. +offline.group-removed = Hue bridge reports group as removed. #LightActions actionLabel=send a light command with a custom fade time diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/i18n/hue_fr.properties b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/i18n/hue_fr.properties index f5b100821ee58..6fc186e11b94e 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/i18n/hue_fr.properties +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/i18n/hue_fr.properties @@ -19,6 +19,8 @@ thing-type.hue.0210.label = Ampoule couleur thing-type.hue.0210.description = Une ampoule avec rglages de l'intensit lumineuse, de la couleur et de la temprature de couleur thing-type.hue.0220.label = Ampoule couleur thing-type.hue.0220.description = Une ampoule avec rglages de l'intensit lumineuse et de la temprature de couleur. +thing-type.hue.group.label = Groupe hue +thing-type.hue.group.description = Un groupe d'ampoules ou une pice pouvant tre allum et teint. # thing type configuration thing-type.config.hue.bridge.ipAddress.label = Adresse rseau @@ -41,6 +43,8 @@ thing-type.config.hue.0210.lightId.label = ID ampoule thing-type.config.hue.0210.lightId.description = L'identifiant d'ampoule identifie l'une des ampoules hue. thing-type.config.hue.0220.lightId.label = ID ampoule thing-type.config.hue.0220.lightId.description = L'identifiant d'ampoule identifie l'une des ampoules hue. +thing-type.config.hue.group.groupId.label = ID groupe +thing-type.config.hue.group.groupId.description = L'identifiant de groupe identifie l'un des groupes d'ampoules hue ou une pice. # channel types channel-type.hue.color.label = Couleur @@ -70,5 +74,9 @@ offline.conf-error-press-pairing-button = Non autentifi offline.conf-error-creation-username = Echec de la cratiion du nouvel utilisateur sur le pont de connexion hue. offline.bridge-connection-lost = Perte de la connexion au pont hue. offline.conf-error-no-light-id = ID ampoule non renseign dans la configuration. +offline.conf-error-no-group-id = ID groupe non renseign dans la configuration. +offline.conf-error-wrong-light-id = Pas d''ampoule avec cet ID dans le pont de connexion hue. +offline.conf-error-wrong-group-id = Pas de groupe avec cet ID dans le pont de connexion hue. offline.light-not-reachable = Le pont de connexion hue signale l''ampoule comme inaccessible. offline.light-removed = Le pont de connexion hue signale l''ampoule comme supprime. +offline.group-removed = Le pont de connexion hue signale le groupe comme supprim. diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/CLIPGenericFlagSensor.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/CLIPGenericFlagSensor.xml index d16cc4ef435cb..0d165659f1e31 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/CLIPGenericFlagSensor.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/CLIPGenericFlagSensor.xml @@ -6,15 +6,15 @@ - + A generic sensor object for IP sensor use. - - + + uniqueId diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/CLIPGenericStatusSensor.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/CLIPGenericStatusSensor.xml index 5d134b91e2bd4..2e425b01b7a4c 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/CLIPGenericStatusSensor.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/CLIPGenericStatusSensor.xml @@ -6,15 +6,15 @@ - + A generic sensor object for IP sensor use. - - + + uniqueId diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ColorLight.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ColorLight.xml index 4e11fcb6b3137..2ca6cac27fae1 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ColorLight.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ColorLight.xml @@ -6,16 +6,16 @@ - + A dimmable light with changeable colors. - - - + + + uniqueId @@ -26,9 +26,9 @@ The light identifier identifies one certain hue light. true
- + - Fade time in ms for changing values + Fade time in milliseconds for changing values 400
diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ColorTemperatureLight.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ColorTemperatureLight.xml index 625294b8daa0c..ef6e281a61e2c 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ColorTemperatureLight.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ColorTemperatureLight.xml @@ -6,17 +6,17 @@ - + A dimmable light with tunable color temperature. - - - - + + + + uniqueId @@ -27,9 +27,9 @@ The light identifier identifies one certain hue light. true
- + - Fade time in ms for changing values + Fade time in milliseconds for changing values 400 diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmableLight.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmableLight.xml index 9e06ea5256352..e2bf2499a8e7d 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmableLight.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmableLight.xml @@ -6,15 +6,15 @@ - + A dimmable light. - - + + uniqueId @@ -25,9 +25,9 @@ The light identifier identifies one certain hue light. true - + - Fade time in ms for changing values + Fade time in milliseconds for changing values 400 diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmablePlug.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmablePlug.xml index 1678e02a05f36..c83f88ac3ee18 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmablePlug.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmablePlug.xml @@ -6,14 +6,14 @@ - + An outlet that can be dimmed. - + uniqueId @@ -24,9 +24,9 @@ The identifier that is used within the hue bridge. true - + - Fade time in ms for changing values + Fade time in milliseconds for changing values 400 diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmerSwitch.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmerSwitch.xml index 48fda3f7cb276..6825f79ade8bc 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmerSwitch.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/DimmerSwitch.xml @@ -6,18 +6,18 @@ - + A dimmer switch. - - - - - + + + + + uniqueId diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ExtendedColorLight.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ExtendedColorLight.xml index 943eb01508d42..b47edf183b012 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ExtendedColorLight.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/ExtendedColorLight.xml @@ -6,17 +6,17 @@ - + A dimmable light with changeable colors and tunable color temperature. - - - - + + + + uniqueId @@ -27,9 +27,9 @@ The light identifier identifies one certain hue light. true - + - Fade time in ms for changing values + Fade time in milliseconds for changing values 400 diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/Group.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/Group.xml new file mode 100644 index 0000000000000..3a2715940c6a4 --- /dev/null +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/Group.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + A group of lights or a room that could be switched on and off. + + + + + + + + + groupId + + + + + The group identifier identifies one certain hue group or room. + true + + + + Fade time in milliseconds for changing values + 400 + + + + diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/LightLevelSensor.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/LightLevelSensor.xml index 402288f60840e..e9f38ebcd7dde 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/LightLevelSensor.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/LightLevelSensor.xml @@ -6,20 +6,20 @@ - + A sensor providing light level information. - - - - - - - + + + + + + + uniqueId @@ -36,16 +36,19 @@ - Turns device LED during normal operation on or off. Devices might still indicate exceptional operation (Reset, SW Update, Battery Low). + Turns device LED during normal operation on or off. Devices might still indicate exceptional operation + (Reset, SW Update, Battery Low). - Threshold the user configured to be used in rules to determine insufficient light level (ie below threshold). Default value 16000. + Threshold the user configured to be used in rules to determine insufficient light level (ie below + threshold). Default value 16000. 16000 - Threshold the user configured to be used in rules to determine sufficient light level (ie above threshold). Specified as relative offset to the “dark” threshold. Shall be >=1. Default value 7000. + Threshold the user configured to be used in rules to determine sufficient light level (ie above + threshold). Specified as relative offset to the “dark” threshold. Shall be >=1. Default value 7000. 7000 diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/OnOffLight.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/OnOffLight.xml index c954a8cdffd4c..11bee9fa1c67c 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/OnOffLight.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/OnOffLight.xml @@ -6,15 +6,15 @@ - + A light that could be switched on and off. - - + + uniqueId diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/OnOffPlug.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/OnOffPlug.xml index 5e4c650076f5d..690e6fbccd9da 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/OnOffPlug.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/OnOffPlug.xml @@ -6,14 +6,14 @@ - + An outlet that could be switched on and off. - + uniqueId diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/PresenceSensor.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/PresenceSensor.xml index a91e9cd6769af..d3f486f8ff2f6 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/PresenceSensor.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/PresenceSensor.xml @@ -6,17 +6,17 @@ - + A motion sensor providing presence detection. - - - - + + + + uniqueId @@ -33,7 +33,8 @@
- Turns device LED during normal operation on or off. Devices might still indicate exceptional operation (Reset, SW Update, Battery Low). + Turns device LED during normal operation on or off. Devices might still indicate exceptional operation + (Reset, SW Update, Battery Low). diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/TapSwitch.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/TapSwitch.xml index dcfff23fda1ba..409f67b77f7c9 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/TapSwitch.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/TapSwitch.xml @@ -6,16 +6,16 @@ - + A customizable switch. - - - + + + uniqueId diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/TemperatureSensor.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/TemperatureSensor.xml index d8af6f2f8e56b..f1f1a65112a81 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/TemperatureSensor.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/TemperatureSensor.xml @@ -6,17 +6,17 @@ - + A sensor providing temperature values. - - - - + + + + uniqueId @@ -33,7 +33,8 @@ - Turns device LED during normal operation on or off. Devices might still indicate exceptional operation (Reset, SW Update, Battery Low). + Turns device LED during normal operation on or off. Devices might still indicate exceptional operation + (Reset, SW Update, Battery Low). diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/bridge.xml index a291b3676a9b4..8c2faf491819c 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/bridge.xml @@ -38,7 +38,8 @@ - Milliseconds between fetching sensor-values from the Hue bridge. A higher value means more delay for the sensor values, but a too low value can cause congestion on the Hue bridge. + Milliseconds between fetching sensor-values from the Hue bridge. A higher value means more delay for + the sensor values, but a too low value can cause congestion on the Hue bridge. true 500 diff --git a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/channels.xml index c284b4364350c..d6645d2f43401 100644 --- a/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.hue/src/main/resources/ESH-INF/thing/channels.xml @@ -36,35 +36,35 @@ The date and time when the sensor was last updated. Time - + Number:Illuminance Current illuminance. - + Number Current light level. - + Switch Light level is below the darkness threshold. - + Switch Light level is above the daylight threshold. - + @@ -165,7 +165,7 @@ Current temperature. Temperature - + @@ -199,7 +199,7 @@ The effect channel allows putting the bulb in a color looping mode. ColorLight - + Number @@ -212,5 +212,5 @@ Flag of CLIP sensor. - + diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/ApiVersionTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/ApiVersionTest.java index 416ff4734e945..aac7516caf03f 100644 --- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/ApiVersionTest.java +++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/ApiVersionTest.java @@ -52,6 +52,5 @@ public void testCompare() { assertTrue(v.compare(new ApiVersion(0, 2, 3)) > 0); assertTrue(v.compare(new ApiVersion(3, 2, 3)) < 0); - } } diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/LightStateConverterTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/LightStateConverterTest.java index c594b753e13ab..9365e2f78e260 100644 --- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/LightStateConverterTest.java +++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/LightStateConverterTest.java @@ -19,8 +19,6 @@ import org.eclipse.smarthome.core.library.types.HSBType; import org.eclipse.smarthome.core.library.types.PercentType; import org.junit.Test; -import org.openhab.binding.hue.internal.State; -import org.openhab.binding.hue.internal.StateUpdate; import org.openhab.binding.hue.internal.State.ColorMode; import org.openhab.binding.hue.internal.handler.LightStateConverter; diff --git a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java index 93762e189f4ef..4d204b19509fe 100644 --- a/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java +++ b/bundles/org.openhab.binding.hue/src/test/java/org/openhab/binding/hue/internal/handler/HueLightHandlerTest.java @@ -400,5 +400,4 @@ private void assertJson(String expected, String actual) { JsonElement jsonActual = parser.parse(actual); assertEquals(jsonExpected, jsonActual); } - } diff --git a/bundles/org.openhab.binding.hydrawise/pom.xml b/bundles/org.openhab.binding.hydrawise/pom.xml index af2cc58bb4345..4bbebad4ba07c 100644 --- a/bundles/org.openhab.binding.hydrawise/pom.xml +++ b/bundles/org.openhab.binding.hydrawise/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.hydrawise diff --git a/bundles/org.openhab.binding.hydrawise/src/main/feature/feature.xml b/bundles/org.openhab.binding.hydrawise/src/main/feature/feature.xml index 5db2f38481787..07ffb45437059 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.hydrawise/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.hydrawise/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.hydrawise/${project.version} + diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseBindingConstants.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseBindingConstants.java index 309002526901d..8570a19b19b1e 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseBindingConstants.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseBindingConstants.java @@ -66,5 +66,4 @@ public class HydrawiseBindingConstants { public static final String PROPERTY_DESCRIPTION = "description"; public static final String PROPERTY_LOCATION = "location"; public static final String PROPERTY_ADDRESS = "address"; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseCloudHandler.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseCloudHandler.java index 3c590ab55a547..39a59c46e69d7 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseCloudHandler.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseCloudHandler.java @@ -155,7 +155,6 @@ protected void sendStopCommand(@Nullable Relay relay) if (relay != null) { client.stopRelay(relay.relayId); } - } @Override diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseLocalHandler.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseLocalHandler.java index 7db82979ed286..e117a8ecfae49 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseLocalHandler.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/HydrawiseLocalHandler.java @@ -46,7 +46,6 @@ protected void configure() throws HydrawiseConnectionException, HydrawiseAuthent logger.trace("Connecting to host {}", configuration.host); client.setCredentials(configuration.host, configuration.username, configuration.password); pollController(); - } @Override diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/BocTopologyActual.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/BocTopologyActual.java index 66741dc7e155f..199c3a72cc492 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/BocTopologyActual.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/BocTopologyActual.java @@ -22,5 +22,4 @@ public class BocTopologyActual { public List bocGateways; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/BocTopologyDesired.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/BocTopologyDesired.java index 8da2ce9a8759c..f3dbde6fb43ec 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/BocTopologyDesired.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/BocTopologyDesired.java @@ -22,5 +22,4 @@ public class BocTopologyDesired { public List bocGateways; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Controller.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Controller.java index adeb0852df569..97214482d0c31 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Controller.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Controller.java @@ -62,5 +62,4 @@ public class Controller { public Boolean online; public List tags = null; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/CustomerDetailsResponse.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/CustomerDetailsResponse.java index df247117e94c7..5425426619fa5 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/CustomerDetailsResponse.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/CustomerDetailsResponse.java @@ -46,5 +46,4 @@ public class CustomerDetailsResponse extends Response { public Integer tandcVersion; public Features features; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Features.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Features.java index 29dd6dd24c204..32d8aaed1ce14 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Features.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Features.java @@ -98,5 +98,4 @@ public class Features { public String customerplanId; public Integer smsUsed; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Forecast.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Forecast.java index 2767a9c88890f..1c7b9fe49a0c7 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Forecast.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Forecast.java @@ -36,5 +36,4 @@ public class Forecast { public String icon; public String iconLocal; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/LocalScheduleResponse.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/LocalScheduleResponse.java index b9fda4df85915..9e804b477b8c8 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/LocalScheduleResponse.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/LocalScheduleResponse.java @@ -29,5 +29,4 @@ public class LocalScheduleResponse extends Response { public String name; public Integer time; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/PlanArray.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/PlanArray.java index 4db5b2a06ba8f..927b2a337cdf8 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/PlanArray.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/PlanArray.java @@ -88,5 +88,4 @@ public class PlanArray { public String start; public String customerplanId; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Relay.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Relay.java index 3d9668214c94c..65e1dae5be9dd 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Relay.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Relay.java @@ -54,5 +54,4 @@ public int getRelayNumber() { int quotient = relay / 100; return (relay - (quotient * 100)) + (quotient * 12); } - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Response.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Response.java index 516958cde40c1..f5bca8a42b4e2 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Response.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Response.java @@ -20,5 +20,4 @@ public class Response { public String errorMsg; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Running.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Running.java index 241e6b9223674..610d478e53fe4 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Running.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Running.java @@ -26,5 +26,4 @@ public class Running { public Integer timeLeft; public String run; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Sensor.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Sensor.java index a1273ad30fe38..9ee2b70d529d4 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Sensor.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/Sensor.java @@ -38,5 +38,4 @@ public class Sensor { public Integer active; public List relays = null; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/SetControllerResponse.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/SetControllerResponse.java index 340834a1e723e..e2d8b1e671804 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/SetControllerResponse.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/SetControllerResponse.java @@ -24,5 +24,4 @@ public class SetControllerResponse extends Response { public String controllerId; public String message; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/SetZoneResponse.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/SetZoneResponse.java index 126d6fa9d2fbc..bf67bf9f5652d 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/SetZoneResponse.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/SetZoneResponse.java @@ -22,5 +22,4 @@ public class SetZoneResponse extends Response { public String message; public String messageType; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/StatusScheduleResponse.java b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/StatusScheduleResponse.java index 8d9d399d4008b..af88b4734a98f 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/StatusScheduleResponse.java +++ b/bundles/org.openhab.binding.hydrawise/src/main/java/org/openhab/binding/hydrawise/internal/api/model/StatusScheduleResponse.java @@ -57,5 +57,4 @@ public class StatusScheduleResponse extends LocalScheduleResponse { public String status; public String statusIcon; - } diff --git a/bundles/org.openhab.binding.hydrawise/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.hydrawise/src/main/resources/ESH-INF/thing/channel-types.xml index aeae5e87503bb..a7532abfbe901 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.hydrawise/src/main/resources/ESH-INF/thing/channel-types.xml @@ -8,14 +8,14 @@ Hydrawise zone - - - - - - - - + + + + + + + + @@ -23,22 +23,22 @@ Commands that control all Hydrawise zones - - + + - + Hydrawise sensor - - - - - - - + + + + + + + @@ -46,12 +46,12 @@ Hydrawise weather forecast - - - - - - + + + + + + @@ -173,7 +173,7 @@ High temperature Temperature - + @@ -181,7 +181,7 @@ Low Temperature Temperature - + @@ -210,7 +210,7 @@ Humidity percentage Temperature - + @@ -218,6 +218,6 @@ Wind speed Wind - + diff --git a/bundles/org.openhab.binding.hydrawise/src/main/resources/ESH-INF/thing/things.xml b/bundles/org.openhab.binding.hydrawise/src/main/resources/ESH-INF/thing/things.xml index 3b2e35fc485cf..b783b67833a86 100644 --- a/bundles/org.openhab.binding.hydrawise/src/main/resources/ESH-INF/thing/things.xml +++ b/bundles/org.openhab.binding.hydrawise/src/main/resources/ESH-INF/thing/things.xml @@ -9,7 +9,7 @@ Hydrawise cloud connected irrigation system - @@ -46,7 +46,7 @@ Day 4 weather forecast - + diff --git a/bundles/org.openhab.binding.hyperion/pom.xml b/bundles/org.openhab.binding.hyperion/pom.xml index 71787bb8a51a5..4f518ffacf91a 100644 --- a/bundles/org.openhab.binding.hyperion/pom.xml +++ b/bundles/org.openhab.binding.hyperion/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.hyperion diff --git a/bundles/org.openhab.binding.hyperion/src/main/feature/feature.xml b/bundles/org.openhab.binding.hyperion/src/main/feature/feature.xml index 01863fd228f43..3d968df15134b 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.hyperion/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - openhab-transport-http - mvn:org.openhab.addons.bundles/org.openhab.binding.hyperion/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + openhab-transport-http + mvn:org.openhab.addons.bundles/org.openhab.binding.hyperion/${project.version} + diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/HyperionBindingConstants.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/HyperionBindingConstants.java index 275169eb5cac4..005d9bfbd573f 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/HyperionBindingConstants.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/HyperionBindingConstants.java @@ -79,5 +79,4 @@ public class HyperionBindingConstants { SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_SERVER_V1); SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_SERVER_NG); } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/HyperionDiscoveryParticipant.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/HyperionDiscoveryParticipant.java index 6fe5cd33c6c2b..3f8a7a2019c24 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/HyperionDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/HyperionDiscoveryParticipant.java @@ -88,5 +88,4 @@ public ThingUID getThingUID(ServiceInfo service) { } return new ThingUID(HyperionBindingConstants.THING_TYPE_SERVER_NG, uid); } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/handler/HyperionNgHandler.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/handler/HyperionNgHandler.java index 5975eb37967eb..e197ed752da79 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/handler/HyperionNgHandler.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/handler/HyperionNgHandler.java @@ -459,7 +459,6 @@ private void handleEffect(Command command) throws IOException, CommandUnsuccessf } else { logger.debug("Channel {} unable to process command {}", CHANNEL_EFFECT, command); } - } private void handleClear(Command command) throws IOException, CommandUnsuccessfulException { @@ -494,5 +493,4 @@ public NgResponse sendCommand(HyperionCommand command) throws IOException, Comma } return response; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ColorCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ColorCommand.java index 70946008609ea..014d6228caf0e 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ColorCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ColorCommand.java @@ -63,5 +63,4 @@ public void setOrigin(String origin) { public String getOrigin() { return origin; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/EffectCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/EffectCommand.java index 67cc2634f4451..4bf0d4a744786 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/EffectCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/EffectCommand.java @@ -64,5 +64,4 @@ public void setOrigin(String origin) { public String getOrigin() { return origin; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/HyperionCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/HyperionCommand.java index d959a84e413b8..9f66a431a5b91 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/HyperionCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/HyperionCommand.java @@ -36,5 +36,4 @@ public String getCommand() { public void setCommand(String command) { this.command = command; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ServerInfoCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ServerInfoCommand.java index 9468ba5b6cf3e..95d788e67b30d 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ServerInfoCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ServerInfoCommand.java @@ -25,5 +25,4 @@ public class ServerInfoCommand extends HyperionCommand { public ServerInfoCommand() { super(NAME); } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Adjustment.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Adjustment.java index bc970b0454001..c844e53315632 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Adjustment.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Adjustment.java @@ -200,5 +200,4 @@ public List getYellow() { public void setYellow(List yellow) { this.yellow = yellow; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/AdjustmentCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/AdjustmentCommand.java index 72e71d074e013..7c837f27ff95b 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/AdjustmentCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/AdjustmentCommand.java @@ -37,5 +37,4 @@ public Adjustment getAdjustment() { public void setAdjustment(Adjustment adjustment) { this.adjustment = adjustment; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Component.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Component.java index f450301d5f152..b018e7d2b89b6 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Component.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Component.java @@ -42,5 +42,4 @@ public void setName(String name) { public void setEnabled(boolean enabled) { this.enabled = enabled; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/ComponentState.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/ComponentState.java index 2abb71a289ca4..2c77680213f54 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/ComponentState.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/ComponentState.java @@ -37,5 +37,4 @@ public String getComponent() { public boolean getState() { return state; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/ComponentStateCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/ComponentStateCommand.java index 453aecb68ec86..a4954161ee769 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/ComponentStateCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/ComponentStateCommand.java @@ -41,5 +41,4 @@ public ComponentState getComponentState() { public void setComponentState(ComponentState componentState) { this.componentState = componentState; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Hyperion.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Hyperion.java index 6e41b2c8bb4aa..a96e4f2ebd0f2 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Hyperion.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Hyperion.java @@ -66,5 +66,4 @@ public void setOff(boolean off) { public void setSessions(List sessions) { this.sessions = sessions; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/NgInfo.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/NgInfo.java index 98938c69df064..a4ebeb0e48d22 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/NgInfo.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/NgInfo.java @@ -75,5 +75,4 @@ public void setHyperion(Hyperion hyperion) { public List getEffects() { return effects; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/NgResponse.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/NgResponse.java index cb1680a4519ab..10bd07df582fd 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/NgResponse.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/NgResponse.java @@ -55,5 +55,4 @@ public NgInfo getInfo() { public String getError() { return error; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Priority.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Priority.java index 7a6eff92e06fd..4d942c6b3f1a8 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Priority.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Priority.java @@ -108,5 +108,4 @@ public Value getValue() { public void setValue(Value value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Session.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Session.java index 1558cc05b62ad..fa8fd8aa934e2 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Session.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Session.java @@ -86,5 +86,4 @@ public String getType() { public void setType(String type) { this.type = type; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Value.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Value.java index 271fb065d8405..562e531321482 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Value.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/ng/Value.java @@ -55,5 +55,4 @@ public void setHSL(List hsl) { public void setRGB(List rgb) { this.rgb = rgb; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ActiveEffect.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ActiveEffect.java index 9b8743c81cc0d..bbc922b3c5ad8 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ActiveEffect.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ActiveEffect.java @@ -53,5 +53,4 @@ public int getTimeout() { public void setTimeout(int timeout) { this.timeout = timeout; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ClearAllCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ClearAllCommand.java index 5a7422581f089..3e34abea06f03 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ClearAllCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ClearAllCommand.java @@ -27,5 +27,4 @@ public class ClearAllCommand extends HyperionCommand { public ClearAllCommand() { super(NAME); } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ClearCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ClearCommand.java index 0b3b5950f25b2..1d5450dec78ff 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ClearCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/ClearCommand.java @@ -37,5 +37,4 @@ public int getPriority() { public void setPriority(int priority) { this.priority = priority; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Correction.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Correction.java index d1810deaa00fd..ba15522128f60 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Correction.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Correction.java @@ -44,5 +44,4 @@ public String getId() { public void setId(String id) { this.id = id; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/HyperionBuild.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/HyperionBuild.java index e5650b5309c14..eb4d6fff6deab 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/HyperionBuild.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/HyperionBuild.java @@ -42,5 +42,4 @@ public String getVersion() { public void setVersion(String version) { this.version = version; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Priority.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Priority.java index d780c264def01..aa8bae3de90ff 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Priority.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Priority.java @@ -42,5 +42,4 @@ public Integer getDurationMs() { public void setDurationMs(Integer durationMs) { this.durationMs = durationMs; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Transform.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Transform.java index 4464c7c7a45fc..e2a49b0309749 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Transform.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/Transform.java @@ -132,5 +132,4 @@ public List getWhitelevel() { public void setWhitelevel(List whitelevel) { this.whitelevel = whitelevel; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/TransformCommand.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/TransformCommand.java index eaae1862fb728..22a78d995b1f8 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/TransformCommand.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/TransformCommand.java @@ -37,5 +37,4 @@ public Transform getTransform() { public void setTransform(Transform transform) { this.transform = transform; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/V1Info.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/V1Info.java index 01c36c183dff5..996c502305659 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/V1Info.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/V1Info.java @@ -134,5 +134,4 @@ public List getTransform() { public void setTransform(List transform) { this.transform = transform; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/V1Response.java b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/V1Response.java index 61926d8d82df7..274bc06ea0980 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/V1Response.java +++ b/bundles/org.openhab.binding.hyperion/src/main/java/org/openhab/binding/hyperion/internal/protocol/v1/V1Response.java @@ -48,5 +48,4 @@ public int getTan() { public V1Info getInfo() { return info; } - } diff --git a/bundles/org.openhab.binding.hyperion/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.hyperion/src/main/resources/ESH-INF/binding/binding.xml index c837b978531b0..b7e583bf2a7ec 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.hyperion/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - Hyperion Binding diff --git a/bundles/org.openhab.binding.hyperion/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.hyperion/src/main/resources/ESH-INF/thing/thing-types.xml index bf7b1eceb89cf..936630447f477 100644 --- a/bundles/org.openhab.binding.hyperion/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.hyperion/src/main/resources/ESH-INF/thing/thing-types.xml @@ -8,10 +8,10 @@ This is a Hyperion server - - - - + + + + @@ -42,20 +42,20 @@ This is a Hyperion.ng server - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -122,43 +122,50 @@ Switch - Shows the current state of the black border component and allows the black border component to be enabled or disabled + Shows the current state of the black border component and allows the black border component to be enabled + or disabled Switch - Shows the current state of the smoothing component and allows the smoothing component to be enabled or disabled + Shows the current state of the smoothing component and allows the smoothing component to be enabled or + disabled Switch - Shows the current state of the Kodi checker component and allows the Kodi checker component to be enabled or disabled + Shows the current state of the Kodi checker component and allows the Kodi checker component to be enabled + or disabled Switch - Shows the current state of the forwarder component and allows the forwarder component to be enabled or disabled + Shows the current state of the forwarder component and allows the forwarder component to be enabled or + disabled Switch - Shows the current state of the UDP listener component and allows the UDP listener component to be enabled or disabled + Shows the current state of the UDP listener component and allows the UDP listener component to be enabled + or disabled Switch - Shows the current state of the Boblight server component and allows the Boblight server component to be enabled or disabled + Shows the current state of the Boblight server component and allows the Boblight server component to be + enabled or disabled Switch - Shows the current state of the grabber component and allows the grabber component to be enabled or disabled + Shows the current state of the grabber component and allows the grabber component to be enabled or + disabled diff --git a/bundles/org.openhab.binding.iaqualink/pom.xml b/bundles/org.openhab.binding.iaqualink/pom.xml index 72d277eb26390..d0af430f127d0 100644 --- a/bundles/org.openhab.binding.iaqualink/pom.xml +++ b/bundles/org.openhab.binding.iaqualink/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.iaqualink diff --git a/bundles/org.openhab.binding.iaqualink/src/main/feature/feature.xml b/bundles/org.openhab.binding.iaqualink/src/main/feature/feature.xml index 9636f132581f4..c1dd5f7cd5ab0 100644 --- a/bundles/org.openhab.binding.iaqualink/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.iaqualink/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.iaqualink/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.iaqualink/${project.version} + diff --git a/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/Device.java b/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/Device.java index 82fbf8c5da275..6e7b869742789 100644 --- a/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/Device.java +++ b/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/Device.java @@ -139,5 +139,4 @@ public Object getLastActivityAt() { public void setLastActivityAt(Object lastActivityAt) { this.lastActivityAt = lastActivityAt; } - } diff --git a/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/OneTouch.java b/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/OneTouch.java index 379a787d4534e..56ee4759064be 100644 --- a/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/OneTouch.java +++ b/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/OneTouch.java @@ -59,5 +59,4 @@ public String getName() { public void setName(String name) { this.name = name; } - } diff --git a/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/SignIn.java b/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/SignIn.java index 9547da0c4fc08..70d72132759b7 100644 --- a/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/SignIn.java +++ b/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/api/model/SignIn.java @@ -56,5 +56,4 @@ public String getPassword() { public void setPassword(String password) { this.password = password; } - } diff --git a/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/handler/IAqualinkHandler.java b/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/handler/IAqualinkHandler.java index 48304ce9709c5..e74579b179df7 100644 --- a/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/handler/IAqualinkHandler.java +++ b/bundles/org.openhab.binding.iaqualink/src/main/java/org/openhab/binding/iaqualink/internal/handler/IAqualinkHandler.java @@ -551,5 +551,4 @@ private ChannelTypeUID getChannelTypeUID(ChannelUID channelUID) { Objects.requireNonNull(channelTypeUID); return channelTypeUID; } - } diff --git a/bundles/org.openhab.binding.iaqualink/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.iaqualink/src/main/resources/ESH-INF/binding/binding.xml index d2656e3160d57..b967484504589 100644 --- a/bundles/org.openhab.binding.iaqualink/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.iaqualink/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + iAquaLink Binding This is the binding for a iAquaLink pool controller. diff --git a/bundles/org.openhab.binding.iaqualink/src/main/resources/ESH-INF/thing/iAqualink.xml b/bundles/org.openhab.binding.iaqualink/src/main/resources/ESH-INF/thing/iAqualink.xml index 4fb473e2dcc52..5f8cf2326a7e9 100644 --- a/bundles/org.openhab.binding.iaqualink/src/main/resources/ESH-INF/thing/iAqualink.xml +++ b/bundles/org.openhab.binding.iaqualink/src/main/resources/ESH-INF/thing/iAqualink.xml @@ -8,9 +8,9 @@ A iAquaLink pool control thing represents a iAquaLink pool controller for Jandy/Zodiac systems - - - + + + The current temperature of the spa @@ -126,7 +126,7 @@ String The status of the iAqualink connection - + @@ -134,7 +134,7 @@ String System Type - + @@ -303,7 +303,7 @@ Number:Temperature Temperature - + @@ -311,7 +311,7 @@ Number:Temperature Temperature - + @@ -319,13 +319,13 @@ String The selected units for temperature (C or F) - + Number Other - + diff --git a/bundles/org.openhab.binding.icalendar/.classpath b/bundles/org.openhab.binding.icalendar/.classpath new file mode 100644 index 0000000000000..dc110e1296307 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/.classpath @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.icalendar/.project b/bundles/org.openhab.binding.icalendar/.project new file mode 100644 index 0000000000000..a635cb1b249dd --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/.project @@ -0,0 +1,23 @@ + + + org.openhab.binding.icalendar + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.icalendar/NOTICE b/bundles/org.openhab.binding.icalendar/NOTICE new file mode 100644 index 0000000000000..af17a7d022a9c --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/NOTICE @@ -0,0 +1,33 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab2-addons + +== Third Party Dependencies +Third Party Dependencies are used inside the code of this project, but not +redistributed. Instead, Openhab retrieves the dependencies directly from +public sources. + +=== net.sf.biweekly:biweekly +Author: Michael Angstadt, Apache Software Foundation, Google Inc. +URL: https://github.com/mangstadt/biweekly +License: BSD 2-Clause License, Apache License Version 2.0 + +=== com.github.mangstadt:vinnie +Author: Michael Angstadt, Apache Software Foundation +URL: https://github.com/mangstadt/vinnie +License: BSD 2-Clause License, Apache License Version 2.0 + +=== com.fasterxml.jackson.core:jackson-core +Author: FasterXML LLC +URL: https://github.com/FasterXML/jackson-core +License: Apache License Version 2.0 diff --git a/bundles/org.openhab.binding.icalendar/README.md b/bundles/org.openhab.binding.icalendar/README.md new file mode 100644 index 0000000000000..0efbb4f0bc50a --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/README.md @@ -0,0 +1,116 @@ +# iCalendar Binding + +This binding is intended to use a web-based iCal calendar as an event trigger or presence switch. +It implements several channels that indicate the current calendar event and upcoming calendar events. +Furthermore it is possible to embed `command tags` in the calendar event description in order to issue commands directly to other items in the system, without the need to create special rules. + +## Supported Things + +The only thing type is the calendar. +It is based on a single iCalendar file. +There can be multiple things having different properties representing different calendars. + +## Thing Configuration + +Each `calendar` thing requires the following configuration parameters: + +| parameter name | description | optional | +|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------| +| `url` | The URL of an iCalendar to be used as a source of events. | mandatory | +| `refreshTime` | The frequency in minutes with which the calendar gets refreshed from the source. | mandatory | +| `username` | The username for pulling the calendar. If set, the binding pulls the calendar using basic auth. Only valid in combination with `password` | optional | +| `password` | The password for pulling the calendar. If set, the binding pulls the calendar using basic auth. Only valid in combination with `username` | optional | +| `maxSize` | The maximum size of the iCal-file in Mebibytes. | mandatory (default available) | +| `authorizationCode` | The authorization code to permit the execution of embedded Command Tags. If set, the binding checks that the authorization code in the Command Tag matches before executing any commands. | optional | + +## Channels + +The channels describe the current and the next forthcoming event. +They are all read-only. + +| Channel | Type | Description | +|-------------------|-----------|-------------------------------------------------------------------------------| +| current_presence | Switch | Current presence of a event, ON if there is currently an event, OFF otherwise | +| current_title | String | Title of a currently present event | +| current_start | DateTime | Start of a currently present event | +| current_end | DateTime | End of a currently present event | +| next_title | String | Title of the next event | +| next_start | DateTime | Start of the next event | +| next_end | DateTime | End of the next event | + +## Command Tags + +Each calendar event may include one or more command tags in its description text. +These command tags are used to issue commands directly to other items in the system when the event begins or ends. +A command tag must consist of at least three fields. +A fourth field is optional. +The syntax is as follows: + +``` + BEGIN:Item_Name:New_State_Value + BEGIN:Item_Name:New_State_Value:Authorization_Code + END:Item_Name:New_State_Value + END:Item_Name:New_State_Value:Authorization_Code +``` + +The first field **must** be either `BEGIN` or `END`. +If it is `BEGIN` then the command will be executed at the beginning of the calendar event. +If it is `END` then the command will be executed at the end of the calendar event. +A calendar event may contain multiple `BEGIN` or `END` tags. +If an event contains both `BEGIN` and `END` tags, the item is (say) to be turned ON at the beginning of an event and turned OFF again at the end of the event. + +The `Item_Name` field must be the name of an Item. + +The `New_State_Value` is the state value that will be sent to the item. +It must be a value which is compatible with the item type. See openHAB core definitions for [command types](https://www.openhab.org/docs/concepts/items.html#state-and-command-type-formatting) for valid types and formats. + +The `Authorization_Code` may *optionally* be used as follows: + +- When the thing configuration parameter `authorizationCode` is blank, the binding will compare the `Authorization_Code` field to the `authorizationCode` Configuration Parameter, and it will only execute the command if the two strings are the same. + +- When the thing configuration parameter `authorizationCode` is not blank, the binding will NOT check this `Authorization_Code` field, and so it will always execute the command. + + +## Full Example + +All required information must be provided in the thing definition, either via UI or in the .things file.. + +``` +Thing icalendar:calendar:deadbeef "My calendar" @ "Internet" [ url="http://example.org/calendar.ical", refreshTime=60 ] +``` + +Link the channels as usual to items + +``` +String current_event_name "current event [%s]" { channel="icalendar:calendar:deadbeef:current_title" } +DateTime current_event_until "current until [%1$tT, %1$tY-%1$tm-%1$td]" { channel="icalendar:calendar:deadbeef:current_end" } +String next_event_name "next event [%s]" { channel="icalendar:calendar:deadbeef:next_title" } +DateTime next_event_at "next at [%1$tT, %1$tY-%1$tm-%1$td]" { channel="icalendar:calendar:deadbeef:next_start" } +``` + +Sitemap just showing the current event and the beginning of the next: + +``` +sitemap local label="My Sitemap w calendar" { + Frame label="events" { + Text item=current_event_name label="current event [%s]" + Text item=current_event_until label="current until [%s]" + Text item=next_event_name label="next event [%s]" + Text item=next_event_at label="next at [%s]" + } +} +``` + +Command tags in a calendar event (in the case that configuration parameter `authorizationCode` equals `abc`): + +``` +BEGIN:Calendar_Test_Temperature:12.3°C:abc +END:Calendar_Test_Temperature:23.4°F:abc +``` + +Command tags in a calendar event (in the case that configuration parameter `authorizationCode` is not set): + +``` +BEGIN:Calendar_Test_Switch:ON +END:Calendar_Test_Switch:OFF +``` diff --git a/bundles/org.openhab.binding.icalendar/pom.xml b/bundles/org.openhab.binding.icalendar/pom.xml new file mode 100644 index 0000000000000..4a8e747b35ff2 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + + org.openhab.binding.icalendar + openHAB Add-ons :: Bundles :: iCalendar Binding + + jackson-core,jackson-annotations,jackson-databind + 2.9.10 + + + + + net.sf.biweekly + biweekly + 0.6.3 + compile + + + + com.github.mangstadt + vinnie + 2.0.2 + compile + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + compile + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + compile + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + compile + + + diff --git a/bundles/org.openhab.binding.icalendar/src/main/feature/feature.xml b/bundles/org.openhab.binding.icalendar/src/main/feature/feature.xml new file mode 100644 index 0000000000000..660395f537705 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + openhab-runtime-base + openhab.tp-jackson + mvn:org.openhab.addons.bundles/org.openhab.binding.icalendar/${project.version} + + diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/ICalendarBindingConstants.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/ICalendarBindingConstants.java new file mode 100644 index 0000000000000..19a27acd6de72 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/ICalendarBindingConstants.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link ICalendarBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Michael Wodniok - Initial contribution + */ +@NonNullByDefault +public class ICalendarBindingConstants { + + public static final String BINDING_ID = "icalendar"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_CALENDAR = new ThingTypeUID(BINDING_ID, "calendar"); + + // List of all Channel ids + public static final String CHANNEL_CURRENT_EVENT_TITLE = "current_title"; + public static final String CHANNEL_CURRENT_EVENT_START = "current_start"; + public static final String CHANNEL_CURRENT_EVENT_END = "current_end"; + public static final String CHANNEL_CURRENT_EVENT_PRESENT = "current_presence"; + public static final String CHANNEL_NEXT_EVENT_TITLE = "next_title"; + public static final String CHANNEL_NEXT_EVENT_START = "next_start"; + public static final String CHANNEL_NEXT_EVENT_END = "next_end"; + + // additional constants + public static final int HTTP_TIMEOUT_SECS = 60; +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/ICalendarHandlerFactory.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/ICalendarHandlerFactory.java new file mode 100644 index 0000000000000..a24d83f5193af --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/ICalendarHandlerFactory.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal; + +import static org.openhab.binding.icalendar.internal.ICalendarBindingConstants.THING_TYPE_CALENDAR; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.smarthome.core.events.EventPublisher; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.net.http.HttpClientFactory; +import org.openhab.binding.icalendar.internal.handler.ICalendarHandler; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link ICalendarHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Michael Wodniok - Initial contribution + * @author Andrew Fiddian-Green - EventPublisher code + */ +@NonNullByDefault +@Component(configurationPid = "binding.icalendar", service = ThingHandlerFactory.class) +public class ICalendarHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_CALENDAR); + + private final HttpClient sharedHttpClient; + private final EventPublisher eventPublisher; + + @Activate + public ICalendarHandlerFactory(@Reference HttpClientFactory httpClientFactory, + @Reference EventPublisher eventPublisher) { + this.eventPublisher = eventPublisher; + sharedHttpClient = httpClientFactory.getCommonHttpClient(); + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + final ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (!supportsThingType(thingTypeUID)) { + return null; + } + return new ICalendarHandler(thing, sharedHttpClient, eventPublisher); + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/config/ICalendarConfiguration.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/config/ICalendarConfiguration.java new file mode 100644 index 0000000000000..b90620011b0ba --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/config/ICalendarConfiguration.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.config; + +import java.math.BigDecimal; + +/** + * The {@link ICalendarConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Michael Wodniok - Initial contribution + * @author Andrew Fiddian-Green - Support for authorizationCode + */ +public class ICalendarConfiguration { + public String authorizationCode; + public Integer maxSize; + public String password; + public BigDecimal refreshTime; + public String url; + public String username; +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/handler/ICalendarHandler.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/handler/ICalendarHandler.java new file mode 100644 index 0000000000000..c335633a83fc7 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/handler/ICalendarHandler.java @@ -0,0 +1,356 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.handler; + +import static org.openhab.binding.icalendar.internal.ICalendarBindingConstants.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.time.Instant; +import java.time.ZoneId; +import java.util.List; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.smarthome.config.core.ConfigConstants; +import org.eclipse.smarthome.core.events.EventPublisher; +import org.eclipse.smarthome.core.items.events.ItemEventFactory; +import org.eclipse.smarthome.core.library.types.DateTimeType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.icalendar.internal.config.ICalendarConfiguration; +import org.openhab.binding.icalendar.internal.handler.PullJob.CalendarUpdateListener; +import org.openhab.binding.icalendar.internal.logic.AbstractPresentableCalendar; +import org.openhab.binding.icalendar.internal.logic.CalendarException; +import org.openhab.binding.icalendar.internal.logic.CommandTag; +import org.openhab.binding.icalendar.internal.logic.CommandTagType; +import org.openhab.binding.icalendar.internal.logic.Event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ICalendarHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Michael Wodniok - Initial contribution + * @author Andrew Fiddian-Green - Support for Command Tags embedded in the Event description + */ +@NonNullByDefault +public class ICalendarHandler extends BaseThingHandler implements CalendarUpdateListener { + + private final File calendarFile; + private @Nullable ICalendarConfiguration configuration; + private final EventPublisher eventPublisherCallback; + private final HttpClient httpClient; + private final Logger logger = LoggerFactory.getLogger(ICalendarHandler.class); + private @Nullable ScheduledFuture pullJobFuture; + private @Nullable AbstractPresentableCalendar runtimeCalendar; + private @Nullable ScheduledFuture updateJobFuture; + private Instant updateStatesLastCalledTime; + + public ICalendarHandler(Thing thing, HttpClient httpClient, EventPublisher eventPublisher) { + super(thing); + this.httpClient = httpClient; + calendarFile = new File(ConfigConstants.getUserDataFolder() + File.separator + + getThing().getUID().getAsString().replaceAll("[<>:\"/\\\\|?*]", "_") + ".ical"); + eventPublisherCallback = eventPublisher; + updateStatesLastCalledTime = Instant.now(); + } + + @Override + public void dispose() { + final ScheduledFuture currentUpdateJobFuture = updateJobFuture; + if (currentUpdateJobFuture != null) { + currentUpdateJobFuture.cancel(true); + } + final ScheduledFuture currentPullJobFuture = pullJobFuture; + if (currentPullJobFuture != null) { + currentPullJobFuture.cancel(true); + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + switch (channelUID.getId()) { + case CHANNEL_CURRENT_EVENT_PRESENT: + case CHANNEL_CURRENT_EVENT_TITLE: + case CHANNEL_CURRENT_EVENT_START: + case CHANNEL_CURRENT_EVENT_END: + case CHANNEL_NEXT_EVENT_TITLE: + case CHANNEL_NEXT_EVENT_START: + case CHANNEL_NEXT_EVENT_END: + if (command instanceof RefreshType) { + updateStates(); + } + break; + default: + logger.warn("Framework sent command to unknown channel with id '{}'", channelUID.getId()); + } + } + + @Override + public void initialize() { + updateStatus(ThingStatus.UNKNOWN); + + final ICalendarConfiguration currentConfiguration = getConfigAs(ICalendarConfiguration.class); + configuration = currentConfiguration; + + if ((currentConfiguration.username == null && currentConfiguration.password != null) + || (currentConfiguration.username != null && currentConfiguration.password == null)) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Only one of username and password was set. This is invalid."); + return; + } + + PullJob regularPull; + try { + regularPull = new PullJob(httpClient, new URI(currentConfiguration.url), currentConfiguration.username, + currentConfiguration.password, calendarFile, currentConfiguration.maxSize * 1048576, this); + } catch (URISyntaxException e) { + logger.warn( + "The URI '{}' for downloading the calendar contains syntax errors. This will result in no downloads/updates.", + currentConfiguration.url, e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR); + return; + } + + if (calendarFile.isFile()) { + if (reloadCalendar()) { + updateStatus(ThingStatus.ONLINE); + updateStates(); + rescheduleCalendarStateUpdate(); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "The calendar seems to be configured correctly, but the local copy of calendar could not be loaded."); + } + pullJobFuture = scheduler.scheduleWithFixedDelay(regularPull, currentConfiguration.refreshTime.longValue(), + currentConfiguration.refreshTime.longValue(), TimeUnit.MINUTES); + } else { + updateStatus(ThingStatus.OFFLINE); + logger.debug( + "The calendar is currently offline as no local copy exists. It will go online as soon as a valid valid calendar is retrieved."); + pullJobFuture = scheduler.scheduleWithFixedDelay(regularPull, 0, + currentConfiguration.refreshTime.longValue(), TimeUnit.MINUTES); + } + } + + @Override + public void onCalendarUpdated() { + if (reloadCalendar()) { + updateStates(); + } else { + logger.trace("Calendar was updated, but loading failed."); + } + } + + private void executeEventCommands(List events, CommandTagType execTime) { + // no begun or ended events => exit quietly as there is nothing to do + if (events.isEmpty()) { + return; + } + + // prevent potential synchronization issues (MVN null pointer warnings) in "configuration" + @Nullable + ICalendarConfiguration syncConfiguration = configuration; + if (syncConfiguration == null) { + logger.debug("Configuration not instantiated!"); + return; + } + // loop through all events in the list + for (Event event : events) { + + // loop through all command tags in the event + for (CommandTag cmdTag : event.commandTags) { + + // only process the BEGIN resp. END tags + if (cmdTag.getTagType() != execTime) { + continue; + } + if (!cmdTag.isAuthorized(syncConfiguration.authorizationCode)) { + logger.warn("Event: {}, Command Tag: {} => Command not authorized!", event.title, + cmdTag.getFullTag()); + continue; + } + + final Command cmdState = cmdTag.getCommand(); + if (cmdState == null) { + logger.warn("Event: {}, Command Tag: {} => Error creating Command State!", event.title, + cmdTag.getFullTag()); + continue; + } + + // (try to) execute the command + try { + eventPublisherCallback.post(ItemEventFactory.createCommandEvent(cmdTag.getItemName(), cmdState)); + if (logger.isDebugEnabled()) { + String cmdType = cmdState.getClass().toString(); + int index = cmdType.lastIndexOf(".") + 1; + if ((index > 0) && (index < cmdType.length())) { + cmdType = cmdType.substring(index); + } + logger.debug("Event: {}, Command Tag: {} => {}.postUpdate({}: {})", event.title, + cmdTag.getFullTag(), cmdTag.getItemName(), cmdType, cmdState); + } + } catch (IllegalArgumentException | IllegalStateException e) { + logger.warn("Event: {}, Command Tag: {} => Unable to push command to target item!", event.title, + cmdTag.getFullTag()); + logger.debug("Exception occured while pushing to item!", e); + } + } + } + } + + /** + * Reloads the calendar from local ical-file. Replaces the class internal calendar - if loading succeeds. Else + * logging details at warn-level logger. + * + * @return Whether the calendar was loaded successfully. + */ + private boolean reloadCalendar() { + if (!calendarFile.isFile()) { + logger.info("Local file for reloading calendar is missing."); + return false; + } + final ICalendarConfiguration config = configuration; + if (config == null) { + logger.warn("Can't reload calendar when configuration is missing."); + return false; + } + try (final FileInputStream fileStream = new FileInputStream(calendarFile)) { + final AbstractPresentableCalendar calendar = AbstractPresentableCalendar.create(fileStream); + runtimeCalendar = calendar; + rescheduleCalendarStateUpdate(); + } catch (IOException | CalendarException e) { + logger.warn("Loading calendar failed: {}", e.getMessage()); + return false; + } + return true; + } + + /** + * Reschedules the next update of the states. + */ + private void rescheduleCalendarStateUpdate() { + final ScheduledFuture currentUpdateJobFuture = updateJobFuture; + if (currentUpdateJobFuture != null) { + if (!(currentUpdateJobFuture.isCancelled() || currentUpdateJobFuture.isDone())) { + currentUpdateJobFuture.cancel(true); + } + updateJobFuture = null; + } + final AbstractPresentableCalendar currentCalendar = runtimeCalendar; + if (currentCalendar == null) { + return; + } + final Instant now = Instant.now(); + if (currentCalendar.isEventPresent(now)) { + final Event currentEvent = currentCalendar.getCurrentEvent(now); + if (currentEvent == null) { + logger.debug( + "Could not schedule next update of states, due to unexpected behaviour of calendar implementation."); + return; + } + updateJobFuture = scheduler.schedule(() -> { + ICalendarHandler.this.updateStates(); + ICalendarHandler.this.rescheduleCalendarStateUpdate(); + }, currentEvent.end.getEpochSecond() - now.getEpochSecond(), TimeUnit.SECONDS); + } else { + final Event nextEvent = currentCalendar.getNextEvent(now); + final ICalendarConfiguration currentConfig = this.configuration; + if (currentConfig == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Something is broken, the configuration is not available."); + return; + } + if (nextEvent == null) { + updateJobFuture = scheduler.schedule(() -> { + ICalendarHandler.this.rescheduleCalendarStateUpdate(); + }, 1L, TimeUnit.DAYS); + } else { + updateJobFuture = scheduler.schedule(() -> { + ICalendarHandler.this.updateStates(); + ICalendarHandler.this.rescheduleCalendarStateUpdate(); + }, nextEvent.start.getEpochSecond() - now.getEpochSecond(), TimeUnit.SECONDS); + } + } + } + + /** + * Updates the states of the Thing and its channels. + */ + private void updateStates() { + final AbstractPresentableCalendar calendar = runtimeCalendar; + if (calendar == null) { + updateStatus(ThingStatus.OFFLINE); + } else { + updateStatus(ThingStatus.ONLINE); + + final Instant now = Instant.now(); + if (calendar.isEventPresent(now)) { + updateState(CHANNEL_CURRENT_EVENT_PRESENT, OnOffType.ON); + final Event currentEvent = calendar.getCurrentEvent(now); + if (currentEvent == null) { + logger.warn("Unexpected inconsistency of internal API. Not Updating event details."); + } else { + updateState(CHANNEL_CURRENT_EVENT_TITLE, new StringType(currentEvent.title)); + updateState(CHANNEL_CURRENT_EVENT_START, + new DateTimeType(currentEvent.start.atZone(ZoneId.systemDefault()))); + updateState(CHANNEL_CURRENT_EVENT_END, + new DateTimeType(currentEvent.end.atZone(ZoneId.systemDefault()))); + } + } else { + updateState(CHANNEL_CURRENT_EVENT_PRESENT, OnOffType.OFF); + updateState(CHANNEL_CURRENT_EVENT_TITLE, UnDefType.UNDEF); + updateState(CHANNEL_CURRENT_EVENT_START, UnDefType.UNDEF); + updateState(CHANNEL_CURRENT_EVENT_END, UnDefType.UNDEF); + } + + final Event nextEvent = calendar.getNextEvent(now); + if (nextEvent != null) { + updateState(CHANNEL_NEXT_EVENT_TITLE, new StringType(nextEvent.title)); + updateState(CHANNEL_NEXT_EVENT_START, new DateTimeType(nextEvent.start.atZone(ZoneId.systemDefault()))); + updateState(CHANNEL_NEXT_EVENT_END, new DateTimeType(nextEvent.end.atZone(ZoneId.systemDefault()))); + } else { + updateState(CHANNEL_NEXT_EVENT_TITLE, UnDefType.UNDEF); + updateState(CHANNEL_NEXT_EVENT_START, UnDefType.UNDEF); + updateState(CHANNEL_NEXT_EVENT_END, UnDefType.UNDEF); + } + + // process all Command Tags in all Calendar Events which ENDED since updateStates was last called + // the END Event tags must be processed before the BEGIN ones + executeEventCommands(calendar.getJustEndedEvents(updateStatesLastCalledTime, now), CommandTagType.END); + + // process all Command Tags in all Calendar Events which BEGAN since updateStates was last called + // the END Event tags must be processed before the BEGIN ones + executeEventCommands(calendar.getJustBegunEvents(updateStatesLastCalledTime, now), CommandTagType.BEGIN); + + // save time when updateStates was previously called + // the purpose is to prevent repeat command execution of events that have already been executed + updateStatesLastCalledTime = now; + } + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/handler/PullJob.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/handler/PullJob.java new file mode 100644 index 0000000000000..87f6f1ba70b83 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/handler/PullJob.java @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.icalendar.internal.handler; + +import static org.openhab.binding.icalendar.internal.ICalendarBindingConstants.HTTP_TIMEOUT_SECS; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.Authentication; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.client.util.BasicAuthentication; +import org.eclipse.jetty.client.util.InputStreamResponseListener; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.openhab.binding.icalendar.internal.logic.AbstractPresentableCalendar; +import org.openhab.binding.icalendar.internal.logic.CalendarException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The Job for pulling an update of a calendar. Fires + * {@link CalendarUpdateListener#onCalendarUpdated()} after successful update. + * + * @author Michael Wodniok - Initial contribution + */ +@NonNullByDefault +class PullJob implements Runnable { + private final static String TMP_FILE_PREFIX = "icalendardld"; + + private final Authentication.@Nullable Result authentication; + private final File destination; + private final HttpClient httpClient; + private final CalendarUpdateListener listener; + private final Logger logger = LoggerFactory.getLogger(PullJob.class); + private final int maxSize; + private final URI sourceURI; + + /** + * Constructor of PullJob for creating a single pull of a calendar. + * + * @param httpClient A HttpClient for getting the source + * @param sourceURI The source as URI + * @param username Optional username for basic auth. Must be set together with a password. + * @param password Optional password for basic auth. Must be set together with an username. + * @param destination The destination the downloaded calendar should be saved to. + * @param maxSize The maximum size of the downloaded calendar in bytes. + * @param listener The listener that should be fired when update succeed. + */ + public PullJob(HttpClient httpClient, URI sourceURI, @Nullable String username, @Nullable String password, + File destination, int maxSize, CalendarUpdateListener listener) { + this.httpClient = httpClient; + this.sourceURI = sourceURI; + if (username != null && password != null) { + authentication = new BasicAuthentication.BasicResult(this.sourceURI, username, password); + } else { + authentication = null; + } + this.destination = destination; + this.listener = listener; + this.maxSize = maxSize; + } + + @Override + public void run() { + final Request request = httpClient.newRequest(sourceURI).followRedirects(true).method(HttpMethod.GET); + final Authentication.@Nullable Result currentAuthentication = authentication; + if (currentAuthentication != null) { + currentAuthentication.apply(request); + } + + final InputStreamResponseListener asyncListener = new InputStreamResponseListener(); + request.send(asyncListener); + + Response response; + try { + response = asyncListener.get(HTTP_TIMEOUT_SECS, TimeUnit.SECONDS); + } catch (InterruptedException | TimeoutException | ExecutionException e1) { + logger.warn("Response for calendar request could not be retrieved. Error message is: {}", e1.getMessage()); + return; + } + + if (response.getStatus() != HttpStatus.OK_200) { + logger.warn("Response status for getting \"{}\" was {} instead of 200. Ignoring it.", sourceURI, + response.getStatus()); + return; + } + + final String responseLength = response.getHeaders().get(HttpHeader.CONTENT_LENGTH); + if (responseLength != null) { + try { + if (Integer.parseInt(responseLength) > maxSize) { + logger.warn( + "Calendar is too big ({} bytes > {} bytes), aborting request. You may change the maximum calendar size in configuration, if appropriate.", + responseLength, maxSize); + response.abort(new ResponseTooBigException()); + return; + } + } catch (NumberFormatException e) { + logger.debug( + "While requesting calendar Content-Length was set, but is malformed. Falling back to read-loop.", + e); + } + } + + File tmpTargetFile; + try { + tmpTargetFile = File.createTempFile(TMP_FILE_PREFIX, null); + } catch (IOException e) { + logger.warn("Not able to create temporary file for downloading iCal. Error message is: {}", e.getMessage()); + return; + } + + try (final FileOutputStream tmpOutStream = new FileOutputStream(tmpTargetFile); + final InputStream httpInputStream = asyncListener.getInputStream()) { + final byte[] buffer = new byte[1024]; + int readBytesTotal = 0; + int currentReadBytes = -1; + while ((currentReadBytes = httpInputStream.read(buffer)) > -1) { + readBytesTotal += currentReadBytes; + if (readBytesTotal > maxSize) { + logger.warn( + "Calendar is too big (> {} bytes). Stopping receiving calendar. You may change the maximum calendar size in configuration, if appropriate.", + maxSize); + response.abort(new ResponseTooBigException()); + return; + } + tmpOutStream.write(buffer, 0, currentReadBytes); + } + } catch (IOException e) { + logger.warn("Not able to write temporary file with downloaded iCal. Error Message is: {}", e.getMessage()); + return; + } + + try (final FileInputStream tmpInput = new FileInputStream(tmpTargetFile)) { + AbstractPresentableCalendar.create(tmpInput); + } catch (IOException | CalendarException e) { + logger.warn( + "Not able to read downloaded iCal. Validation failed or file not readable. Error message is: {}", + e.getMessage()); + return; + } + + try { + Files.move(tmpTargetFile.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + logger.warn("Failed to replace iCal file. Error message is: {}", e.getMessage()); + return; + } + + try { + listener.onCalendarUpdated(); + } catch (Exception e) { + logger.debug("An Exception was thrown while calling back", e); + } + } + + /** + * Interface for calling back when the update succeed. + */ + public static interface CalendarUpdateListener { + /** + * Callback when update was successful and result was placed onto target file. + */ + public void onCalendarUpdated(); + } + + /** + * Exception for failure if size of the response is greater than allowed. + */ + private static class ResponseTooBigException extends Exception { + + /** + * The only local definition. Rest of implementation is taken from Exception or is default. + */ + private static final long serialVersionUID = 7033851403473533793L; + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/AbstractPresentableCalendar.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/AbstractPresentableCalendar.java new file mode 100644 index 0000000000000..121ea70ecec5a --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/AbstractPresentableCalendar.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.logic; + +import java.io.IOException; +import java.io.InputStream; +import java.time.Instant; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * A calendar which provides the interface to the calendar implementation for + * the binding, encapsulating the implementation of the real calendar. + * + * @author Michael Wodniok - Initial contribution + * @author Andrew Fiddian-Green - Methods getJustBegunEvents() & getJustEndedEvents() + */ +@NonNullByDefault +public abstract class AbstractPresentableCalendar { + + /** + * Creates an implementing Instance of AbstractPresentableCalendar. + * + * @param calendarStream A Stream containing the iCal data. + * @return The instance. + * @throws IOException When something while reading stream fails. + * @throws CalendarException When something while parsing fails. + */ + public static AbstractPresentableCalendar create(InputStream calendarStream) throws IOException, CalendarException { + return new BiweeklyPresentableCalendar(calendarStream); + } + + /** + * Searches the event currently (at given Instant) present. + * + * @param instant The Instant, the event should be returned for. + * @return The current {@link Event} containing the data of the event or + * null if no event is present. + */ + public abstract @Nullable Event getCurrentEvent(Instant instant); + + /** + * Return a list of events that have just begun within the time frame + * + * @param frameBegin the start of the time frame + * @param frameEnd the start of the time frame + * @return list of iCalendar Events that BEGIN within the time frame + */ + public abstract List getJustBegunEvents(Instant frameBegin, Instant frameEnd); + + /** + * Return a list of events that have just ended within the time frame + * + * @param frameBegin the start of the time frame + * @param frameEnd the start of the time frame + * @return list of iCalendar Events that END within the time frame + */ + public abstract List getJustEndedEvents(Instant frameBegin, Instant frameEnd); + + /** + * The next event after given instant. + * + * @param instant The Instant after which the next event should be + * searched. + * @return The next event after the given Instant or null if there is any + * further in the calendar. + */ + public abstract @Nullable Event getNextEvent(Instant instant); + + /** + * Checks whether an event is present at given Instant. + * + * @param instant The Instant, that should be checked. + * @return True if an event is present. + */ + public abstract boolean isEventPresent(Instant instant); +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/BiweeklyPresentableCalendar.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/BiweeklyPresentableCalendar.java new file mode 100644 index 0000000000000..895d2a48b9f4d --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/BiweeklyPresentableCalendar.java @@ -0,0 +1,313 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.logic; + +import java.io.IOException; +import java.io.InputStream; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.TimeZone; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import biweekly.ICalendar; +import biweekly.component.VEvent; +import biweekly.io.TimezoneAssignment; +import biweekly.io.TimezoneInfo; +import biweekly.io.text.ICalReader; +import biweekly.property.DateEnd; +import biweekly.property.DateStart; +import biweekly.property.Description; +import biweekly.property.DurationProperty; +import biweekly.property.Status; +import biweekly.property.Summary; +import biweekly.property.Uid; +import biweekly.util.com.google.ical.compat.javautil.DateIterator; + +/** + * Implementation of {@link AbstractPresentableCalendar} with ical4j. Please + * use {@link AbstractPresentableCalendar#create(InputStream)} for productive + * instantiation. + * + * @author Michael Wodniok - Initial contribution + * @author Andrew Fiddian-Green - Methods getJustBegunEvents() & getJustEndedEvents() + */ +@NonNullByDefault +class BiweeklyPresentableCalendar extends AbstractPresentableCalendar { + private final ICalendar usedCalendar; + + BiweeklyPresentableCalendar(InputStream streamed) throws IOException, CalendarException { + try (final ICalReader reader = new ICalReader(streamed)) { + final ICalendar currentCalendar = reader.readNext(); + if (currentCalendar == null) { + throw new CalendarException("No calendar was parsed."); + } + this.usedCalendar = currentCalendar; + } + } + + @Override + public @Nullable Event getCurrentEvent(Instant instant) { + final VEventWPeriod currentComponentWPeriod = this.getCurrentComponentWPeriod(instant); + if (currentComponentWPeriod == null) { + return null; + } + + return currentComponentWPeriod.toEvent(); + } + + @Override + public List getJustBegunEvents(Instant frameBegin, Instant frameEnd) { + final List eventList = new ArrayList<>(); + // process all the events in the iCalendar + for (final VEvent event : usedCalendar.getEvents()) { + // iterate over all begin dates + final DateIterator begDates = getRecurredEventDateIterator(event); + while (begDates.hasNext()) { + final Instant begInst = begDates.next().toInstant(); + if (begInst.isBefore(frameBegin)) { + continue; + } else if (begInst.isAfter(frameEnd)) { + break; + } + // fall through => means we are within the time frame + Duration duration = getEventLength(event); + if (duration == null) { + duration = Duration.ofMinutes(1); + } + eventList.add(new VEventWPeriod(event, begInst, begInst.plus(duration)).toEvent()); + break; + } + } + return eventList; + } + + @Override + public List getJustEndedEvents(Instant frameBegin, Instant frameEnd) { + final List eventList = new ArrayList<>(); + // process all the events in the iCalendar + for (final VEvent event : usedCalendar.getEvents()) { + final Duration duration = getEventLength(event); + if (duration == null) { + continue; + } + // iterate over all begin dates + final DateIterator begDates = getRecurredEventDateIterator(event); + while (begDates.hasNext()) { + final Instant begInst = begDates.next().toInstant(); + final Instant endInst = begInst.plus(duration); + if (endInst.isBefore(frameBegin)) { + continue; + } else if (endInst.isAfter(frameEnd)) { + break; + } + // fall through => means we are within the time frame + eventList.add(new VEventWPeriod(event, begInst, endInst).toEvent()); + break; + } + } + return eventList; + } + + @Override + public @Nullable Event getNextEvent(Instant instant) { + final Collection candidates = new ArrayList(); + final Collection negativeEvents = new ArrayList(); + final Collection positiveEvents = new ArrayList(); + classifyEvents(positiveEvents, negativeEvents); + for (final VEvent currentEvent : positiveEvents) { + final DateIterator startDates = this.getRecurredEventDateIterator(currentEvent); + final Duration duration = getEventLength(currentEvent); + if (duration == null) { + continue; + } + startDates.advanceTo(Date.from(instant)); + while (startDates.hasNext()) { + final Instant startInstant = startDates.next().toInstant(); + if (startInstant.isAfter(instant)) { + @Nullable + final Uid currentEventUid = currentEvent.getUid(); + if (currentEventUid == null || !isCounteredBy(startInstant, currentEventUid, negativeEvents)) { + candidates.add(new VEventWPeriod(currentEvent, startInstant, startInstant.plus(duration))); + break; + } + } + } + } + VEventWPeriod earliestNextEvent = null; + for (final VEventWPeriod positiveCandidate : candidates) { + if (earliestNextEvent == null || earliestNextEvent.start.isAfter(positiveCandidate.start)) { + earliestNextEvent = positiveCandidate; + } + } + + if (earliestNextEvent == null) { + return null; + } + return earliestNextEvent.toEvent(); + } + + @Override + public boolean isEventPresent(Instant instant) { + return (this.getCurrentComponentWPeriod(instant) != null); + } + + /** + * Classifies events into positive and negative ones. + * + * @param positiveEvents A List where to add positive ones. + * @param negativeEvents A List where to add negative ones. + */ + private void classifyEvents(Collection positiveEvents, Collection negativeEvents) { + for (final VEvent currentEvent : usedCalendar.getEvents()) { + @Nullable + final Status eventStatus = currentEvent.getStatus(); + boolean positive = (eventStatus == null || (eventStatus.isTentative() || eventStatus.isConfirmed())); + final Collection positiveOrNegativeEvents = (positive ? positiveEvents : negativeEvents); + positiveOrNegativeEvents.add(currentEvent); + } + } + + /** + * Searches for a current event at given Instant. + * + * @param instant The Instant to use for finding events. + * @return A VEventWPeriod describing the event or null if there is none. + */ + private @Nullable VEventWPeriod getCurrentComponentWPeriod(Instant instant) { + final List negativeEvents = new ArrayList(); + final List positiveEvents = new ArrayList(); + classifyEvents(positiveEvents, negativeEvents); + + for (final VEvent currentEvent : positiveEvents) { + final DateIterator startDates = this.getRecurredEventDateIterator(currentEvent); + final Duration duration = getEventLength(currentEvent); + if (duration == null) { + continue; + } + startDates.advanceTo(Date.from(instant.minus(duration))); + while (startDates.hasNext()) { + final Instant startInstant = startDates.next().toInstant(); + final Instant endInstant = startInstant.plus(duration); + if (startInstant.isBefore(instant) && endInstant.isAfter(instant)) { + @Nullable + final Uid eventUid = currentEvent.getUid(); + if (eventUid == null || !isCounteredBy(startInstant, eventUid, negativeEvents)) { + return new VEventWPeriod(currentEvent, startInstant, endInstant); + } + } + if (startInstant.isAfter(instant.plus(duration))) { + break; + } + } + } + + return null; + } + + /** + * Finds a duration of the event. + * + * @param vEvent The event to find out the duration. + * @return Either a Duration describing the events length or null, if no information is available. + */ + private static @Nullable Duration getEventLength(VEvent vEvent) { + final DurationProperty duration = vEvent.getDuration(); + if (duration != null) { + final biweekly.util.Duration eventDuration = duration.getValue(); + return Duration.ofMillis(eventDuration.toMillis()); + } + final DateStart start = vEvent.getDateStart(); + final DateEnd end = vEvent.getDateEnd(); + if (start == null || end == null) { + return null; + } + return Duration.between(start.getValue().toInstant(), end.getValue().toInstant()); + } + + /** + * Retrieves a DateIterator to iterate through the events occurrences. + * + * @param vEvent The VEvent to create the iterator for. + * @return The DateIterator for {@link VEvent} + */ + private DateIterator getRecurredEventDateIterator(VEvent vEvent) { + final TimezoneInfo tzinfo = this.usedCalendar.getTimezoneInfo(); + + final DateStart firstStart = vEvent.getDateStart(); + TimeZone tz; + if (tzinfo.isFloating(firstStart)) { + tz = TimeZone.getDefault(); + } else { + final TimezoneAssignment startAssignment = tzinfo.getTimezone(firstStart); + tz = (startAssignment == null ? TimeZone.getTimeZone("UTC") : startAssignment.getTimeZone()); + } + return vEvent.getDateIterator(tz); + } + + /** + * Checks whether an counter event blocks an event with given uid and start. + * + * @param startInstant The start of the event. + * @param eventUid The uid of the event. + * @param counterEvents Events that may counter. + * @return True if a counter event exists that matches uid and start, else false. + */ + private boolean isCounteredBy(Instant startInstant, Uid eventUid, Collection counterEvents) { + for (final VEvent counterEvent : counterEvents) { + @Nullable + final Uid counterEventUid = counterEvent.getUid(); + if (counterEventUid != null && eventUid.getValue().contentEquals(counterEventUid.getValue())) { + final DateIterator counterStartDates = getRecurredEventDateIterator(counterEvent); + counterStartDates.advanceTo(Date.from(startInstant)); + if (counterStartDates.hasNext()) { + final Instant counterStartInstant = counterStartDates.next().toInstant(); + if (counterStartInstant.equals(startInstant)) { + return true; + } + } + } + } + return false; + } + + /** + * A Class describing an event together with a start and end instant. + * + * @author Michael Wodniok - Initial contribution. + */ + private static class VEventWPeriod { + final VEvent vEvent; + final Instant start; + final Instant end; + + public VEventWPeriod(VEvent vEvent, Instant start, Instant end) { + this.vEvent = vEvent; + this.start = start; + this.end = end; + } + + public Event toEvent() { + final Summary eventSummary = vEvent.getSummary(); + final String title = eventSummary != null ? eventSummary.getValue() : "-"; + final Description eventDescription = vEvent.getDescription(); + final String description = eventDescription != null ? eventDescription.getValue() : ""; + return new Event(title, start, end, description); + } + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CalendarException.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CalendarException.java new file mode 100644 index 0000000000000..1e19db6b2e83b --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CalendarException.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.logic; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Exception Class to encapsulate Exception data for binding. + * + * @author Michael Wodniok - Initial contribution + */ +@NonNullByDefault +public class CalendarException extends Exception { + + private static final long serialVersionUID = -2071400154241449096L; + + public CalendarException(String message) { + super(message); + } + + public CalendarException(String message, Exception source) { + super(message, source); + } + + public CalendarException(Exception source) { + super("Implementation specific exception occurred", source); + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CommandTag.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CommandTag.java new file mode 100644 index 0000000000000..b7593d6e7d50e --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CommandTag.java @@ -0,0 +1,181 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.logic; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.HSBType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.library.types.PlayPauseType; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.types.RewindFastforwardType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.library.types.UpDownType; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.TypeParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is a class that implements a Command Tag that may be embedded in an + * Event Description. Valid Tags must follow one of the following forms.. + * + * BEGIN:: + * BEGIN::: + * END:: + * END::: + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public class CommandTag { + + private static final List> otherCommandTypes = Arrays.asList(QuantityType.class, + OnOffType.class, OpenClosedType.class, UpDownType.class, HSBType.class, PlayPauseType.class, + RewindFastforwardType.class, StringType.class); + + private static final List> percentCommandType = Arrays.asList(PercentType.class); + + private static final Logger logger = LoggerFactory.getLogger(CommandTag.class); + + private String inputLine; + private CommandTagType tagType; + private String itemName; + private String targetState; + private String authorizationCode; + private @Nullable Command theCommand; + + public CommandTag(String inputLine) throws IllegalArgumentException { + this.inputLine = inputLine.trim(); + + if (!CommandTagType.prefixValid(inputLine)) { + throw new IllegalArgumentException( + String.format("Command Tag Exception \"%s\" => Bad tag prefix!", inputLine)); + } + + if (!inputLine.contains(":")) { + throw new IllegalArgumentException( + String.format("Command Tag Exception \"%s\" => Missing \":\" delimiters!", inputLine)); + } + + String[] fields = inputLine.split(":"); + if (fields.length < 3) { + throw new IllegalArgumentException( + String.format("Command Tag Exception \"%s\" => Not enough fields!", inputLine)); + } + + if (fields.length > 4) { + throw new IllegalArgumentException( + String.format("Command Tag Exception \"%s\" => Too many fields!", inputLine)); + } + + try { + tagType = CommandTagType.valueOf(fields[0]); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException( + String.format("Command Tag Exception \"%s\" => Invalid Tag Type!", inputLine)); + } + + itemName = fields[1].trim(); + if (itemName.isEmpty()) { + throw new IllegalArgumentException( + String.format("Command Tag Exception \"%s\" => Item name empty!", inputLine)); + } + + if (!itemName.matches("^\\w+$")) { + throw new IllegalArgumentException( + String.format("Command Tag Exception \"%s\" => Bad syntax for Item name!", inputLine)); + } + + targetState = fields[2].trim(); + if (targetState.isEmpty()) { + throw new IllegalArgumentException( + String.format("Command Tag Exception \"%s\" => Target State empty!", inputLine)); + } + + // string is in double quotes => force StringType + if (targetState.startsWith("\"") && targetState.endsWith("\"")) { + // new StringType() should always succeed + theCommand = new StringType(targetState.replace("\"", "")); + } + + // string is in single quotes => ditto + else if (targetState.startsWith("'") && targetState.endsWith("'")) { + // new StringType() should always succeed + theCommand = new StringType(targetState.replace("'", "")); + } + + // string ends with % => try PercentType + else if (targetState.endsWith("%")) { + theCommand = TypeParser.parseCommand(percentCommandType, + targetState.substring(0, targetState.length() - 1)); + if (theCommand == null) { + throw new IllegalArgumentException(String + .format("Command Tag Exception \"%s\" => Invalid Target State percent value!", inputLine)); + } + } + + // try all other possible CommandTypes + if (theCommand == null) { + // TypeParser.parseCommand(otherCommandTypes should always succeed (with new StringType()) + theCommand = TypeParser.parseCommand(otherCommandTypes, targetState); + } + + if (fields.length == 4) { + authorizationCode = fields[3].trim(); + } else { + authorizationCode = ""; + } + } + + public static @Nullable CommandTag createCommandTag(String inputLine) { + if (inputLine.isEmpty() || !CommandTagType.prefixValid(inputLine)) { + logger.trace("Command Tag Trace: \"{}\" => NOT a (valid) Command Tag!", inputLine); + return null; + } + try { + final CommandTag tag = new CommandTag(inputLine); + logger.trace("Command Tag Trace: \"{}\" => Fully valid Command Tag!", inputLine); + return tag; + } catch (IllegalArgumentException e) { + logger.warn("{}", e.getMessage()); + return null; + } + } + + public @Nullable Command getCommand() { + return theCommand; + } + + public String getFullTag() { + return inputLine; + } + + public String getItemName() { + return itemName; + } + + public CommandTagType getTagType() { + return tagType; + } + + public boolean isAuthorized(@Nullable String userAuthorizationCode) { + return (userAuthorizationCode == null || userAuthorizationCode.isEmpty() + || userAuthorizationCode.equals(authorizationCode)); + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CommandTagType.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CommandTagType.java new file mode 100644 index 0000000000000..dccf680c56ebd --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/CommandTagType.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.logic; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * An type enumerator to indicate whether a Command Tag is of type BEGIN or END; as in the following examples: + * + * BEGIN:: + * END:: + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public enum CommandTagType { + BEGIN, + END; + + public static boolean prefixValid(@Nullable String line) { + return (line != null) && (line.startsWith(BEGIN.toString()) || line.startsWith(END.toString())); + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/Event.java b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/Event.java new file mode 100644 index 0000000000000..0e3863180934c --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/java/org/openhab/binding/icalendar/internal/logic/Event.java @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.logic; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * A single event. + * + * @author Michael Wodniok - Initial contribution + * @author Andrew Fiddian-Green - Added support for event description + */ +@NonNullByDefault +public class Event { + public final List commandTags = new ArrayList(); + public final Instant end; + public final Instant start; + public final String title; + + public Event(String title, Instant start, Instant end, String description) { + this.title = title; + this.start = start; + this.end = end; + + if (description.isEmpty()) { + return; + } + + String[] lines = description.replace("

", "").replace("

", "\n").split("\n"); + for (String line : lines) { + CommandTag tag = CommandTag.createCommandTag(line); + if (tag != null) { + commandTags.add(tag); + } + } + } + + @Override + public boolean equals(@Nullable Object other) { + if (other == null || other.getClass() != this.getClass()) { + return false; + } + final Event otherEvent = (Event) other; + return (this.title.equals(otherEvent.title) && this.start.equals(otherEvent.start) + && this.end.equals(otherEvent.end)); + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..702cc7e685df1 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + iCalendar Binding + Binding for using iCal calendars + Michael Wodniok + + diff --git a/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/i18n/icalendar_de_DE.properties b/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/i18n/icalendar_de_DE.properties new file mode 100644 index 0000000000000..f83ce569c0c33 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/i18n/icalendar_de_DE.properties @@ -0,0 +1,37 @@ +# binding +binding.icalendar.name = iCalendar-Binding +binding.icalendar.description = Binding zur Nutzung von iCal-Kalendern als Prsenz-Schalter. + +# thing types +thing-type.icalendar.calendar.label = Kalender +thing-type.icalendar.calendar.description = Kalender basierend auf einem lesbaren iCal-Kalender. + +# thing type config description +thing-type.config.icalendar.calendar.url.label = URL +thing-type.config.icalendar.calendar.url.description = URL des Kalenders +thing-type.config.icalendar.calendar.refreshTime.label = Aktualisierungsintervall +thing-type.config.icalendar.calendar.refreshTime.description = Intervall, in dem nach Updates im Kalender gesucht wird (Minuten) +thing-type.config.icalendar.calendar.username.label = Benutzername +thing-type.config.icalendar.calendar.username.description = Benutzername zum Abruf der Kalender-URL (fr Basic-Auth, nur sinnvoll mit gesetztem Passwort) +thing-type.config.icalendar.calendar.password.label = Passwort +thing-type.config.icalendar.calendar.password.description = Passwort zum Abruf der Kalender-URL (fr Basic-Auth, nur sinnvoll mit gesetztem Benutzername) +thing-type.config.icalendar.calendar.maxSize.label = Maximale Gre +thing-type.config.icalendar.calendar.maxSize.description = Es werden nur iCal-Dateien verwendet, die bis zur angegebenen Gre (in Mebibytes) gro sind +thing-type.config.icalendar.calendar.authorizationCode.label = Autorisierungs-Code +thing-type.config.icalendar.calendar.authorizationCode.description = Code zur Autorisierung von Kommandos in Kalendareintrgen + +# channel types +channel-type.icalendar.calendar-current_title.label = Titel des aktuellen Eintrags +channel-type.icalendar.calendar-current_title.description = Titel des aktuell prsenten Eintrags +channel-type.icalendar.calendar-current_start.label = Start des aktuellen Eintrags +channel-type.icalendar.calendar-current_start.description = Start des aktuell prsenten Eintrags +channel-type.icalendar.calendar-current_end.label = Ende des aktuellen Eintrags +channel-type.icalendar.calendar-current_end.description = Ende des aktuell prsenten Eintrags +channel-type.icalendar.calendar-current_presence.label = Prsenz eines aktuellen Eintrags +channel-type.icalendar.calendar-current_presence.description = Schalter, der die Prsenz eines aktuellen Eintrags darstellt +channel-type.icalendar.calendar-next_title.label = Titel des nchsten Eintrags +channel-type.icalendar.calendar-next_title.description = Titel des nchsten Eintrags +channel-type.icalendar.calendar-next_start.label = Start des nchsten Eintrags +channel-type.icalendar.calendar-next_start.description = Start des nchsten Eintrags +channel-type.icalendar.calendar-next_end.label = Ende des nchsten Eintrags +channel-type.icalendar.calendar-next_end.description = Ende des nchsten Eintrags diff --git a/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..7b4e615a7f360 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/main/resources/ESH-INF/thing/thing-types.xml @@ -0,0 +1,102 @@ + + + + + + Calendar based on an iCal calendar. + + + + + + + + + + + + + + + + + + + + + URL for downloading iCalendar events + url + + + + Frequency to scan for changes in minutes + + + + User name for fetching the calendar (usable in combination with password in HTTP basic auth) + + + + Password for fetching the calendar (usable in combination with user name in HTTP basic auth) + password + + + + The maximum size of the calendar in Megabytes + 16 + MB + + + + Authorization Code to allow the execution of Command Tags (may be empty) + + + + + + + String + + Title of the currently present event + + + + DateTime + + Start of the currently present event + + + + DateTime + + End of the currently present event + + + + Switch + + Current presence of an event + + + + String + + Title of the next starting event in calendar + + + + DateTime + + Start of the next event in calendar + + + + DateTime + + End of the next event in calendar + + + diff --git a/bundles/org.openhab.binding.icalendar/src/test/java/org/openhab/binding/icalendar/internal/logic/BiweeklyPresentableCalendarTest.java b/bundles/org.openhab.binding.icalendar/src/test/java/org/openhab/binding/icalendar/internal/logic/BiweeklyPresentableCalendarTest.java new file mode 100644 index 0000000000000..c40b497c6bc5b --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/test/java/org/openhab/binding/icalendar/internal/logic/BiweeklyPresentableCalendarTest.java @@ -0,0 +1,545 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.icalendar.internal.logic; + +import static org.junit.Assert.*; + +import java.io.FileInputStream; +import java.io.IOException; +import java.time.Instant; +import java.util.List; + +import org.eclipse.smarthome.core.library.types.HSBType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.library.types.PlayPauseType; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.types.RewindFastforwardType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.library.types.UpDownType; +import org.eclipse.smarthome.core.types.Command; +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for presentable calendar. + * + * @author Michael Wodniok - Initial contribution. + * + * @author Andrew Fiddian-Green - Tests for Command Tag code + * + */ +public class BiweeklyPresentableCalendarTest { + private AbstractPresentableCalendar calendar; + private AbstractPresentableCalendar calendar2; + private AbstractPresentableCalendar calendar3; + + @Before + public void setUp() throws IOException, CalendarException { + calendar = new BiweeklyPresentableCalendar(new FileInputStream("src/test/resources/test.ics")); + calendar2 = new BiweeklyPresentableCalendar(new FileInputStream("src/test/resources/test2.ics")); + calendar3 = new BiweeklyPresentableCalendar(new FileInputStream("src/test/resources/test3.ics")); + } + + /** + * Tests recurrence and whether TimeZone is interpolated in a right way. + */ + @Test + public void testIsEventPresent() { + // Test series + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-08T09:04:00Z"))); + assertTrue(calendar.isEventPresent(Instant.parse("2019-09-08T09:08:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-08T09:11:00Z"))); + + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-09T09:04:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-09T09:08:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-09T09:11:00Z"))); + + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-10T09:04:00Z"))); + assertTrue(calendar.isEventPresent(Instant.parse("2019-09-10T09:08:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-10T09:11:00Z"))); + + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-11T09:04:00Z"))); + assertTrue(calendar.isEventPresent(Instant.parse("2019-09-11T09:08:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-11T09:11:00Z"))); + + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-12T09:04:00Z"))); + assertTrue(calendar.isEventPresent(Instant.parse("2019-09-12T09:08:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-12T09:11:00Z"))); + + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-13T09:04:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-13T09:08:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-13T09:11:00Z"))); + + // Test in CEST (UTC+2) + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-14T07:59:00Z"))); + assertTrue(calendar.isEventPresent(Instant.parse("2019-09-14T08:03:00Z"))); + assertFalse(calendar.isEventPresent(Instant.parse("2019-09-14T09:01:00Z"))); + + // Test Series with cancelled event by Davdroid + assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-03T09:55:00Z"))); + assertTrue(calendar2.isEventPresent(Instant.parse("2019-11-03T10:01:00Z"))); + assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-03T13:00:00Z"))); + + assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-24T09:55:00Z"))); + assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-24T10:01:00Z"))); + assertFalse(calendar2.isEventPresent(Instant.parse("2019-11-24T13:00:00Z"))); + } + + /** + * This test relies on a working isEventPresent and assumes the calculation + * of recurrence is done the same way. + */ + @Test + public void testGetCurrentEvent() { + Event currentEvent = calendar.getCurrentEvent(Instant.parse("2019-09-10T09:07:00Z")); + assertNotNull(currentEvent); + assertTrue("Test Series in UTC".contentEquals(currentEvent.title)); + assertEquals(0, Instant.parse("2019-09-10T09:05:00Z").compareTo(currentEvent.start)); + assertEquals(0, Instant.parse("2019-09-10T09:10:00Z").compareTo(currentEvent.end)); + + Event nonExistingEvent = calendar.getCurrentEvent(Instant.parse("2019-09-09T09:07:00Z")); + assertNull(nonExistingEvent); + } + + /** + * This test relies on a working isEventPresent and assumes the calculation + * of recurrence is done the same way. + */ + @Test + public void testGetNextEvent() { + // positive case: next event of series + Event nextEventOfSeries = calendar.getNextEvent(Instant.parse("2019-09-10T09:07:00Z")); + assertNotNull(nextEventOfSeries); + assertTrue("Test Series in UTC".contentEquals(nextEventOfSeries.title)); + assertEquals(0, Instant.parse("2019-09-11T09:05:00Z").compareTo(nextEventOfSeries.start)); + assertEquals(0, Instant.parse("2019-09-11T09:10:00Z").compareTo(nextEventOfSeries.end)); + + // positive case: next event after series + Event nextEventOutsideSeries = calendar.getNextEvent(Instant.parse("2019-09-12T09:07:00Z")); + assertNotNull(nextEventOutsideSeries); + assertTrue("Test Event in UTC+2".contentEquals(nextEventOutsideSeries.title)); + assertEquals(0, Instant.parse("2019-09-14T08:00:00Z").compareTo(nextEventOutsideSeries.start)); + assertEquals(0, Instant.parse("2019-09-14T09:00:00Z").compareTo(nextEventOutsideSeries.end)); + + // positive case: next event should be also set if currently none is present + Event nextEventIndependent = calendar.getNextEvent(Instant.parse("2019-09-13T09:07:00Z")); + assertTrue(nextEventOutsideSeries.equals(nextEventIndependent)); + + // negative case: after last event there is no next + Event nonExistingEvent = calendar.getNextEvent(Instant.parse("2019-09-14T12:00:00Z")); + assertNull(nonExistingEvent); + + // mixed case: cancelled events also not show up as next + Event nextEventAfterCancelled = calendar2.getNextEvent(Instant.parse("2019-11-24T09:55:00Z")); + assertNotNull(nextEventAfterCancelled); + assertEquals(0, Instant.parse("2019-12-01T10:00:00Z").compareTo(nextEventAfterCancelled.start)); + } + + /** + * This test checks for Events that have just begun or ended, and if so it checks for Command Tags + * and checks if these tags are valid + */ + @Test + public void testCommandTagCode() { + List events = null; + int eventCount = 2; + int tagsPerEvent = 8; + + // test just begun events: first in the series + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T15:55:00Z"), + Instant.parse("2020-01-28T16:05:00Z")); + assertNotNull(events); + assertEquals(eventCount, events.size()); + for (Event event : events) { + List cmdTags = event.commandTags; + assertEquals(tagsPerEvent, cmdTags.size()); + int beginTags = 0; + for (CommandTag cmdTag : cmdTags) { + if (cmdTag.getTagType() == CommandTagType.BEGIN) { + assertTrue(cmdTag.isAuthorized("abc")); + assertTrue(cmdTag.getItemName().matches("^\\w+$")); + assertTrue(cmdTag.getCommand() != null); + beginTags++; + } + } + assertEquals(tagsPerEvent / 2, beginTags); + } + + // test just begun events: third in the series + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-30T15:55:00Z"), + Instant.parse("2020-01-30T16:05:00Z")); + assertNotNull(events); + assertEquals(eventCount, events.size()); + for (Event event : events) { + List cmdTags = event.commandTags; + assertEquals(tagsPerEvent, cmdTags.size()); + int beginTags = 0; + for (CommandTag cmdTag : cmdTags) { + if (cmdTag.getTagType() == CommandTagType.BEGIN) { + assertTrue(cmdTag.isAuthorized("abc")); + assertTrue(cmdTag.getItemName().matches("^\\w+$")); + assertTrue(cmdTag.getCommand() != null); + beginTags++; + } + } + assertEquals(tagsPerEvent / 2, beginTags); + } + + // test outside of window: begun events, too early + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T15:50:00Z"), + Instant.parse("2020-01-28T15:55:00Z")); + assertNotNull(events); + assertEquals(0, events.size()); + + // test outside of window: begun events, too late + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T16:05:00Z"), + Instant.parse("2020-01-28T16:10:00Z")); + assertNotNull(events); + assertEquals(0, events.size()); + + // test just ended events: first in the series + events = calendar3.getJustEndedEvents(Instant.parse("2020-01-28T16:25:00Z"), + Instant.parse("2020-01-28T16:35:00Z")); + assertNotNull(events); + assertEquals(eventCount, events.size()); + for (Event event : events) { + List cmdTags = event.commandTags; + assertEquals(tagsPerEvent, cmdTags.size()); + int endTags = 0; + for (CommandTag cmdTag : cmdTags) { + if (cmdTag.getTagType() == CommandTagType.END) { + assertTrue(cmdTag.isAuthorized("abc")); + assertTrue(cmdTag.getItemName().matches("^\\w+$")); + assertTrue(cmdTag.getCommand() != null); + endTags++; + } + } + assertEquals(tagsPerEvent / 2, endTags); + } + + // test outside of window: ended events, too early + events = calendar3.getJustEndedEvents(Instant.parse("2020-01-28T16:20:00Z"), + Instant.parse("2020-01-28T16:25:00Z")); + assertNotNull(events); + assertEquals(0, events.size()); + + // test outside of window: ended events, too late + events = calendar3.getJustEndedEvents(Instant.parse("2020-01-28T16:35:00Z"), + Instant.parse("2020-01-28T16:40:00Z")); + assertNotNull(events); + assertEquals(0, events.size()); + + // test a valid just begun event with both good and bad authorization codes + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T15:55:00Z"), + Instant.parse("2020-01-28T16:05:00Z")); + assertNotNull(events); + assertTrue(events.size() > 0); + List cmdTags = events.get(0).commandTags; + assertTrue(cmdTags.size() > 0); + CommandTag cmd = cmdTags.get(0); + // accept correct, empty or null configuration codes + assertTrue(cmd.isAuthorized("abc")); + assertTrue(cmd.isAuthorized("")); + assertTrue(cmd.isAuthorized(null)); + // reject incorrect configuration code + assertFalse(cmd.isAuthorized("123")); + + // test tag syntax: Test Series #1 + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T19:25:00Z"), + Instant.parse("2020-01-28T19:35:00Z")); + assertNotNull(events); + assertEquals(1, events.size()); + cmdTags = events.get(0).commandTags; + assertEquals(11, cmdTags.size()); + + // BEGIN:Calendar_Test_Color:ON:abc + assertEquals("Calendar_Test_Color", cmdTags.get(0).getItemName()); + assertTrue(cmdTags.get(0).isAuthorized("abc")); + Command cmd0 = cmdTags.get(0).getCommand(); + assertNotNull(cmd0); + assertEquals(OnOffType.class, cmd0.getClass()); + + // BEGIN:Calendar_Test_Contact:OPEN:abc + Command cmd1 = cmdTags.get(1).getCommand(); + assertNotNull(cmd1); + assertEquals(OpenClosedType.class, cmd1.getClass()); + + // BEGIN:Calendar_Test_Dimmer:ON:abc + Command cmd2 = cmdTags.get(2).getCommand(); + assertNotNull(cmd2); + assertEquals(OnOffType.class, cmd2.getClass()); + + // BEGIN:Calendar_Test_Number:12.3:abc + Command cmd3 = cmdTags.get(3).getCommand(); + assertNotNull(cmd3); + assertEquals(QuantityType.class, cmd3.getClass()); + + // BEGIN:Calendar_Test_Temperature:12.3°C:abc + Command cmd4 = cmdTags.get(4).getCommand(); + assertNotNull(cmd4); + assertEquals(QuantityType.class, cmd4.getClass()); + + // BEGIN:Calendar_Test_Pressure:12.3hPa:abc + Command cmd5 = cmdTags.get(5).getCommand(); + assertNotNull(cmd5); + assertEquals(QuantityType.class, cmd5.getClass()); + + // BEGIN:Calendar_Test_Speed:12.3m/s:abc + Command cmd6 = cmdTags.get(6).getCommand(); + assertNotNull(cmd6); + assertEquals(QuantityType.class, cmd6.getClass()); + + // BEGIN:Calendar_Test_Player:PLAY:abc + Command cmd7 = cmdTags.get(7).getCommand(); + assertNotNull(cmd7); + assertEquals(PlayPauseType.class, cmd7.getClass()); + + // BEGIN:Calendar_Test_RollerShutter:UP:abc + Command cmd8 = cmdTags.get(8).getCommand(); + assertNotNull(cmd8); + assertEquals(UpDownType.class, cmd8.getClass()); + + // BEGIN:Calendar_Test_String:Test Series #1:abc + Command cmd9 = cmdTags.get(9).getCommand(); + assertNotNull(cmd9); + assertEquals(StringType.class, cmd9.getClass()); + + // BEGIN:Calendar_Test_Switch:ON:abc + Command cmd10 = cmdTags.get(10).getCommand(); + assertNotNull(cmd10); + assertEquals(OnOffType.class, cmd10.getClass()); + + // test tag syntax: Test Series #4 + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T20:10:00Z"), + Instant.parse("2020-01-28T20:20:00Z")); + assertNotNull(events); + assertEquals(1, events.size()); + cmdTags = events.get(0).commandTags; + assertEquals(11, cmdTags.size()); + + // BEGIN:Calendar_Test_Color:0%:abc + cmd0 = cmdTags.get(0).getCommand(); + assertNotNull(cmd0); + assertEquals(PercentType.class, cmd0.getClass()); + + // BEGIN:Calendar_Test_Contact:CLOSED:abc + cmd1 = cmdTags.get(1).getCommand(); + assertNotNull(cmd1); + assertEquals(OpenClosedType.class, cmd1.getClass()); + + // BEGIN:Calendar_Test_Dimmer:0%:abc + cmd2 = cmdTags.get(2).getCommand(); + assertNotNull(cmd2); + assertEquals(PercentType.class, cmd2.getClass()); + + // BEGIN:Calendar_Test_Number:-12.3:abc + cmd3 = cmdTags.get(3).getCommand(); + assertNotNull(cmd3); + assertEquals(QuantityType.class, cmd3.getClass()); + + // BEGIN:Calendar_Test_Temperature:-12.3°C:abc + cmd4 = cmdTags.get(4).getCommand(); + assertNotNull(cmd4); + assertEquals(QuantityType.class, cmd4.getClass()); + + // BEGIN:Calendar_Test_Pressure:500mmHg:abc + cmd5 = cmdTags.get(5).getCommand(); + assertNotNull(cmd5); + assertEquals(QuantityType.class, cmd5.getClass()); + + // BEGIN:Calendar_Test_Speed:12300000mm/h:abc + cmd6 = cmdTags.get(6).getCommand(); + assertNotNull(cmd6); + assertEquals(QuantityType.class, cmd6.getClass()); + + // BEGIN:Calendar_Test_Player:REWIND:abc + cmd7 = cmdTags.get(7).getCommand(); + assertNotNull(cmd7); + assertEquals(RewindFastforwardType.class, cmd7.getClass()); + + // BEGIN:Calendar_Test_RollerShutter:100%:abc + cmd8 = cmdTags.get(8).getCommand(); + assertNotNull(cmd8); + assertEquals(PercentType.class, cmd8.getClass()); + + // BEGIN:Calendar_Test_String:Test Series #4:abc + cmd9 = cmdTags.get(9).getCommand(); + assertNotNull(cmd9); + assertEquals(StringType.class, cmd9.getClass()); + + // BEGIN:Calendar_Test_Switch:OFF:abc + cmd10 = cmdTags.get(10).getCommand(); + assertNotNull(cmd10); + assertEquals(OnOffType.class, cmd10.getClass()); + + // test tag syntax: Test Series #5 + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T20:25:00Z"), + Instant.parse("2020-01-28T20:35:00Z")); + assertNotNull(events); + assertEquals(1, events.size()); + cmdTags = events.get(0).commandTags; + assertEquals(11, cmdTags.size()); + + // BEGIN:Calendar_Test_Color:240,100,100:abc + cmd0 = cmdTags.get(0).getCommand(); + assertNotNull(cmd0); + assertEquals(HSBType.class, cmd0.getClass()); + + // BEGIN:Calendar_Test_Contact:OPEN:abc + cmd1 = cmdTags.get(1).getCommand(); + assertNotNull(cmd1); + assertEquals(OpenClosedType.class, cmd1.getClass()); + + // BEGIN:Calendar_Test_Dimmer:50%:abc + cmd2 = cmdTags.get(2).getCommand(); + assertNotNull(cmd2); + assertEquals(PercentType.class, cmd2.getClass()); + + // BEGIN:Calendar_Test_Number:-0:abc + cmd3 = cmdTags.get(3).getCommand(); + assertNotNull(cmd3); + assertEquals(QuantityType.class, cmd3.getClass()); + + // BEGIN:Calendar_Test_Temperature:0K:abc + cmd4 = cmdTags.get(4).getCommand(); + assertNotNull(cmd4); + assertEquals(QuantityType.class, cmd4.getClass()); + + // BEGIN:Calendar_Test_Pressure:12.3hPa:abc + cmd5 = cmdTags.get(5).getCommand(); + assertNotNull(cmd5); + assertEquals(QuantityType.class, cmd5.getClass()); + + // BEGIN:Calendar_Test_Speed:12.3km/h:abc + cmd6 = cmdTags.get(6).getCommand(); + assertNotNull(cmd6); + assertEquals(QuantityType.class, cmd6.getClass()); + + // BEGIN:Calendar_Test_Player:PLAY:abc + cmd7 = cmdTags.get(7).getCommand(); + assertNotNull(cmd7); + assertEquals(PlayPauseType.class, cmd7.getClass()); + + // BEGIN:Calendar_Test_RollerShutter:50%:abc + cmd8 = cmdTags.get(8).getCommand(); + assertNotNull(cmd8); + assertEquals(PercentType.class, cmd8.getClass()); + + // BEGIN:Calendar_Test_String:Test Series #5:abc + cmd9 = cmdTags.get(9).getCommand(); + assertNotNull(cmd9); + assertEquals(StringType.class, cmd9.getClass()); + + // BEGIN:Calendar_Test_Switch:ON:abc + cmd10 = cmdTags.get(10).getCommand(); + assertNotNull(cmd10); + assertEquals(OnOffType.class, cmd10.getClass()); + + // test bad command tag syntax: Test Series #6 + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T20:40:00Z"), + Instant.parse("2020-01-28T20:50:00Z")); + assertNotNull(events); + assertEquals(1, events.size()); + cmdTags = events.get(0).commandTags; + // Test Series #6 contains only "bad" command tags as follows.. + + // tags with wrong case prefix.. + // begin + // Begin + // BEGIn + + // tags that are missing ":" field delimiters.. + // BEGIN + + // tags with too few field delimiters.. + // BEGIN:www + + // tags with too many field delimiters.. + // BEGIN:www:xxx:yyy:zzz + + // tags with an invalid prefix.. + // BEGINX:xxx:yyy:zzz + // ENDX:xxx:yyy:zzz + // BEGIN :xxx:yyy:zzz + // BEGIN :xxx:yyy:zzz + + // tags with an empty Item Name + // BEGIN::yyy:zzz + // BEGIN: :yyy:zzz + // BEGIN: :yyy:zzz + + // tags with bad Item Name + // BEGIN:!:yyy:zzz + // BEGIN:@:yyy:zzz + // BEGIN:£:yyy:zzz + + // tags with an empty Target State value + // BEGIN:xxx::zzz + // BEGIN:xxx: :zzz + // BEGIN:xxx: :zzz + + // Note: All of the above tags must be rejected! => Assert cmdTags.size() == 0 ! + + assertEquals(0, cmdTags.size()); + + // test HTML command tag syntax: Test Series #7 + events = calendar3.getJustBegunEvents(Instant.parse("2020-01-28T20:55:00Z"), + Instant.parse("2020-01-28T21:05:00Z")); + assertNotNull(events); + assertEquals(1, events.size()); + cmdTags = events.get(0).commandTags; + assertEquals(8, cmdTags.size()); + + //

BEGIN:Calendar_Test_Temperature:12.3°C:abc

+ cmd0 = cmdTags.get(0).getCommand(); + assertNotNull(cmd0); + assertEquals(QuantityType.class, cmd0.getClass()); + + //

END:Calendar_Test_Temperature:23.4°C:abc

+ cmd1 = cmdTags.get(1).getCommand(); + assertNotNull(cmd1); + assertEquals(QuantityType.class, cmd1.getClass()); + + //

BEGIN:Calendar_Test_Switch:ON:abc

+ cmd2 = cmdTags.get(2).getCommand(); + assertNotNull(cmd2); + assertEquals(OnOffType.class, cmd2.getClass()); + + //

END:Calendar_Test_Switch:OFF:abc

+ cmd3 = cmdTags.get(3).getCommand(); + assertNotNull(cmd3); + assertEquals(OnOffType.class, cmd3.getClass()); + + //

BEGIN:Calendar_Test_String:the quick:abc

+ cmd4 = cmdTags.get(4).getCommand(); + assertNotNull(cmd4); + assertEquals(StringType.class, cmd4.getClass()); + + //

END:Calendar_Test_String:brown fox:abc

+ cmd5 = cmdTags.get(5).getCommand(); + assertNotNull(cmd5); + assertEquals(StringType.class, cmd5.getClass()); + + //

BEGIN:Calendar_Test_Number:12.3:abc

+ cmd6 = cmdTags.get(6).getCommand(); + assertNotNull(cmd6); + assertEquals(QuantityType.class, cmd6.getClass()); + + //

END:Calendar_Test_Number:23.4:abc

+ cmd7 = cmdTags.get(7).getCommand(); + assertNotNull(cmd7); + assertEquals(QuantityType.class, cmd7.getClass()); + } +} diff --git a/bundles/org.openhab.binding.icalendar/src/test/resources/test.ics b/bundles/org.openhab.binding.icalendar/src/test/resources/test.ics new file mode 100644 index 0000000000000..f8affe98d1357 --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/test/resources/test.ics @@ -0,0 +1,45 @@ +BEGIN:VCALENDAR +PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN +VERSION:2.0 +BEGIN:VTIMEZONE +TZID:Europe/Berlin +BEGIN:DAYLIGHT +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +DTSTART:19700329T020000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:CET +DTSTART:19701025T030000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +CREATED:20190908T072348Z +LAST-MODIFIED:20190908T072425Z +DTSTAMP:20190908T072425Z +UID:2aefe156-ef9c-4c5e-a9bd-1c0f23174d4a +SUMMARY:Test Event in UTC+2 +DTSTART;TZID=Europe/Berlin:20190914T100000 +DTEND;TZID=Europe/Berlin:20190914T110000 +TRANSP:OPAQUE +END:VEVENT +BEGIN:VEVENT +CREATED:20190908T072100Z +LAST-MODIFIED:20190908T072329Z +DTSTAMP:20190908T072329Z +UID:dafba377-5b10-4edc-b536-b2f93677279d +SUMMARY:Test Series in UTC +RRULE:FREQ=DAILY;COUNT=5 +EXDATE:20190909T090500Z +DTSTART:20190908T090500Z +DTEND:20190908T091000Z +TRANSP:OPAQUE +SEQUENCE:1 +X-MOZ-GENERATION:1 +END:VEVENT +END:VCALENDAR diff --git a/bundles/org.openhab.binding.icalendar/src/test/resources/test2.ics b/bundles/org.openhab.binding.icalendar/src/test/resources/test2.ics new file mode 100644 index 0000000000000..d436583c657ad --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/test/resources/test2.ics @@ -0,0 +1,125 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:+//IDN bitfire.at//DAVx5/2.2.3.1-ose ical4j/2.2.3 +BEGIN:VTIMEZONE +TZID:Europe/Berlin +TZURL:http://tzurl.org/zoneinfo/Europe/Berlin +X-LIC-LOCATION:Europe/Berlin +BEGIN:DAYLIGHT +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +DTSTART:19810329T020000 +RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU +END:DAYLIGHT +BEGIN:DAYLIGHT +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +TZNAME:CEST +DTSTART:19160430T230000 +RDATE:19160430T230000 +RDATE:19170416T020000 +RDATE:19180415T020000 +RDATE:19400401T020000 +RDATE:19430329T020000 +RDATE:19440403T020000 +RDATE:19450402T020000 +RDATE:19460414T020000 +RDATE:19470406T030000 +RDATE:19480418T020000 +RDATE:19490410T020000 +RDATE:19800406T020000 +END:DAYLIGHT +BEGIN:DAYLIGHT +TZOFFSETFROM:+0200 +TZOFFSETTO:+0300 +TZNAME:CEMT +DTSTART:19450524T010000 +RDATE:19450524T010000 +RDATE:19470511T020000 +END:DAYLIGHT +BEGIN:DAYLIGHT +TZOFFSETFROM:+0300 +TZOFFSETTO:+0200 +TZNAME:CEST +DTSTART:19450924T030000 +RDATE:19450924T030000 +RDATE:19470629T030000 +END:DAYLIGHT +BEGIN:STANDARD +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:CET +DTSTART:19961027T030000 +RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU +END:STANDARD +BEGIN:STANDARD +TZOFFSETFROM:+005328 +TZOFFSETTO:+0100 +TZNAME:CET +DTSTART:18930401T000000 +RDATE:18930401T000000 +END:STANDARD +BEGIN:STANDARD +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +TZNAME:CET +DTSTART:19161001T010000 +RDATE:19161001T010000 +RDATE:19170917T030000 +RDATE:19180916T030000 +RDATE:19421102T030000 +RDATE:19431004T030000 +RDATE:19441002T030000 +RDATE:19451118T030000 +RDATE:19461007T030000 +RDATE:19471005T030000 +RDATE:19481003T030000 +RDATE:19491002T030000 +RDATE:19800928T030000 +RDATE:19810927T030000 +RDATE:19820926T030000 +RDATE:19830925T030000 +RDATE:19840930T030000 +RDATE:19850929T030000 +RDATE:19860928T030000 +RDATE:19870927T030000 +RDATE:19880925T030000 +RDATE:19890924T030000 +RDATE:19900930T030000 +RDATE:19910929T030000 +RDATE:19920927T030000 +RDATE:19930926T030000 +RDATE:19940925T030000 +RDATE:19950924T030000 +END:STANDARD +BEGIN:STANDARD +TZOFFSETFROM:+0100 +TZOFFSETTO:+0100 +TZNAME:CET +DTSTART:19460101T000000 +RDATE:19460101T000000 +RDATE:19800101T000000 +END:STANDARD +END:VTIMEZONE +BEGIN:VEVENT +DTSTAMP:20191123T214104Z +UID:2bcc7543-27c8-4519-96af-d932fb9a9067 +SEQUENCE:3 +SUMMARY:Evt +DTSTART;TZID=Europe/Berlin:20190915T110000 +DURATION:PT6300S +RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU +STATUS:CONFIRMED +END:VEVENT +BEGIN:VEVENT +DTSTAMP:20191123T214104Z +UID:2bcc7543-27c8-4519-96af-d932fb9a9067 +RECURRENCE-ID:20191124T100000Z +SEQUENCE:1 +SUMMARY:Evt +DTSTART;TZID=Europe/Berlin:20191124T110000 +DTEND;TZID=Europe/Berlin:20191124T124500 +STATUS:CANCELLED +END:VEVENT +END:VCALENDAR diff --git a/bundles/org.openhab.binding.icalendar/src/test/resources/test3.ics b/bundles/org.openhab.binding.icalendar/src/test/resources/test3.ics new file mode 100644 index 0000000000000..15ef73682daca --- /dev/null +++ b/bundles/org.openhab.binding.icalendar/src/test/resources/test3.ics @@ -0,0 +1,5033 @@ +BEGIN:VCALENDAR +PRODID:-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN +VERSION:2.0 +METHOD:PUBLISH +X-CALSTART:20200128T160000Z +X-CALEND:20200421T153000Z +X-WR-RELCALID:{0000002E-56AD-5AD9-A42B-47B1E6C79BAB} +X-WR-CALNAME:iCalendar Test Calendar (1) +BEGIN:VTIMEZONE +TZID:GMT Standard Time +BEGIN:STANDARD +DTSTART:16011028T020000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 +TZOFFSETFROM:+0100 +TZOFFSETTO:-0000 +END:STANDARD +BEGIN:DAYLIGHT +DTSTART:16010325T010000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 +TZOFFSETFROM:-0000 +TZOFFSETTO:+0100 +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191653Z +DESCRIPTION:BEGIN:Calendar_Test_Temperature:12.3°C:abc\nEND:Calendar_Test_ + Temperature:23.4°C:abc\n \nBEGIN:Calendar_Test_Switch:ON:abc\nEND:Calenda + r_Test_Switch:OFF:abc\n \nBEGIN:Calendar_Test_String:the quick:abc\nEND:Ca + lendar_Test_String:brown fox:abc\n \nBEGIN:Calendar_Test_Number:12.3:abc\n + END:Calendar_Test_Number:23.4:abc\n \nThe quick brown fox jumps over the l + azy dog. The quick brown fox jumps over the lazy dog. The quick brown fox + jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The + quick brown fox jumps over the lazy dog. The quick brown fox jumps over th + e lazy dog. The quick brown fox jumps over the lazy dog. The quick brown f + ox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. T + he quick brown fox jumps over the lazy dog. The quick brown fox jumps over + the lazy dog. The quick brown fox jumps over the lazy dog.\n +DTEND;TZID="GMT Standard Time":20200128T163000 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T160000 +LAST-MODIFIED:20200407T001726Z +LOCATION:Scotland +PRIORITY:5 +RRULE:FREQ=DAILY;COUNT=85 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Aardvark +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E0080000000050105A02C8D5D501000000000000000 + 01000000085D53E516988C747AE33805186E3A047 +X-ALT-DESC;FMTTYPE=text/html:< + !--[if gte mso 9]>\n\n110\nClean\n\n\n\n\n\nfalse\nfalse\nfalse\n\nEN-GB\nX-NONE\nX-N + ONE\n\n\ + n\n\n\n< + w:DontGrowAutofit/>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n< + m:naryLim m:val="undOvr"/>\n\n

BEGIN:Calendar_Test_Temperature:12.3 + °C:abc

END:Calendar_Test_Temperature:23. + 4°C:abc

 \;

BEGIN:Calendar_Test_Switch:ON:abc< + /o:p>

END:Calendar_Test_Switch:OF + F:abc

 \;

BEGIN:Calendar_Test_String:the quick:abc

END:Calendar_Test_String:brown fox:abc +

 \;

BEGIN:Calendar_Test_Number:12.3:abc

END:Calendar_Test_Number:23.4:abc

 \;

The quick brown fox jumps over the la + zy dog. The quick brown fox jumps over the lazy dog. The quick brown fox j + umps over the lazy dog. The quick brown fox jumps over the lazy dog. The q + uick brown fox jumps over the lazy dog. The quick brown fox jumps over the + lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fo + x jumps over the lazy dog. The quick brown fox jumps over the lazy dog. Th + e quick brown fox jumps over the lazy dog. The quick brown fox jumps over + the lazy dog. The quick brown fox jumps over the lazy dog.

< + /div> +X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-AUTOFILLLOCATION:FALSE +X-MS-OLK-CONFTYPE:0 +BEGIN:VALARM +TRIGGER:-PT15M +ACTION:DISPLAY +DESCRIPTION:Reminder +END:VALARM +END:VEVENT +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191653Z +DESCRIPTION:BEGIN:Calendar_Test_Temperature:12.3°C:abc\nEND:Calendar_Test_ + Temperature:23.4°C:abc\n \nBEGIN:Calendar_Test_Switch:ON:abc\nEND:Calenda + r_Test_Switch:OFF:abc\n \nBEGIN:Calendar_Test_String:the quick:abc\nEND:Ca + lendar_Test_String:brown fox:abc\n \nBEGIN:Calendar_Test_Number:12.3:abc\n + END:Calendar_Test_Number:23.4:abc\n \nThe quick brown fox jumps over the l + azy dog. The quick brown fox jumps over the lazy dog. The quick brown fox + jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The + quick brown fox jumps over the lazy dog. The quick brown fox jumps over th + e lazy dog. The quick brown fox jumps over the lazy dog. The quick brown f + ox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. T + he quick brown fox jumps over the lazy dog. The quick brown fox jumps over + the lazy dog. The quick brown fox jumps over the lazy dog.\n +DTEND;TZID="GMT Standard Time":20200128T163000 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T160000 +LAST-MODIFIED:20200407T001726Z +LOCATION:Italy +PRIORITY:5 +RRULE:FREQ=DAILY;COUNT=85 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Alligator +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E00800000000A05B491DC8D5D501000000000000000 + 010000000D63114DF6CFE104FB71C4A55E48C9634 +X-ALT-DESC;FMTTYPE=text/html:< + !--[if gte mso 9]>\n\n110\nClean\n\n\n\n\n\nfalse\nfalse\nfalse\n\nEN-GB\nX-NONE\nX-N + ONE\n\n\ + n\n\n\n< + w:DontGrowAutofit/>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n< + m:naryLim m:val="undOvr"/>\n\n

BEGIN:Calendar_Test_Temperature:12.3 + °C:abc

END:Calendar_Test_Temperature:23. + 4°C:abc

 \;

BEGIN:Calendar_Test_Switch:ON:abc< + /o:p>

END:Calendar_Test_Switch:OF + F:abc

 \;

BEGIN:Calendar_Test_String:the quick:abc

END:Calendar_Test_String:brown fox:abc +

 \;

BEGIN:Calendar_Test_Number:12.3:abc

END:Calendar_Test_Number:23.4:abc

 \;

The quick brown fox jumps over the la + zy dog. The quick brown fox jumps over the lazy dog. The quick brown fox j + umps over the lazy dog. The quick brown fox jumps over the lazy dog. The q + uick brown fox jumps over the lazy dog. The quick brown fox jumps over the + lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fo + x jumps over the lazy dog. The quick brown fox jumps over the lazy dog. Th + e quick brown fox jumps over the lazy dog. The quick brown fox jumps over + the lazy dog. The quick brown fox jumps over the lazy dog.

< + /div> +X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-AUTOFILLLOCATION:FALSE +X-MS-OLK-CONFTYPE:0 +BEGIN:VALARM +TRIGGER:-PT15M +ACTION:DISPLAY +DESCRIPTION:Reminder +END:VALARM +END:VEVENT +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191653Z +DESCRIPTION:BEGIN:Calendar_Test_Color:ON:abc\nBEGIN:Calendar_Test_Contact:O + PEN:abc\nBEGIN:Calendar_Test_Dimmer:ON:abc \nBEGIN:Calendar_Test_Number:12 + .3:abc\nBEGIN:Calendar_Test_Temperature:12.3°C:abc\nBEGIN:Calendar_Test_P + ressure:12.3hPa:abc\nBEGIN:Calendar_Test_Speed:12.3m/s:abc\nBEGIN:Calendar + _Test_Player:PLAY:abc\nBEGIN:Calendar_Test_RollerShutter:UP:abc\nBEGIN:Cal + endar_Test_String:Test Series #1:abc\nBEGIN:Calendar_Test_Switch:ON:abc\n + \n +DTEND;TZID="GMT Standard Time":20200128T194500 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T193000 +LAST-MODIFIED:20200406T191654Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Test Series: 1 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E00800000000300521B5D8D5D501000000000000000 + 010000000A1A1CDA7921D424E95F8279245885818 +X-ALT-DESC;FMTTYPE=text/html:

BEGIN:Calendar_Test_Color:ON:abc

BEGIN:Calendar_Test_Contact:OPEN:abc

BEGIN:Calendar_Test_Dimmer:ON + :abc

BEGIN:Calendar_Test_Number:1 + 2.3:abc

BEGIN:Calendar_Test_Temperature:1 + 2.3°C:abc

BEGIN:Calendar_Test_Pressure:1 + 2.3hPa:abc

BEGIN:Calendar_Test_Speed:12.3 + m/s:abc

BEGIN:Calendar_Test_Player:PLAY:abc

BEGIN:Calendar_Test_RollerShutter:UP:abc< + /span>

BEGIN:Calendar_ + Test_String:Test Series #1:abc

BEGIN:Calendar_Test_Switch:ON:abc

 \;

+X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +END:VEVENT +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191654Z +DESCRIPTION:BEGIN:Calendar_Test_Color:OFF:abc\nBEGIN:Calendar_Test_Contact: + CLOSED:abc\nBEGIN:Calendar_Test_Dimmer:OFF:abc\nBEGIN:Calendar_Test_Number + :0:abc\nBEGIN:Calendar_Test_Temperature:300.3K:abc\nBEGIN:Calendar_Test_Pr + essure:12.3bar:abc\nBEGIN:Calendar_Test_Speed:12.3km/h:abc\nBEGIN:Calendar + _Test_Player:PAUSE:abc\nBEGIN:Calendar_Test_RollerShutter:DOWN:abc\nBEGIN: + Calendar_Test_String:"Test Series #2":abc\nBEGIN:Calendar_Test_Switch:OFF: + abc\n \n +DTEND;TZID="GMT Standard Time":20200128T200000 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T194500 +LAST-MODIFIED:20200406T191659Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Test Series: 2 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E0080000000060C34DBDD8D5D501000000000000000 + 010000000A1A1CDA7921D424E95F8279245885818 +X-ALT-DESC;FMTTYPE=text/html:

BEGIN:Calendar_Test_Color:OFF:abc

BEGIN:Calendar_Test_Contact:CLOSED:abc +

BEGIN:Calendar_Test_Dimmer + :OFF:abc

BEGIN:Calendar_Test_Numbe + r:0:abc

BEGIN:Calendar_Test_Temperature:3 + 00.3K:abc

BEGIN:Calendar_Test_Pressure:12 + .3bar:abc

BEGIN:Calendar_Test_Speed:12.3k + m/h:abc

BEGIN:Calendar_Test_Player:PAUSE:abc

BEGIN:Calendar_Test_RollerShutter:DOWN:a + bc

BEGIN:Calend + ar_Test_String:"\;Test Series #2"\;:abc

BEGIN:Calendar_Test_Switch:OFF:abc +

 \;

+X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +END:VEVENT +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191654Z +DESCRIPTION:BEGIN:Calendar_Test_Color:100%:abc\nBEGIN:Calendar_Test_Contact + :OPEN:abc\nBEGIN:Calendar_Test_Dimmer:100%:abc\nBEGIN:Calendar_Test_Number + :1:abc\nBEGIN:Calendar_Test_Temperature:62.3°F:abc\nBEGIN:Calendar_Test_P + ressure:12.3mbar:abc\nBEGIN:Calendar_Test_Speed:12.3mph:abc\nBEGIN:Calenda + r_Test_Player:FASTFORWARD:abc\nBEGIN:Calendar_Test_RollerShutter:0%:abc\nB + EGIN:Calendar_Test_String:'Test Series #3':abc\nBEGIN:Calendar_Test_Switch + :ON:abc\n +DTEND;TZID="GMT Standard Time":20200128T201500 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T200000 +LAST-MODIFIED:20200406T191700Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Test Series: 3 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E00800000000703B73BFD8D5D501000000000000000 + 010000000A1A1CDA7921D424E95F8279245885818 +X-ALT-DESC;FMTTYPE=text/html:

BEGIN:Calendar_Test_Color:100%:abc< + o:p>

BEGIN:Calendar_Test_Co + ntact:OPEN:abc

BEGIN:Calendar_Test + _Dimmer:100%:abc

BEGIN:Calendar_Test_Number:1:abc

BEGIN: + Calendar_Test_Temperature:62.3°F:abc

BEG + IN:Calendar_Test_Pressure:12.3mbar:abc

BE + GIN:Calendar_Test_Speed:12.3mph:abc

BEGIN:Calendar_Test_Player:FASTFORWARD:abc +

BEGIN:Calendar_Test_RollerShutter:0%:abc

BEGIN: + Calendar_Test_String:'Test Series #3':abc

BEGIN:Calendar_Test_Switch:ON:abc

+X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +END:VEVENT +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191654Z +DESCRIPTION:BEGIN:Calendar_Test_Color:0%:abc\nBEGIN:Calendar_Test_Contact:C + LOSED:abc\nBEGIN:Calendar_Test_Dimmer:0%:abc\nBEGIN:Calendar_Test_Number:- + 12.3:abc\nBEGIN:Calendar_Test_Temperature:-12.3°C:abc\nBEGIN:Calendar_Tes + t_Pressure:500mmHg:abc\nBEGIN:Calendar_Test_Speed:12300000mm/h:abc\nBEGIN: + Calendar_Test_Player:REWIND:abc\nBEGIN:Calendar_Test_RollerShutter:100%:ab + c\nBEGIN:Calendar_Test_String:Test Series #4:abc\nBEGIN:Calendar_Test_Swit + ch:OFF:abc\n \n +DTEND;TZID="GMT Standard Time":20200128T203000 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T201500 +LAST-MODIFIED:20200406T191700Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Test Series: 4 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E008000000002033B0C1D8D5D501000000000000000 + 010000000A1A1CDA7921D424E95F8279245885818 +X-ALT-DESC;FMTTYPE=text/html:

BEGIN:Calendar + _Test_Color:0%:abc

BEGIN:Calendar_Test_Contact:CLOSED:abc< + /o:p>

BEGIN:Calendar_Test_Dimmer:0%:abc

BEGIN:Ca + lendar_Test_Number:-12.3:abc

BEGIN:Calendar_Test_Temperature:-12.3°C:abc

BEGIN:Calendar_Test_Pressure:500mmHg:abc

BEGIN:Calendar_Test_Speed:12300000mm/h:abc

BE + GIN:Calendar_Test_Player:REWIND:abc

BEGIN:Calendar_Test_RollerShutter:100%:abc

BEGIN:Calendar_Test_Strin + g:Test Series #4:abc

BEGIN:Calendar_Test_Switch:OFF:abc

 \;

+X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +END:VEVENT +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191655Z +DESCRIPTION:BEGIN:Calendar_Test_Color:240\,100\,100:abc\nBEGIN:Calendar_Tes + t_Contact:OPEN:abc\nBEGIN:Calendar_Test_Dimmer:50%:abc\nBEGIN:Calendar_Tes + t_Number:-0:abc\nBEGIN:Calendar_Test_Temperature:0K:abc\nBEGIN:Calendar_Te + st_Pressure:12.3hPa:abc\nBEGIN:Calendar_Test_Speed:12.3km/h:abc\nBEGIN:Cal + endar_Test_Player:PLAY:abc\nBEGIN:Calendar_Test_RollerShutter:50%:abc\nBEG + IN:Calendar_Test_String:Test Series #5:abc\nBEGIN:Calendar_Test_Switch:ON: + abc\n \n +DTEND;TZID="GMT Standard Time":20200128T204500 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T203000 +LAST-MODIFIED:20200406T191700Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Test Series: 5 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E00800000000F07FD7C3D8D5D501000000000000000 + 010000000A1A1CDA7921D424E95F8279245885818 +X-ALT-DESC;FMTTYPE=text/html:

BEGIN:Calendar + _Test_Color:240\,100\,100:abc

BEGIN:Calendar_Test_Contact:OPEN:abc

BEGIN:Calendar_Test_Dimmer:50%:abc

BEGIN:Calendar_Test_Numb + er:-0:abc

BEGIN:Calendar_Test_Temp + erature:0K:abc

BEGIN:Calendar_Test_Pressu + re:12.3hPa:abc

BEGIN:Calendar_Test_Speed: + 12.3km/h:abc

BEGIN:Calendar_Test_Player:PLAY:abc

+

BEGIN:Calendar_Test_RollerShutter:50%:abc

BEGIN:Cal + endar_Test_String:Test Series #5:abc

BEGIN:Calendar_Test_Switch:ON:abc< + /p>

 \;

+X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +END:VEVENT +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191655Z +DESCRIPTION:Wrong case prefix..\nbegin\nBegin\nBEGIn\n \nMissing : delimite + rs..\nBEGIN\n \nToo few delimiter fields..\nBEGIN:www\n \nToo many delimit + er fields..\nBEGIN:www:xxx:yyy:zzz\n \nInvalid prefix..\nBEGINX:xxx:yyy:zz + z\nENDX:xxx:yyy:zzz\nBEGIN :xxx:yyy:zzz\nBEGIN :xxx:yyy:zzz\n \nEmpty it + em name \nBEGIN::yyy:zzz\nBEGIN: :yyy:zzz\nBEGIN: :yyy:zzz\n \nBad item n + ame \nBEGIN:!:yyy:zzz\nBEGIN:@:yyy:zzz\nBEGIN:£:yyy:zzz\n \nEmpty target + state value\nBEGIN:xxx::zzz\nBEGIN:xxx: :zzz\nBEGIN:xxx: :zzz\n \ + nBad percent type target state value\nBEGIN:xxx:%:zzz\nBEGIN:xxx:a1%:zzz\n + \n +DTEND;TZID="GMT Standard Time":20200128T210000 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T204500 +LAST-MODIFIED:20200407T121933Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Test Series: 6 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E00800000000200784EA260CD601000000000000000 + 010000000C72EE95F973E004FBB2A8623BFB2933B +X-ALT-DESC;FMTTYPE=text/html:

Wrong case pre + fix..

begin

Begin

BEGIn +

 \;

Missing : delimiters..

BEGIN< + /p>

 \;

Too few del + imiter fields..

BEGIN: + www

 \;

Too many delimiter fields..

BEGIN:www:xxx:yyy:zzz

 \;

Invalid prefix..< + /p>

BEGINX:xxx:yyy:zzz

ENDX:xxx:yyy:zzz< + /o:p>

BEGIN :xxx:yyy:zzz

BEGIN   :xxx:yyy:zzz

 \;

Empty item name

BEGIN::yyy:zzz

BEGIN: :yyy:zzz

BEGIN:  :yyy:zzz

 \;< + /o:p>

Bad item name

BEGIN:!:yyy:zzz

BEGIN:@:yyy:zzz

BEGIN:£:yyy:zzz

 \;

Empty target state value

BEGIN:xxx::zzz

BEGIN:xxx: :zzz

BEGIN:xxx:          :zzz

< + p class=MsoNormal> \;

Bad percent typ + e target state value

B + EGIN:xxx:%:zzz

BEGIN:xxx:a1%:zzz

 \;

+X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +END:VEVENT +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20200406T191656Z +DESCRIPTION:

BEGIN:Calendar_Test_Temperature:12.3°C:abc

END:Calend + ar_Test_Temperature:23.4°C:abc

 \;

BEGIN:Calendar_Test_Sw + itch:ON:abc

END:Calendar_Test_Switch:OFF:abc

 \;

BEG + IN:Calendar_Test_String:the quick:abc

END:Calendar_Test_String:brown + fox:abc

 \;

BEGIN:Calendar_Test_Number:12.3:abc

END + :Calendar_Test_Number:23.4:abc

\n \n +DTEND;TZID="GMT Standard Time":20200128T211500 +DTSTAMP:20200128T124950Z +DTSTART;TZID="GMT Standard Time":20200128T210000 +LAST-MODIFIED:20200406T191700Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Test Series: 7 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E0080000000050E42233500CD601000000000000000 + 010000000E08D1158F365874D8251F8BA740D2CFB +X-ALT-DESC;FMTTYPE=text/html: +

<\;p>\;BEGIN:Calendar_Test_Temperature + :12.3°C:abc<\;/p>\;<\;p>\;END:Calendar_Test_Temperature:23.4°C:a + bc<\;/p>\;<\;p>\;&\;nbsp\;<\;/p>\;<\;p>\;BEGIN:Calendar + _Test_Switch:ON:abc<\;/p>\;<\;p>\;END:Calendar_Test_Switch:OFF:abc + <\;/p>\;<\;p>\;&\;nbsp\;<\;/p>\;<\;p>\;BEGIN:Calendar_T + est_String:the quick:abc<\;/p>\;<\;p>\;< + span class=SpellE>END:Calendar_Test_String:brown fox:abc<\;/p>\ + ;<\;p>\;&\;nbsp\;<\;/p>\;<\;p>\;BEGIN:Calendar_Test_Number: + 12.3:abc<\;/p>\;<\;p>\;END:Calendar_Test_Number:23.4:abc<\;/p> + \;

 \;

+X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +END:VEVENT +END:VCALENDAR diff --git a/bundles/org.openhab.binding.icloud/pom.xml b/bundles/org.openhab.binding.icloud/pom.xml index 06b9e0505cffd..d04ddeb6b92a6 100644 --- a/bundles/org.openhab.binding.icloud/pom.xml +++ b/bundles/org.openhab.binding.icloud/pom.xml @@ -1,10 +1,12 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.icloud diff --git a/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/ICloudHandlerFactory.java b/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/ICloudHandlerFactory.java index f2aee2925b6c1..9e4989ff75e6d 100644 --- a/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/ICloudHandlerFactory.java +++ b/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/ICloudHandlerFactory.java @@ -115,5 +115,4 @@ public void setTranslationProvider(TranslationProvider i18nProvider) { public void unsetTranslationProvider(TranslationProvider i18nProvider) { this.i18nProvider = null; } - } diff --git a/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/handler/ICloudDeviceHandler.java b/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/handler/ICloudDeviceHandler.java index e8465eddf291c..519c651fb1168 100644 --- a/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/handler/ICloudDeviceHandler.java +++ b/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/handler/ICloudDeviceHandler.java @@ -128,7 +128,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { if (command == OnOffType.ON) { try { final String deviceId = this.deviceId; - if(deviceId == null) { + if (deviceId == null) { logger.debug("Can't send Find My Device request, because deviceId is null!"); return; } diff --git a/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/utilities/ICloudTextTranslator.java b/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/utilities/ICloudTextTranslator.java index 921427f11ed0a..b86a00d4b2f77 100644 --- a/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/utilities/ICloudTextTranslator.java +++ b/bundles/org.openhab.binding.icloud/src/main/java/org/openhab/binding/icloud/internal/utilities/ICloudTextTranslator.java @@ -44,5 +44,4 @@ public String getText(String key, Object... arguments) { public String getDefaultText(@Nullable String key) { return i18nProvider.getText(bundle, key, key, Locale.ENGLISH); } - } diff --git a/bundles/org.openhab.binding.icloud/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.icloud/src/main/resources/ESH-INF/thing/thing-types.xml index 9920c50725534..be950bed36ff4 100644 --- a/bundles/org.openhab.binding.icloud/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.icloud/src/main/resources/ESH-INF/thing/thing-types.xml @@ -28,20 +28,20 @@ - + @text/icloud.device-thing.description - - - - - - - + + + + + + + deviceId @@ -73,16 +73,16 @@ Location - + Number - + DateTime - + diff --git a/bundles/org.openhab.binding.ihc/pom.xml b/bundles/org.openhab.binding.ihc/pom.xml index bd10c3e5ad4f1..17f9ee40f4326 100644 --- a/bundles/org.openhab.binding.ihc/pom.xml +++ b/bundles/org.openhab.binding.ihc/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.ihc diff --git a/bundles/org.openhab.binding.ihc/src/main/feature/feature.xml b/bundles/org.openhab.binding.ihc/src/main/feature/feature.xml index f6264e77a53d3..5554903f4f1cd 100644 --- a/bundles/org.openhab.binding.ihc/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.ihc/src/main/feature/feature.xml @@ -1,12 +1,12 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.apache.httpcomponents/httpcore-osgi/4.4.10 - mvn:org.apache.httpcomponents/httpclient-osgi/4.5.8 - mvn:commons-logging/commons-logging/1.2 - mvn:org.openhab.addons.bundles/org.openhab.binding.ihc/${project.version} - + + openhab-runtime-base + mvn:org.apache.httpcomponents/httpcore-osgi/4.4.10 + mvn:org.apache.httpcomponents/httpclient-osgi/4.5.8 + mvn:commons-logging/commons-logging/1.2 + mvn:org.openhab.addons.bundles/org.openhab.binding.ihc/${project.version} + diff --git a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/profiles/IhcProfiles.java b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/profiles/IhcProfiles.java index 0e7609b645f09..847286c1da748 100644 --- a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/profiles/IhcProfiles.java +++ b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/profiles/IhcProfiles.java @@ -34,5 +34,4 @@ public interface IhcProfiles { .withSupportedItemTypes(CoreItemFactory.DIMMER, CoreItemFactory.ROLLERSHUTTER, CoreItemFactory.CONTACT, CoreItemFactory.SWITCH, CoreItemFactory.PLAYER) .build(); - } diff --git a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/datatypes/WSTimeManagerSettings.java b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/datatypes/WSTimeManagerSettings.java index 31164005e6e42..60879f20effc1 100644 --- a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/datatypes/WSTimeManagerSettings.java +++ b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/datatypes/WSTimeManagerSettings.java @@ -142,7 +142,7 @@ public WSTimeManagerSettings parseXMLData(String data) throws IhcExecption { setTimeAndDateInUTC(timeAndDateInUTC); return this; - } catch (IOException | XPathExpressionException| NumberFormatException e) { + } catch (IOException | XPathExpressionException | NumberFormatException e) { throw new IhcExecption("Error occured during XML data parsing", e); } } diff --git a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/resourcevalues/WSFloatingPointValue.java b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/resourcevalues/WSFloatingPointValue.java index 8aadba5c7584f..8e2cb9fb49c73 100644 --- a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/resourcevalues/WSFloatingPointValue.java +++ b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/resourcevalues/WSFloatingPointValue.java @@ -32,7 +32,7 @@ public WSFloatingPointValue(int resourceID, double value, double minimumValue, d @Override public String toString() { - return String.format("[resourceId=%d, value=%.2f, min=%.2f, max=%.2f]", super.resourceID, value, - minimumValue, maximumValue); + return String.format("[resourceId=%d, value=%.2f, min=%.2f, max=%.2f]", super.resourceID, value, minimumValue, + maximumValue); } } diff --git a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/services/IhcAirlinkManagementService.java b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/services/IhcAirlinkManagementService.java index d41e1bcd86e5b..2a5bda8277bac 100644 --- a/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/services/IhcAirlinkManagementService.java +++ b/bundles/org.openhab.binding.ihc/src/main/java/org/openhab/binding/ihc/internal/ws/services/IhcAirlinkManagementService.java @@ -54,9 +54,12 @@ public synchronized List getDetectedDeviceList() throws IhcExecption if (nodeList != null) { for (int i = 0; i < nodeList.getLength(); i++) { - WSRFDevice newVal = parseResourceValue(nodeList.item(i)); - if (newVal != null) { - resourceValueList.add(newVal); + Node node = nodeList.item(i); + if (node != null) { + WSRFDevice dev = parseResourceValue(node); + if (dev != null) { + resourceValueList.add(dev); + } } } } else { @@ -69,14 +72,16 @@ public synchronized List getDetectedDeviceList() throws IhcExecption } private WSRFDevice parseResourceValue(Node n) throws XPathExpressionException, NumberFormatException { - String batteryLevel = XPathUtils.getValueFromNode(n, "batteryLevel"); - String deviceType = XPathUtils.getValueFromNode(n, "deviceType"); - String serialNumber = XPathUtils.getValueFromNode(n, "serialNumber"); - String signalStrength = XPathUtils.getValueFromNode(n, "signalStrength"); - String version = XPathUtils.getValueFromNode(n, "version"); - String detected = XPathUtils.getValueFromNode(n, "detected"); - return new WSRFDevice(Integer.parseInt(batteryLevel), Integer.parseInt(deviceType), - Long.parseLong(serialNumber), Integer.parseInt(signalStrength), Integer.parseInt(version), - Boolean.valueOf(detected)); + try { + int batteryLevel = Integer.parseInt(XPathUtils.getValueFromNode(n, "batteryLevel")); + int deviceType = Integer.parseInt(XPathUtils.getValueFromNode(n, "deviceType")); + long serialNumber = Long.parseLong(XPathUtils.getValueFromNode(n, "serialNumber")); + int signalStrength = Integer.parseInt(XPathUtils.getValueFromNode(n, "signalStrength")); + int version = Integer.parseInt(XPathUtils.getValueFromNode(n, "version")); + boolean detected = Boolean.valueOf(XPathUtils.getValueFromNode(n, "detected")); + return new WSRFDevice(batteryLevel, deviceType, serialNumber, signalStrength, version, detected); + } catch (NumberFormatException e) { + return null; + } } } diff --git a/bundles/org.openhab.binding.ihc/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.ihc/src/main/resources/ESH-INF/thing/channels.xml index ca88d89e1cedf..0724e25228f10 100644 --- a/bundles/org.openhab.binding.ihc/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.ihc/src/main/resources/ESH-INF/thing/channels.xml @@ -48,7 +48,8 @@ - Pulse width in milliseconds. If defined, binding send pulse rather than command value to IHC controller. + Pulse width in milliseconds. If defined, binding send pulse rather than command value to IHC + controller. @@ -132,7 +133,8 @@ - If defined, binding use this level when ON command is received rather than resource maximum value. Level is anyhow limited to resource maximum value. + If defined, binding use this level when ON command is received rather than resource maximum value. + Level is anyhow limited to resource maximum value. diff --git a/bundles/org.openhab.binding.ihc/src/main/resources/ESH-INF/thing/controller.xml b/bundles/org.openhab.binding.ihc/src/main/resources/ESH-INF/thing/controller.xml index ecc34f724722c..3888d3d472dcc 100644 --- a/bundles/org.openhab.binding.ihc/src/main/resources/ESH-INF/thing/controller.xml +++ b/bundles/org.openhab.binding.ihc/src/main/resources/ESH-INF/thing/controller.xml @@ -10,28 +10,29 @@ - - - + + + - - - - - - - - - + + + + + + + + + network-address - Network/IP address of the IHC / ELKO controller without https prefix, but can contain TCP port if default port is not used + Network/IP address of the IHC / ELKO controller without https prefix, but can contain TCP port if + default port is not used @@ -54,7 +55,8 @@ - Create channels automatically from project file. Project file loading parameter should be enabled as well. + Create channels automatically from project file. Project file loading parameter should be enabled as + well. true diff --git a/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcAirlinkManagementServiceTest.java b/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcAirlinkManagementServiceTest.java index e83d5427dd75a..3c566f971103a 100644 --- a/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcAirlinkManagementServiceTest.java +++ b/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcAirlinkManagementServiceTest.java @@ -39,24 +39,26 @@ public class IhcAirlinkManagementServiceTest { private final String host = "1.1.1.1"; private final String url = "https://1.1.1.1/ws/AirlinkManagementService"; private Map requestProps = new HashMap<>(); + private String query; private final int timeout = 100; @Before public void setUp() throws IhcExecption, SocketTimeoutException { ihcAirlinkManagementService = spy(new IhcAirlinkManagementService(host, timeout, new IhcConnectionPool())); - final String query = ResourceFileUtils.getFileContent("EmptyQuery.xml"); - final String response = ResourceFileUtils.getFileContent("GetDetectedDeviceListResponse.xml"); + query = ResourceFileUtils.getFileContent("EmptyQuery.xml"); requestProps.clear(); requestProps.put("SOAPAction", "getDetectedDeviceList"); - doReturn(response).when(ihcAirlinkManagementService).sendQuery(eq(url), eq(requestProps), eq(query), - eq(timeout)); } @Test public void test() throws IhcExecption { + final String response = ResourceFileUtils.getFileContent("GetDetectedDeviceListResponse.xml"); + doReturn(response).when(ihcAirlinkManagementService).sendQuery(eq(url), eq(requestProps), eq(query), + eq(timeout)); + final List result = ihcAirlinkManagementService.getDetectedDeviceList(); assertEquals(1, result.size()); @@ -68,4 +70,15 @@ public void test() throws IhcExecption { assertEquals(10, result.get(0).getSignalStrength()); assertEquals(1, result.get(0).getVersion()); } + + @Test + public void testEmptyList() throws IhcExecption { + final String response = ResourceFileUtils.getFileContent("GetEmptyDetectedDeviceListResponse.xml"); + doReturn(response).when(ihcAirlinkManagementService).sendQuery(eq(url), eq(requestProps), eq(query), + eq(timeout)); + + final List result = ihcAirlinkManagementService.getDetectedDeviceList(); + + assertEquals(0, result.size()); + } } diff --git a/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcConfigurationServiceTest.java b/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcConfigurationServiceTest.java index c1a0a59270979..b3f8109cb3b99 100644 --- a/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcConfigurationServiceTest.java +++ b/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcConfigurationServiceTest.java @@ -98,5 +98,4 @@ public void testv3() throws IhcExecption { assertEquals("3.06.c", result.getRfModuleSoftwareVersion()); assertEquals("640C10140000", result.getRfModuleSerialNumber()); } - } diff --git a/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcControllerServiceTest.java b/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcControllerServiceTest.java index 5ee9fc066be3b..0c8f208b85db8 100644 --- a/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcControllerServiceTest.java +++ b/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcControllerServiceTest.java @@ -140,5 +140,4 @@ public void projectSegmentQueryTest() throws IhcExecption { assertTrue("Result bytes doesn't match to expected bytes", Arrays.equals(expectedResult, result.getData())); } - } diff --git a/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcTimeServiceTest.java b/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcTimeServiceTest.java index 0f3aac9c33329..51871759aff06 100644 --- a/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcTimeServiceTest.java +++ b/bundles/org.openhab.binding.ihc/src/test/java/org/openhab/binding/ihc/internal/ws/services/IhcTimeServiceTest.java @@ -66,6 +66,5 @@ public void test() throws IhcExecption { assertEquals(24, result.getSyncIntervalInHours()); assertEquals(LocalDateTime.parse("2018-12-07T08:20:10", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")), result.getTimeAndDateInUTC().getAsLocalDateTime()); - } } diff --git a/bundles/org.openhab.binding.ihc/src/test/resources/GetEmptyDetectedDeviceListResponse.xml b/bundles/org.openhab.binding.ihc/src/test/resources/GetEmptyDetectedDeviceListResponse.xml new file mode 100644 index 0000000000000..2e364b8598260 --- /dev/null +++ b/bundles/org.openhab.binding.ihc/src/test/resources/GetEmptyDetectedDeviceListResponse.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/bundles/org.openhab.binding.innogysmarthome/pom.xml b/bundles/org.openhab.binding.innogysmarthome/pom.xml index 9ec6c624f864d..9ab188ac6a568 100644 --- a/bundles/org.openhab.binding.innogysmarthome/pom.xml +++ b/bundles/org.openhab.binding.innogysmarthome/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.innogysmarthome diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/InnogyClient.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/InnogyClient.java index d547e3a615fa8..5b91c47b8fe03 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/InnogyClient.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/InnogyClient.java @@ -41,6 +41,7 @@ import org.eclipse.smarthome.core.auth.client.oauth2.OAuthResponseException; import org.openhab.binding.innogysmarthome.internal.client.entity.StatusResponse; import org.openhab.binding.innogysmarthome.internal.client.entity.action.Action; +import org.openhab.binding.innogysmarthome.internal.client.entity.action.ShutterAction; import org.openhab.binding.innogysmarthome.internal.client.entity.action.StateActionSetter; import org.openhab.binding.innogysmarthome.internal.client.entity.capability.Capability; import org.openhab.binding.innogysmarthome.internal.client.entity.capability.CapabilityState; @@ -300,6 +301,7 @@ public void setDimmerActuatorState(final String capabilityId, final int dimLevel * @param rollerShutterLevel * @throws IOException * @throws ApiException + * @throws AuthenticationException */ public void setRollerShutterActuatorState(final String capabilityId, final int rollerShutterLevel) throws IOException, ApiException, AuthenticationException { @@ -307,6 +309,21 @@ public void setRollerShutterActuatorState(final String capabilityId, final int r new StateActionSetter(capabilityId, Capability.TYPE_ROLLERSHUTTERACTUATOR, rollerShutterLevel)); } + /** + * Starts or stops moving a RollerShutterActuator + * + * @param capabilityId + * @param rollerShutterAction + * @throws IOException + * @throws ApiException + * @throws AuthenticationException + */ + public void setRollerShutterAction(final String capabilityId, + final ShutterAction.ShutterActions rollerShutterAction) + throws IOException, ApiException, AuthenticationException { + executePost(API_URL_ACTION, new ShutterAction(capabilityId, rollerShutterAction)); + } + /** * Sets a new state of a VariableActuator. * diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/Action.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/Action.java index bda0602feef25..8d2eaa76b95be 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/Action.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/Action.java @@ -125,5 +125,4 @@ public ActionParams getParams() { public void setParams(ActionParams params) { this.params = params; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/ActionParams.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/ActionParams.java index 7d415a32ca320..ce4344cff06f2 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/ActionParams.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/ActionParams.java @@ -32,6 +32,8 @@ public class ActionParams { private StringActionParam operationMode; + private StringActionParam rampDirection; + /** * @return the onState */ @@ -116,4 +118,17 @@ public void setOperationMode(StringActionParam operationMode) { this.operationMode = operationMode; } + /** + * @return the rampDirection + */ + public StringActionParam getRampDirection() { + return rampDirection; + } + + /** + * @param rampDirection the rampDirection to set + */ + public void setRampDirection(StringActionParam rampDirection) { + this.rampDirection = rampDirection; + } } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/DoubleActionParam.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/DoubleActionParam.java index 27c9176e0ea48..e3db9f233472c 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/DoubleActionParam.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/DoubleActionParam.java @@ -59,5 +59,4 @@ public double isValue() { public void setValue(double value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/IntegerActionParam.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/IntegerActionParam.java index 28d58a4db7870..c680085292856 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/IntegerActionParam.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/IntegerActionParam.java @@ -59,5 +59,4 @@ public int isValue() { public void setValue(int value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/ShutterAction.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/ShutterAction.java new file mode 100644 index 0000000000000..2fa9adbfb5eeb --- /dev/null +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/ShutterAction.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.innogysmarthome.internal.client.entity.action; + +/** + * Special {@link Action} needed to control shutters. + * + * @author Marco Mans + */ +public class ShutterAction extends Action { + + public enum ShutterActions { + UP, + DOWN, + STOP + } + + private static final String TYPE_STOP_RAMP = "StopRamp"; + private static final String TYPE_START_RAMP = "StartRamp"; + private static final String DIRECTION_RAMP_UP = "RampUp"; + private static final String DIRECTION_RAMP_DOWN = "RampDown"; + private static final String CONSTANT = "Constant"; + private static final String NAMESPACE_COSIP = "CosipDevices.RWE"; + + /** + * Describes a Shutteraction + * + * @param capabilityId String of the 32 character capability id + * @param action Which action to perform (UP, DOWN, STOP) + */ + public ShutterAction(String capabilityId, ShutterActions action) { + setTargetCapabilityById(capabilityId); + setNamespace(NAMESPACE_COSIP); + final ActionParams params = new ActionParams(); + + if (ShutterActions.STOP.equals(action)) { + setType(TYPE_STOP_RAMP); + } else if (ShutterActions.UP.equals(action)) { + setType(TYPE_START_RAMP); + params.setRampDirection(new StringActionParam(CONSTANT, DIRECTION_RAMP_UP)); + } else if (ShutterActions.DOWN.equals(action)) { + setType(TYPE_START_RAMP); + params.setRampDirection(new StringActionParam(CONSTANT, DIRECTION_RAMP_DOWN)); + } + setParams(params); + } +} diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/StateActionSetter.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/StateActionSetter.java index e8f81afc5b27f..8311f5784ff02 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/StateActionSetter.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/StateActionSetter.java @@ -102,5 +102,4 @@ public StateActionSetter(String capabilityId, String capabilityType, String newV } setParams(params); } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/StringActionParam.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/StringActionParam.java index 4667006178c28..58b8b61714817 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/StringActionParam.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/action/StringActionParam.java @@ -59,5 +59,4 @@ public String isValue() { public void setValue(String value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/device/Device.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/device/Device.java index 78170e3afd297..919ed1ead80f3 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/device/Device.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/device/Device.java @@ -457,7 +457,6 @@ public boolean isBatteryPowered() { */ public void setIsBatteryPowered(boolean hasBattery) { batteryPowered = hasBattery; - } /** @@ -540,5 +539,4 @@ public String toString() { + getType() + " name=" + getConfig().getName() + "]"; return string; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/device/DeviceConfig.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/device/DeviceConfig.java index b8828c2ba016d..5509d4d1642b0 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/device/DeviceConfig.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/device/DeviceConfig.java @@ -408,5 +408,4 @@ public String getMeterFirmwareVersion() { public void setMeterFirmwareVersion(String meterFirmwareVersion) { this.meterFirmwareVersion = meterFirmwareVersion; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/event/BaseEvent.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/event/BaseEvent.java index d4b82c0cb6de1..f33bfe1d2c6bc 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/event/BaseEvent.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/event/BaseEvent.java @@ -149,5 +149,4 @@ public boolean isNewMessageReceivedEvent() { public boolean isStateChangedEvent() { return TYPE_STATE_CHANGED.equals(getType()); } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/event/EventProperties.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/event/EventProperties.java index 0c4e36374ad74..e40ffaed07a7f 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/event/EventProperties.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/event/EventProperties.java @@ -579,5 +579,4 @@ public void setMemoryUsage(final Double memoryUsage) { public Double getMemoryUsage() { return memoryUsage; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/message/MessageProperties.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/message/MessageProperties.java index ae6a06cc1a6d1..277e7491a29af 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/message/MessageProperties.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/message/MessageProperties.java @@ -75,5 +75,4 @@ public String getLocationName() { public void setLocationName(String locationName) { this.locationName = locationName; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/DoubleState.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/DoubleState.java index ccb7e69486588..74aaf8718b154 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/DoubleState.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/DoubleState.java @@ -32,5 +32,4 @@ public Double getValue() { public void setValue(Double value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/IntegerState.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/IntegerState.java index b0a4984a7b8af..b8a6dba4eca6c 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/IntegerState.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/IntegerState.java @@ -32,5 +32,4 @@ public Integer getValue() { public void setValue(Integer value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/StringState.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/StringState.java index 6c4c334cc924c..64db1c9f93844 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/StringState.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/entity/state/StringState.java @@ -32,5 +32,4 @@ public String getValue() { public void setValue(String value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/AuthenticationException.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/AuthenticationException.java index 9d7104bf2f5e4..41722cab73c4f 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/AuthenticationException.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/AuthenticationException.java @@ -31,5 +31,4 @@ public AuthenticationException() { public AuthenticationException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/ControllerOfflineException.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/ControllerOfflineException.java index 0360f61418887..2a66da50ccb45 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/ControllerOfflineException.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/ControllerOfflineException.java @@ -33,5 +33,4 @@ public ControllerOfflineException() { public ControllerOfflineException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/RemoteAccessNotAllowedException.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/RemoteAccessNotAllowedException.java index 6f4294f1cbe83..a279496a2eaa8 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/RemoteAccessNotAllowedException.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/RemoteAccessNotAllowedException.java @@ -31,5 +31,4 @@ public RemoteAccessNotAllowedException() { public RemoteAccessNotAllowedException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/SessionNotFoundException.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/SessionNotFoundException.java index 2498d7e43968e..e8b06e2992ded 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/SessionNotFoundException.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/client/exception/SessionNotFoundException.java @@ -31,5 +31,4 @@ public SessionNotFoundException() { public SessionNotFoundException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyBridgeConfiguration.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyBridgeConfiguration.java index dd95903b35457..0de34541d71de 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyBridgeConfiguration.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyBridgeConfiguration.java @@ -29,5 +29,4 @@ public class InnogyBridgeConfiguration { public String clientId = InnogyBindingConstants.CLIENT_ID_INNOGY_SMARTHOME; public String clientSecret = InnogyBindingConstants.CLIENT_SECRET_INNOGY_SMARTHOME; public String redirectUrl = InnogyBindingConstants.REDIRECT_URL_INNOGY_SMARTHOME; - } diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyBridgeHandler.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyBridgeHandler.java index 06321377126df..fd14643445cc8 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyBridgeHandler.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyBridgeHandler.java @@ -54,6 +54,7 @@ import org.eclipse.smarthome.core.types.Command; import org.openhab.binding.innogysmarthome.internal.InnogyWebSocket; import org.openhab.binding.innogysmarthome.internal.client.InnogyClient; +import org.openhab.binding.innogysmarthome.internal.client.entity.action.ShutterAction; import org.openhab.binding.innogysmarthome.internal.client.entity.capability.Capability; import org.openhab.binding.innogysmarthome.internal.client.entity.device.Device; import org.openhab.binding.innogysmarthome.internal.client.entity.device.DeviceConfig; @@ -465,7 +466,6 @@ public void onDeviceStateChanged(final Device device) { } } - } @Override @@ -601,7 +601,6 @@ public void handleStateChangedEvent(final Event event) throws ApiException, IOEx } else { logger.debug("link type {} not supported (yet?)", event.getSourceLinkType()); } - } /** @@ -666,7 +665,6 @@ public void handleNewMessageReceivedEvent(final MessageEvent event) } else { logger.debug("Message received event not yet implemented for Messagetype {}.", message.getType()); } - } /** @@ -862,6 +860,29 @@ public void commandSetRollerShutterLevel(final String deviceId, final int roller } } + /** + * Sends the command to start or stop moving the rollershutter (ISR2) in a specified direction + * + * @param deviceId + * @param action + */ + public void commandSetRollerShutterStop(final String deviceId, ShutterAction.ShutterActions action) { + final DeviceStructureManager deviceStructMan = this.deviceStructMan; + if (deviceStructMan == null) { + return; + } + try { + final String capabilityId = deviceStructMan.getCapabilityId(deviceId, + Capability.TYPE_ROLLERSHUTTERACTUATOR); + if (capabilityId == null) { + return; + } + client.setRollerShutterAction(capabilityId, action); + } catch (IOException | ApiException | AuthenticationException e) { + handleClientException(e); + } + } + /** * Handles all Exceptions of the client communication. For minor "errors" like an already existing session, it * returns true to inform the binding to continue running. In other cases it may e.g. schedule a reinitialization of diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyDeviceHandler.java b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyDeviceHandler.java index 2163f9aecd01f..91d4a76e8f15f 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyDeviceHandler.java +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/java/org/openhab/binding/innogysmarthome/internal/handler/InnogyDeviceHandler.java @@ -23,12 +23,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.OpenClosedType; -import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.library.types.UpDownType; +import org.eclipse.smarthome.core.library.types.*; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -42,6 +37,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.innogysmarthome.internal.client.entity.action.ShutterAction; import org.openhab.binding.innogysmarthome.internal.client.entity.capability.Capability; import org.openhab.binding.innogysmarthome.internal.client.entity.capability.CapabilityState; import org.openhab.binding.innogysmarthome.internal.client.entity.device.Device; @@ -144,19 +140,19 @@ public void handleCommand(final ChannelUID channelUID, final Command command) { invertValueIfConfigured(CHANNEL_ROLLERSHUTTER, rollerShutterLevel.intValue())); } else if (command instanceof OnOffType) { if (OnOffType.ON.equals(command)) { - innogyBridgeHandler.commandSetRollerShutterLevel(deviceId, - invertValueIfConfigured(CHANNEL_ROLLERSHUTTER, 100)); + innogyBridgeHandler.commandSetRollerShutterStop(deviceId, ShutterAction.ShutterActions.DOWN); } else { - innogyBridgeHandler.commandSetRollerShutterLevel(deviceId, - invertValueIfConfigured(CHANNEL_ROLLERSHUTTER, 0)); + innogyBridgeHandler.commandSetRollerShutterStop(deviceId, ShutterAction.ShutterActions.UP); } } else if (command instanceof UpDownType) { if (UpDownType.DOWN.equals(command)) { - innogyBridgeHandler.commandSetRollerShutterLevel(deviceId, - invertValueIfConfigured(CHANNEL_ROLLERSHUTTER, 100)); + innogyBridgeHandler.commandSetRollerShutterStop(deviceId, ShutterAction.ShutterActions.DOWN); } else { - innogyBridgeHandler.commandSetRollerShutterLevel(deviceId, - invertValueIfConfigured(CHANNEL_ROLLERSHUTTER, 0)); + innogyBridgeHandler.commandSetRollerShutterStop(deviceId, ShutterAction.ShutterActions.UP); + } + } else if (command instanceof StopMoveType) { + if (StopMoveType.STOP.equals(command)) { + innogyBridgeHandler.commandSetRollerShutterStop(deviceId, ShutterAction.ShutterActions.STOP); } } @@ -938,7 +934,6 @@ public void onDeviceStateChanged(final Device changedDevice, final Event event) } } - } /** diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/AnalogMeter.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/AnalogMeter.xml index d659e095c9e10..869c8b05eb0ed 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/AnalogMeter.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/AnalogMeter.xml @@ -6,20 +6,20 @@ - + The Analog Meter from the innogy EnergyControl product. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/BRC8.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/BRC8.xml index d1acede5b2180..cc1c0e8852e8b 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/BRC8.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/BRC8.xml @@ -6,32 +6,32 @@ - + A battery powered remote controller with eight push buttons. - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/BT-PSS.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/BT-PSS.xml index 0500ab1cb0a33..45c659ba2364d 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/BT-PSS.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/BT-PSS.xml @@ -6,16 +6,16 @@ - + A pluggable switch that can be switched on and off and which can measure the current energy consumption. - + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/GenerationMeter.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/GenerationMeter.xml index 74bd748b61ddc..6224fdd11492f 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/GenerationMeter.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/GenerationMeter.xml @@ -6,21 +6,21 @@ - + The Generation Meter from the innogy PowerControlSolar product, that measures the generated energy. - - - - - - + + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISC2.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISC2.xml index 1ce17b688ab80..1c8ebdde3f317 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISC2.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISC2.xml @@ -6,19 +6,19 @@ - + A smart controller with two push buttons. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISD2.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISD2.xml index fa9b48aaff94f..3c891dc5cac3b 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISD2.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISD2.xml @@ -6,20 +6,20 @@ - + An in wall dimmer with push buttons. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISR2.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISR2.xml index 01c963b4e0dc4..c4cf80ea1b4f7 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISR2.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISR2.xml @@ -6,20 +6,20 @@ - + An in wall rollershutter with two push buttons. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISS2.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISS2.xml index a9d8e89332896..9bb133a9408f8 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISS2.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/ISS2.xml @@ -6,20 +6,20 @@ - + An in wall switch with push buttons that can be switched on and off. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSD.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSD.xml index 03648aa246a0c..1cb6e9bff7d09 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSD.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSD.xml @@ -6,16 +6,16 @@ - + A pluggable dimmer. - + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSS.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSS.xml index 3f40d98831443..e7cb590838d2a 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSS.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSS.xml @@ -6,16 +6,16 @@ - + A pluggable switch that can be switched on and off. - + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSSO.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSSO.xml index c0ef4ffeab2c9..614a713a67c3c 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSSO.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/PSSO.xml @@ -6,16 +6,16 @@ - + A pluggable outdoor switch that can be switched on and off. - + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/RST.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/RST.xml index 8dc8752923701..502794083b1bd 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/RST.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/RST.xml @@ -6,23 +6,23 @@ - + A thermostat, that supports setting the temperature and measuring the current temperature and humidity. - - - - - - - - + + + + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/RST2.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/RST2.xml index d8ec5c6c2a999..63aca1e1f3a38 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/RST2.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/RST2.xml @@ -6,23 +6,24 @@ - + - A thermostat, that supports setting the temperature and measuring the current temperature and humidity (2 battery version since 2018) + A thermostat, that supports setting the temperature and measuring the current temperature and humidity (2 + battery version since 2018) - - - - - - - - + + + + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/SmartMeter.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/SmartMeter.xml index 5e607bb0dabbc..e3cfaaf9daa41 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/SmartMeter.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/SmartMeter.xml @@ -6,21 +6,21 @@ - + The Smart Meter from the innogy PowerControl product. - - - - - - + + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/TwoWayMeter.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/TwoWayMeter.xml index bd167f304515d..1ebb074c774c0 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/TwoWayMeter.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/TwoWayMeter.xml @@ -6,28 +6,28 @@ - + The Two-Way-Meter from the innogy PowerControlSolar product. - - - - - + + + + + - - - - - + + + + + - + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/VariableActuator.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/VariableActuator.xml index f5152fa264238..01d3f03e2c02a 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/VariableActuator.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/VariableActuator.xml @@ -6,16 +6,16 @@ - + A variable from the innogy SmartHome System that can be switched on and off. - + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WDS.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WDS.xml index 5ef1eb6064cd2..3555b4d547961 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WDS.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WDS.xml @@ -6,17 +6,17 @@ - + A window/door sensor, that provides the open/close state. - - + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WMD.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WMD.xml index e474dce0c7d2a..a30825a2bd44c 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WMD.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WMD.xml @@ -6,18 +6,18 @@ - + A battery powered motion detector, that also measures luminance. - - - + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WMDO.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WMDO.xml index ef368a6ff1270..e873ea54c4044 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WMDO.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WMDO.xml @@ -6,18 +6,18 @@ - + A battery powered motion detector for outdoors, that also measures luminance. - - - + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WRT.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WRT.xml index f7ac43e764717..c1bccef813a58 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WRT.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WRT.xml @@ -6,23 +6,24 @@ - + - A wall thermostat, that supports setting the temperature and measuring the current temperature and humidity. + A wall thermostat, that supports setting the temperature and measuring the current temperature and + humidity. - - - - - - - - + + + + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSC2.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSC2.xml index 907522315e425..ee178027ba238 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSC2.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSC2.xml @@ -6,20 +6,20 @@ - + A battery powered smart controller with two push buttons. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSD.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSD.xml index c367e4610f817..0e8d9734c83db 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSD.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSD.xml @@ -6,18 +6,18 @@ - + A battery powered smoke detector sensor with integrated alarm (first version). - - - + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSD2.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSD2.xml index 84993ca6888ce..ac3d1f4bd45c9 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSD2.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/WSD2.xml @@ -6,18 +6,18 @@ - + A battery powered smoke detector sensor with integrated alarm (2nd version with long-life battery). - - - + + + - + diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/bridge.xml index 937ec36ea60dc..c3a42a9d76d10 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/bridge.xml @@ -9,9 +9,9 @@ The innogy SmartHome Controller (SHC) is the bridge for the innogy SmartHome System. - - - + + + @@ -47,8 +47,10 @@ seconds The WebSocket is the connection to the innogy service that listens to status updates. - If no data is received over the websocket connection for the given time, - the websocket will reconnect. 0 will disable the idle timeout. Default is 900 seconds (15 minutes). + If no data is + received over the websocket connection for the given time, + the websocket will reconnect. 0 will disable the idle + timeout. Default is 900 seconds (15 minutes). 900 true diff --git a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/channels.xml index 8b05d61ccc22a..e9dc92e5c2368 100644 --- a/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.innogysmarthome/src/main/resources/ESH-INF/thing/channels.xml @@ -68,7 +68,7 @@ Thermostat temperature reduced, if window is open. Temperature - + @@ -85,7 +85,7 @@ Warns, if temperature drop below a threshold (configured in innogy app) Temperature - + @@ -102,7 +102,7 @@ Active, if humidity is over a threshold (configured in innogy app) Humidity - + diff --git a/bundles/org.openhab.binding.insteon/README.md b/bundles/org.openhab.binding.insteon/README.md index 1fae4d9067acc..e8d1e20d2befa 100644 --- a/bundles/org.openhab.binding.insteon/README.md +++ b/bundles/org.openhab.binding.insteon/README.md @@ -43,7 +43,6 @@ The Insteon PLM or hub is configured with the following parameters: |----------|---------:|--------:|-------------| | port | | Yes | **Examples:**
- PLM on Linux: `/dev/ttyS0` or `/dev/ttyUSB0`
- Smartenit ZBPLM on Linux: `/dev/ttyUSB0,baudRate=115200`
- PLM on Windows: `COM1`
- Current hub (2245-222) at 192.168.1.100 on port 25105, with a poll interval of 1000 ms (1 second): `/hub2/my_user_name:my_password@192.168.1.100:25105,poll_time=1000`
- Legacy hub (2242-222) at 192.168.1.100 on port 9761:`/hub/192.168.1.100:9761`
- Networked PLM using ser2net at 192.168.1.100 on port 9761:`/tcp/192.168.1.100:9761` | | devicePollIntervalSeconds | 300 | No | Poll interval of devices in seconds. Poll too often and you will overload the insteon network, leading to sluggish or no response when trying to send messages to devices. The default poll interval of 300 seconds has been tested and found to be a good compromise in a configuration of about 110 switches/dimmers. | -|modemDbRetryTimeoutSeconds|120|No|The number of seconds to wait for the modem database to completely download before retrying again. Under normal circumstances this will not need to be modified.| | additionalDevices | | No | Optional file with additional device types. The syntax of the file is identical to the `device_types.xml` file in the source tree. Please remember to post successfully added device types to the openhab group so the developers can include them into the `device_types.xml` file! | | additionalFeatures | | No | Optional file with additional feature templates, like in the `device_features.xml` file in the source tree. | @@ -155,7 +154,7 @@ In order to determine which channels a device supports, you can look at the devi | keypadButtonF | Switch | Keypad Button F | | keypadButtonG | Switch | Keypad Button G | | keypadButtonH | Switch | Keypad Button H | -| kWh | Number | Kilowatt Hour | +| kWh | Number:Energy | Kilowatt Hour | | lastHeardFrom | DateTime | Last Heard From | | ledBrightness | Number | LED brightness | | ledOnOff | Switch | LED On/Off | @@ -183,7 +182,7 @@ In order to determine which channels a device supports, you can look at the devi | temperature | Number:Temperature | Temperature | | topOutlet | Switch | Top Outlet | | update | Switch | Update | -| watts | Number | Watts | +| watts | Number:Power | Watts | ## Full Example @@ -648,10 +647,10 @@ See the example below: **Items** ``` - Number iMeterWatts "iMeter [%d watts]" { channel="insteon:device:home:AABBCC:watts" } - Number iMeterKwh "iMeter [%.04f kwh]" { channel="insteon:device:home:AABBCC:kwh" } - Switch iMeterUpdate "iMeter Update" { channel="insteon:device:home:AABBCC:update" } - Switch iMeterReset "iMeter Reset" { channel="insteon:device:home:AABBCC:reset" } + Number:Power iMeterWatts "iMeter [%d watts]" { channel="insteon:device:home:AABBCC:watts" } + Number:Energy iMeterKwh "iMeter [%.04f kWh]" { channel="insteon:device:home:AABBCC:kWh" } + Switch iMeterUpdate "iMeter Update" { channel="insteon:device:home:AABBCC:update" } + Switch iMeterReset "iMeter Reset" { channel="insteon:device:home:AABBCC:reset" } ``` ### Fan Controllers @@ -827,9 +826,6 @@ If new devices are linked, the binding must be restarted. Use the [Insteon Terminal](https://github.com/pfrommerd/insteon-terminal) for that. If using Insteon Terminal (especially as root), ensure any stale lock files (For example, /var/lock/LCK..ttyUSB0) are removed before starting openHAB runtime. Failure to do so may result in "found no ports". -* Very rarely during binding startup, a message arrives at the modem while the initial read of the modem database happens. -Somehow the modem then stops sending the remaining link records and the binding no longer is able to address the missing devices. -The fix is to simply restart the binding. -* The Insteon PLM device is know to break after about 2-3 years due to poorly sized capacitors of the power supply. -With a bit of soldering skill you can repair it yourself, see [here](http://pfrommer.us/home-automation) or [the original thread](http://forum.universal-devices.com/topic/13866-repair-of-2413s-plm-when-the-power-supply-fails/). +* The Insteon PLM or hub is know to break in about 2-3 years due to poorly sized capacitors. +You can repair it yourself using basic soldering skills, search for "Insteon PLM repair" or "Insteon hub repair". * Using the Insteon Hub 2014 in conjunction with other applications (such as the InsteonApp) is not supported. Concretely, openHAB will not learn when a switch is flipped via the Insteon App until the next poll, which could take minutes. diff --git a/bundles/org.openhab.binding.insteon/pom.xml b/bundles/org.openhab.binding.insteon/pom.xml index e49e6c1ef51a6..76d29a978790e 100644 --- a/bundles/org.openhab.binding.insteon/pom.xml +++ b/bundles/org.openhab.binding.insteon/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.insteon diff --git a/bundles/org.openhab.binding.insteon/src/main/feature/feature.xml b/bundles/org.openhab.binding.insteon/src/main/feature/feature.xml index cfcb08298df64..804d2f06d182b 100644 --- a/bundles/org.openhab.binding.insteon/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.insteon/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.insteon/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.insteon/${project.version} + diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/InsteonBinding.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/InsteonBinding.java index 9974a546a95e7..0affda35cc761 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/InsteonBinding.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/InsteonBinding.java @@ -24,6 +24,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; import javax.xml.parsers.ParserConfigurationException; @@ -110,7 +111,7 @@ public class InsteonBinding { private final Logger logger = LoggerFactory.getLogger(InsteonBinding.class); - private Driver driver = new Driver(); + private Driver driver; private ConcurrentHashMap devices = new ConcurrentHashMap<>(); private ConcurrentHashMap bindingConfigs = new ConcurrentHashMap<>(); private PortListener portListener = new PortListener(); @@ -122,21 +123,21 @@ public class InsteonBinding { private InsteonNetworkHandler handler; public InsteonBinding(InsteonNetworkHandler handler, @Nullable InsteonNetworkConfiguration config, - @Nullable SerialPortManager serialPortManager) { + @Nullable SerialPortManager serialPortManager, ScheduledExecutorService scheduler) { this.handler = handler; + String port = config.getPort(); + logger.debug("port = '{}'", Utils.redactPassword(port)); + + driver = new Driver(port, portListener, serialPortManager, scheduler); + driver.addMsgListener(portListener); + Integer devicePollIntervalSeconds = config.getDevicePollIntervalSeconds(); if (devicePollIntervalSeconds != null) { devicePollIntervalMilliseconds = devicePollIntervalSeconds * 1000; } logger.debug("device poll interval set to {} seconds", devicePollIntervalMilliseconds / 1000); - Integer modemDbRetryTimeoutSeconds = config.getModemDbRetryTimeoutSeconds(); - if (modemDbRetryTimeoutSeconds != null) { - logger.debug("setting modem db retry timeout to {} seconds", modemDbRetryTimeoutSeconds); - driver.setModemDBRetryTimeout(modemDbRetryTimeoutSeconds * 1000); - } - String additionalDevices = config.getAdditionalDevices(); if (additionalDevices != null) { try { @@ -155,34 +156,12 @@ public InsteonBinding(InsteonNetworkHandler handler, @Nullable InsteonNetworkCon deadDeviceTimeout = devicePollIntervalMilliseconds * DEAD_DEVICE_COUNT; logger.debug("dead device timeout set to {} seconds", deadDeviceTimeout / 1000); - - String port = config.getPort(); - logger.debug("port = '{}'", Utils.redactPassword(port)); - driver.addPort("port", port, serialPortManager); - driver.addMsgListener(portListener, port); - - logger.debug("setting driver listener"); - driver.setDriverListener(portListener); } public boolean startPolling() { - logger.debug("starting {} ports", driver.getNumberOfPorts()); - - driver.startAllPorts(); - logger.debug("ports started"); - switch (driver.getNumberOfPorts()) { - case 0: - logger.warn("initialization complete, but found no ports!"); - return false; - case 1: - logger.debug("initialization complete, found 1 port!"); - break; - default: - logger.warn("initialization complete, found {} ports.", driver.getNumberOfPorts()); - break; - } - - return true; + logger.debug("starting to poll {}", driver.getPortName()); + driver.start(); + return driver.isRunning(); } public void setIsActive(boolean isActive) { @@ -270,7 +249,6 @@ public InsteonDevice makeNewDevice(InsteonAddress addr, String productKey) { InsteonDevice dev = InsteonDevice.makeDevice(dt); dev.setAddress(addr); dev.setDriver(driver); - dev.addPort(driver.getDefaultPort()); if (!dev.hasValidPollingInterval()) { dev.setPollInterval(devicePollIntervalMilliseconds); } @@ -341,6 +319,11 @@ public Map getDatabaseInfo() { } } + public boolean reconnect() { + driver.stop(); + return startPolling(); + } + /** * Everything below was copied from Insteon PLM v1 */ @@ -350,7 +333,7 @@ public Map getDatabaseInfo() { */ public void shutdown() { logger.debug("shutting down Insteon bridge"); - driver.stopAllPorts(); + driver.stop(); devices.clear(); RequestQueueManager.destroyInstance(); Poller.instance().stop(); @@ -445,18 +428,17 @@ public void logDeviceStatistics() { @NonNullByDefault private class PortListener implements MsgListener, DriverListener { @Override - public void msg(Msg msg, String fromPort) { + public void msg(Msg msg) { if (msg.isEcho() || msg.isPureNack()) { return; } messagesReceived++; logger.debug("got msg: {}", msg); if (msg.isX10()) { - handleX10Message(msg, fromPort); + handleX10Message(msg); } else { - handleInsteonMessage(msg, fromPort); + handleInsteonMessage(msg); } - } @Override @@ -508,7 +490,12 @@ public void driverCompletelyInitialized() { } } - private void handleInsteonMessage(Msg msg, String fromPort) { + @Override + public void disconnected() { + handler.bindingDisconnected(); + } + + private void handleInsteonMessage(Msg msg) { InsteonAddress toAddr = msg.getAddr("toAddress"); if (!msg.isBroadcast() && !driver.isMsgForUs(toAddr)) { // not for one of our modems, do not process @@ -519,17 +506,17 @@ private void handleInsteonMessage(Msg msg, String fromPort) { logger.debug("invalid fromAddress, ignoring msg {}", msg); return; } - handleMessage(fromPort, fromAddr, msg); + handleMessage(fromAddr, msg); } - private void handleX10Message(Msg msg, String fromPort) { + private void handleX10Message(Msg msg) { try { int x10Flag = msg.getByte("X10Flag") & 0xff; int rawX10 = msg.getByte("rawX10") & 0xff; if (x10Flag == 0x80) { // actual command if (x10HouseUnit != -1) { InsteonAddress fromAddr = new InsteonAddress((byte) x10HouseUnit); - handleMessage(fromPort, fromAddr, msg); + handleMessage(fromAddr, msg); } } else if (x10Flag == 0) { // what unit the next cmd will apply to @@ -541,12 +528,12 @@ private void handleX10Message(Msg msg, String fromPort) { } } - private void handleMessage(String fromPort, InsteonAddress fromAddr, Msg msg) { + private void handleMessage(InsteonAddress fromAddr, Msg msg) { InsteonDevice dev = getDevice(fromAddr); if (dev == null) { logger.debug("dropping message from unknown device with address {}", fromAddr); } else { - dev.handleMessage(fromPort, msg); + dev.handleMessage(msg); } } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/config/InsteonNetworkConfiguration.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/config/InsteonNetworkConfiguration.java index f030528a3154d..d8199b7faf563 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/config/InsteonNetworkConfiguration.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/config/InsteonNetworkConfiguration.java @@ -28,8 +28,6 @@ public class InsteonNetworkConfiguration { private @Nullable Integer devicePollIntervalSeconds; - private @Nullable Integer modemDbRetryTimeoutSeconds; - private @Nullable String additionalDevices; private @Nullable String additionalFeatures; @@ -42,10 +40,6 @@ public String getPort() { return devicePollIntervalSeconds; } - public @Nullable Integer getModemDbRetryTimeoutSeconds() { - return modemDbRetryTimeoutSeconds; - } - public @Nullable String getAdditionalDevices() { return additionalDevices; } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceFeature.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceFeature.java index 8baacf530129e..70dba109c1233 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceFeature.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceFeature.java @@ -261,15 +261,14 @@ public boolean isReferencedByItem(String aItemName) { * Called when message is incoming. Dispatches message according to message dispatcher * * @param msg The message to dispatch - * @param port the port from which the message came * @return true if dispatch successful */ - public boolean handleMessage(Msg msg, String port) { + public boolean handleMessage(Msg msg) { if (dispatcher == null) { logger.warn("{} no dispatcher for msg {}", name, msg); return false; } - return (dispatcher.dispatch(msg, port)); + return (dispatcher.dispatch(msg)); } /** diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceType.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceType.java index 252711d395bde..da2f3fd7b84fa 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceType.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/DeviceType.java @@ -163,5 +163,4 @@ public String toString() { return (s.replaceAll(",$", "")); } } - } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonDevice.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonDevice.java index d5a7da33d35cd..97b9e00c9b0ae 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonDevice.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/InsteonDevice.java @@ -59,7 +59,6 @@ public static enum DeviceStatus { private static final int TIME_BETWEEN_POLL_MESSAGES = 1500; private InsteonAddress address = new InsteonAddress(); - private ArrayList ports = new ArrayList<>(); private long pollInterval = -1L; // in milliseconds private @Nullable Driver driver = null; private HashMap features = new HashMap<>(); @@ -106,10 +105,6 @@ public InsteonAddress getAddress() { return driver; } - public boolean hasValidPorts() { - return (!ports.isEmpty()); - } - public long getPollInterval() { return pollInterval; } @@ -146,13 +141,6 @@ public long getPollOverDueTime() { return (lastTimePolled - lastMsgReceived); } - public String getPort() throws IOException { - if (ports.isEmpty()) { - throw new IOException("no ports configured for instrument " + getAddress()); - } - return (ports.iterator().next()); - } - public boolean hasAnyListeners() { synchronized (features) { for (DeviceFeature f : features.values()) { @@ -206,20 +194,6 @@ public void setFeatureQueried(@Nullable DeviceFeature f) { synchronized (mrequestQueue) { return (featureQueried); } - }; - - /** - * Add a port. Currently only a single port is being used. - * - * @param p the port to add - */ - public void addPort(@Nullable String p) { - if (p == null) { - return; - } - if (!ports.contains(p)) { - ports.add(p); - } } /** @@ -301,11 +275,10 @@ public void doPoll(long delay) { /** * Handle incoming message for this device by forwarding * it to all features that this device supports - * - * @param fromPort port from which the message come in + * * @param msg the incoming message */ - public void handleMessage(String fromPort, Msg msg) { + public void handleMessage(Msg msg) { synchronized (lastMsgReceived) { lastMsgReceived = System.currentTimeMillis(); } @@ -315,7 +288,7 @@ public void handleMessage(String fromPort, Msg msg) { for (DeviceFeature f : features.values()) { if (!f.isStatusFeature()) { logger.debug("----- applying message to feature: {}", f.getName()); - if (f.handleMessage(msg, fromPort)) { + if (f.handleMessage(msg)) { // handled a reply to a query, // mark it as processed logger.trace("handled reply of direct: {}", f); @@ -328,7 +301,7 @@ public void handleMessage(String fromPort, Msg msg) { // e.g. when the device was last updated for (DeviceFeature f : features.values()) { if (f.isStatusFeature()) { - f.handleMessage(msg, fromPort); + f.handleMessage(msg); } } } @@ -528,7 +501,7 @@ public void enqueueDelayedMessage(Msg m, DeviceFeature f, long delay) { } private void writeMessage(Msg m) throws IOException { - driver.writeMessage(getPort(), m); + driver.writeMessage(m); } private void instantiateFeatures(@Nullable DeviceType dt) { diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageDispatcher.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageDispatcher.java index b9fb84258c568..4e0f330827881 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageDispatcher.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageDispatcher.java @@ -56,10 +56,9 @@ public void setParameters(@Nullable Map map) { * Generic handling of incoming ALL LINK messages * * @param msg the message received - * @param port the port on which the message was received * @return true if the message was handled by this function */ - protected boolean handleAllLinkMessage(Msg msg, String port) { + protected boolean handleAllLinkMessage(Msg msg) { if (!msg.isAllLink()) { return false; } @@ -88,7 +87,7 @@ protected boolean handleAllLinkMessage(Msg msg, String port) { if (h.matchesGroup(group) && h.matches(msg)) { logger.debug("{}:{}->{} cmd1:{} group {}/{}", feature.getDevice().getAddress(), feature.getName(), h.getClass().getSimpleName(), Utils.getHexByte(cmd1), group, h.getGroup()); - h.handleMessage(group, cmd1, msg, feature, port); + h.handleMessage(group, cmd1, msg, feature); } else { logger.debug("message ignored because matches group: {} matches filter: {}", h.matchesGroup(group), h.matches(msg)); @@ -118,11 +117,10 @@ boolean isMyDirectAck(Msg msg) { * Dispatches message * * @param msg Message to dispatch - * @param port Insteon device ('/dev/usb') from which the message came * @return true if this message was found to be a reply to a direct message, * and was claimed by one of the handlers */ - public abstract boolean dispatch(Msg msg, String port); + public abstract boolean dispatch(Msg msg); // // @@ -137,7 +135,7 @@ public static class DefaultDispatcher extends MessageDispatcher { } @Override - public boolean dispatch(Msg msg, String port) { + public boolean dispatch(Msg msg) { byte cmd = 0x00; byte cmd1 = 0x00; boolean isConsumed = false; @@ -154,7 +152,7 @@ public boolean dispatch(Msg msg, String port) { // in response to a direct status query message return false; } - if (handleAllLinkMessage(msg, port)) { + if (handleAllLinkMessage(msg)) { return false; } if (msg.isAckOfDirect()) { @@ -184,7 +182,7 @@ public boolean dispatch(Msg msg, String port) { logger.debug("{}:{}->{} DIRECT", feature.getDevice().getAddress(), feature.getName(), h.getClass().getSimpleName()); } - h.handleMessage(-1, cmd1, msg, feature, port); + h.handleMessage(-1, cmd1, msg, feature); } } if (isConsumed) { @@ -203,7 +201,7 @@ public static class DefaultGroupDispatcher extends MessageDispatcher { } @Override - public boolean dispatch(Msg msg, String port) { + public boolean dispatch(Msg msg) { byte cmd = 0x00; byte cmd1 = 0x00; boolean isConsumed = false; @@ -220,7 +218,7 @@ public boolean dispatch(Msg msg, String port) { // in response to a direct status query message return false; } - if (handleAllLinkMessage(msg, port)) { + if (handleAllLinkMessage(msg)) { return false; } if (msg.isAckOfDirect()) { @@ -251,7 +249,7 @@ public boolean dispatch(Msg msg, String port) { logger.debug("{}:{}->{} DIRECT", f.getDevice().getAddress(), f.getName(), h.getClass().getSimpleName()); } - h.handleMessage(-1, cmd1, msg, f, port); + h.handleMessage(-1, cmd1, msg, f); } } @@ -272,13 +270,13 @@ public static class PollGroupDispatcher extends MessageDispatcher { } @Override - public boolean dispatch(Msg msg, String port) { + public boolean dispatch(Msg msg) { if (msg.isAllLinkCleanupAckOrNack()) { // Had cases when a KeypadLinc would send an ALL_LINK_CLEANUP_ACK // in response to a direct status query message return false; } - if (handleAllLinkMessage(msg, port)) { + if (handleAllLinkMessage(msg)) { return false; } if (msg.isAckOfDirect()) { @@ -299,10 +297,10 @@ public static class SimpleDispatcher extends MessageDispatcher { } @Override - public boolean dispatch(Msg msg, String port) { + public boolean dispatch(Msg msg) { byte cmd1 = 0x00; try { - if (handleAllLinkMessage(msg, port)) { + if (handleAllLinkMessage(msg)) { return false; } if (msg.isAllLinkCleanupAckOrNack()) { @@ -324,7 +322,7 @@ public boolean dispatch(Msg msg, String port) { if (h.matches(msg)) { logger.trace("{}:{}->{} {}", feature.getDevice().getAddress(), feature.getName(), h.getClass().getSimpleName(), msg); - h.handleMessage(-1, cmd1, msg, feature, port); + h.handleMessage(-1, cmd1, msg, feature); } return isConsumed; } @@ -337,7 +335,7 @@ public static class X10Dispatcher extends MessageDispatcher { } @Override - public boolean dispatch(Msg msg, String port) { + public boolean dispatch(Msg msg) { try { byte rawX10 = msg.getByte("rawX10"); int cmd = (rawX10 & 0x0f); @@ -348,7 +346,7 @@ public boolean dispatch(Msg msg, String port) { logger.debug("{}:{}->{} {}", feature.getDevice().getAddress(), feature.getName(), h.getClass().getSimpleName(), msg); if (h.matches(msg)) { - h.handleMessage(-1, (byte) cmd, msg, feature, port); + h.handleMessage(-1, (byte) cmd, msg, feature); } } catch (FieldException e) { logger.warn("error parsing {}: ", msg, e); @@ -364,12 +362,12 @@ public static class PassThroughDispatcher extends MessageDispatcher { } @Override - public boolean dispatch(Msg msg, String port) { + public boolean dispatch(Msg msg) { MessageHandler h = feature.getDefaultMsgHandler(); if (h.matches(msg)) { logger.trace("{}:{}->{} {}", feature.getDevice().getAddress(), feature.getName(), h.getClass().getSimpleName(), msg); - h.handleMessage(-1, (byte) 0x01, msg, feature, port); + h.handleMessage(-1, (byte) 0x01, msg, feature); } return false; } @@ -385,7 +383,7 @@ public static class NoOpDispatcher extends MessageDispatcher { } @Override - public boolean dispatch(Msg msg, String port) { + public boolean dispatch(Msg msg) { return false; } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageHandler.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageHandler.java index 54104a861f0aa..6a725a8ced971 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageHandler.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/MessageHandler.java @@ -28,6 +28,7 @@ import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.unit.ImperialUnits; import org.eclipse.smarthome.core.library.unit.SIUnits; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.types.State; import org.openhab.binding.insteon.internal.device.DeviceFeatureListener.StateChangeType; import org.openhab.binding.insteon.internal.device.GroupMessageStateMachine.GroupMessage; @@ -74,9 +75,8 @@ public abstract class MessageHandler { * @param cmd1 the insteon cmd1 field * @param msg the received insteon message * @param feature the DeviceFeature to which this message handler is attached - * @param fromPort the device (/dev/ttyUSB0) from which the message has been received */ - public abstract void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature feature, String fromPort); + public abstract void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature feature); /** * Method to send an extended insteon message for querying a device @@ -347,7 +347,7 @@ public static class DefaultMsgHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { logger.debug("{} ignoring unimpl message with cmd1:{}", nm(), Utils.getHexByte(cmd1)); } } @@ -359,7 +359,7 @@ public static class NoOpMsgHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { logger.trace("{} ignore msg {}: {}", nm(), Utils.getHexByte(cmd1), msg); } } @@ -371,7 +371,7 @@ public static class LightOnDimmerHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { if (!isMybutton(msg, f)) { return; } @@ -401,7 +401,7 @@ public static class LightOffDimmerHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { if (isMybutton(msg, f)) { String mode = getStringParameter("mode", "REGULAR"); logger.debug("{}: device {} was turned off {}.", nm(), f.getDevice().getAddress(), mode); @@ -417,7 +417,7 @@ public static class LightOnSwitchHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { if (isMybutton(msg, f)) { String mode = getStringParameter("mode", "REGULAR"); logger.debug("{}: device {} was switched on {}.", nm(), f.getDevice().getAddress(), mode); @@ -435,7 +435,7 @@ public static class LightOffSwitchHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { if (isMybutton(msg, f)) { String mode = getStringParameter("mode", "REGULAR"); logger.debug("{}: device {} was switched off {}.", nm(), f.getDevice().getAddress(), mode); @@ -470,7 +470,7 @@ public void setParameters(Map params) { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { if (cmd1 == onCmd) { int level = getLevel(msg); logger.debug("{}: device {} was switched on using ramp to level {}.", nm(), f.getDevice().getAddress(), @@ -518,7 +518,7 @@ public static class SwitchRequestReplyHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { try { InsteonAddress a = f.getDevice().getAddress(); int cmd2 = msg.getByte("command2") & 0xff; @@ -586,7 +586,7 @@ public static class DimmerRequestReplyHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonDevice dev = f.getDevice(); try { int cmd2 = msg.getByte("command2") & 0xff; @@ -629,7 +629,7 @@ public boolean isDuplicate(Msg msg) { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { Msg m = f.makePollMsg(); if (m != null) { f.getDevice().enqueueMessage(m, f); @@ -651,7 +651,7 @@ public boolean isDuplicate(Msg msg) { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { try { int cmd2 = msg.getByte("command2") & 0xff; int upDown = (cmd2 == 0) ? 0 : 2; @@ -678,10 +678,9 @@ public boolean isDuplicate(Msg msg) { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { logger.debug("{}: dev {} manual state change: {}", nm(), f.getDevice().getAddress(), 0); feature.publish(new DecimalType(1), StateChangeType.ALWAYS); - } } @@ -692,7 +691,7 @@ public static class InfoRequestReplyHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonDevice dev = f.getDevice(); if (!msg.isExtended()) { logger.warn("{} device {} expected extended msg as info reply, got {}", nm(), dev.getAddress(), msg); @@ -728,7 +727,7 @@ public static class MotionSensorDataReplyHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonDevice dev = f.getDevice(); if (!msg.isExtended()) { logger.trace("{} device {} ignoring non-extended msg {}", nm(), dev.getAddress(), msg); @@ -763,7 +762,7 @@ public static class HiddenDoorSensorDataReplyHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonDevice dev = f.getDevice(); if (!msg.isExtended()) { logger.trace("{} device {} ignoring non-extended msg {}", nm(), dev.getAddress(), msg); @@ -799,7 +798,7 @@ public static class PowerMeterUpdateHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { if (msg.isExtended()) { try { // see iMeter developer notes 2423A1dev-072013-en.pdf @@ -821,8 +820,10 @@ public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String } logger.debug("{}:{} watts: {} kwh: {} ", nm(), f.getDevice().getAddress(), watts, kwh); - feature.publish(new DecimalType(kwh), StateChangeType.CHANGED, "field", "kwh"); - feature.publish(new DecimalType(watts), StateChangeType.CHANGED, "field", "watts"); + feature.publish(new QuantityType<>(kwh, SmartHomeUnits.KILOWATT_HOUR), StateChangeType.CHANGED, + "field", "kwh"); + feature.publish(new QuantityType<>(watts, SmartHomeUnits.WATT), StateChangeType.CHANGED, "field", + "watts"); } catch (FieldException e) { logger.warn("error parsing {}: ", msg, e); } @@ -837,7 +838,7 @@ public static class PowerMeterResetHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonDevice dev = f.getDevice(); logger.debug("{}: power meter {} was reset", nm(), dev.getAddress()); @@ -856,7 +857,7 @@ public static class LastTimeHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1a, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1a, Msg msg, DeviceFeature f) { feature.publish(new DateTimeType(), StateChangeType.ALWAYS); } } @@ -868,7 +869,7 @@ public static class ContactRequestReplyHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1a, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1a, Msg msg, DeviceFeature f) { byte cmd = 0x00; byte cmd2 = 0x00; try { @@ -893,7 +894,7 @@ public static class ClosedContactHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { feature.publish(OpenClosedType.CLOSED, StateChangeType.ALWAYS); } } @@ -905,7 +906,7 @@ public static class OpenedContactHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { feature.publish(OpenClosedType.OPEN, StateChangeType.ALWAYS); } } @@ -917,7 +918,7 @@ public static class OpenedOrClosedContactHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { try { byte cmd2 = msg.getByte("command2"); switch (cmd1) { @@ -958,7 +959,7 @@ public static class ClosedSleepingContactHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { feature.publish(OpenClosedType.CLOSED, StateChangeType.ALWAYS); sendExtendedQuery(f, (byte) 0x2e, (byte) 00); } @@ -971,7 +972,7 @@ public static class OpenedSleepingContactHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { feature.publish(OpenClosedType.OPEN, StateChangeType.ALWAYS); sendExtendedQuery(f, (byte) 0x2e, (byte) 00); } @@ -992,7 +993,7 @@ public static class TriggerPollMsgHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { feature.getDevice().doPoll(2000); // 2000 ms delay } } @@ -1007,7 +1008,7 @@ public static class NumberMsgHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { try { // first do the bit manipulations to focus on the right area int mask = getIntParameter("mask", 0xFFFF); @@ -1178,7 +1179,7 @@ public static class X10OnHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonAddress a = f.getDevice().getAddress(); logger.debug("{}: set X10 device {} to ON", nm(), a); feature.publish(OnOffType.ON, StateChangeType.ALWAYS); @@ -1192,7 +1193,7 @@ public static class X10OffHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonAddress a = f.getDevice().getAddress(); logger.debug("{}: set X10 device {} to OFF", nm(), a); feature.publish(OnOffType.OFF, StateChangeType.ALWAYS); @@ -1206,7 +1207,7 @@ public static class X10BrightHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonAddress a = f.getDevice().getAddress(); logger.debug("{}: ignoring brighten message for device {}", nm(), a); } @@ -1219,7 +1220,7 @@ public static class X10DimHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonAddress a = f.getDevice().getAddress(); logger.debug("{}: ignoring dim message for device {}", nm(), a); } @@ -1232,7 +1233,7 @@ public static class X10OpenHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonAddress a = f.getDevice().getAddress(); logger.debug("{}: set X10 device {} to OPEN", nm(), a); feature.publish(OpenClosedType.OPEN, StateChangeType.ALWAYS); @@ -1246,7 +1247,7 @@ public static class X10ClosedHandler extends MessageHandler { } @Override - public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f, String fromPort) { + public void handleMessage(int group, byte cmd1, Msg msg, DeviceFeature f) { InsteonAddress a = f.getDevice().getAddress(); logger.debug("{}: set X10 device {} to CLOSED", nm(), a); feature.publish(OpenClosedType.CLOSED, StateChangeType.ALWAYS); diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/ModemDBBuilder.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/ModemDBBuilder.java index e8725bf149821..d35eb1c8d099a 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/ModemDBBuilder.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/device/ModemDBBuilder.java @@ -16,6 +16,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -37,56 +40,57 @@ */ @NonNullByDefault @SuppressWarnings("null") -public class ModemDBBuilder implements MsgListener, Runnable { +public class ModemDBBuilder implements MsgListener { + private static final int MESSAGE_TIMEOUT = 30000; + private final Logger logger = LoggerFactory.getLogger(ModemDBBuilder.class); - private boolean isComplete = false; + + private volatile boolean isComplete = false; private Port port; - private @Nullable Thread writeThread = null; - private int timeoutMillis = 120000; + private ScheduledExecutorService scheduler; + private @Nullable ScheduledFuture job = null; + private volatile long lastMessageTimestamp; + private volatile int messageCount = 0; - public ModemDBBuilder(Port port) { + public ModemDBBuilder(Port port, ScheduledExecutorService scheduler) { this.port = port; - } - - public void setRetryTimeout(int timeout) { - this.timeoutMillis = timeout; + this.scheduler = scheduler; } public void start() { port.addListener(this); - writeThread = new Thread(this); - writeThread.setName("Insteon DBBuilder"); - writeThread.setDaemon(true); - writeThread.start(); - logger.debug("querying port for first link record"); + + logger.trace("starting modem db builder"); + startDownload(); + job = scheduler.scheduleWithFixedDelay(() -> { + if (isComplete()) { + logger.trace("modem db builder finished"); + job.cancel(false); + job = null; + } else { + if (System.currentTimeMillis() - lastMessageTimestamp > MESSAGE_TIMEOUT) { + String s = ""; + if (messageCount == 0) { + s = " No messages were received, the PLM or hub might be broken. If this continues see " + + "'Known Limitations and Issues' in the Insteon binding documentation."; + } + logger.warn("Modem database download was unsuccessful, restarting!{}", s); + startDownload(); + } + } + }, 0, 1, TimeUnit.SECONDS); } - public void startDownload() { + private void startDownload() { logger.trace("starting modem database download"); port.clearModemDB(); + lastMessageTimestamp = System.currentTimeMillis(); + messageCount = 0; getFirstLinkRecord(); } - public synchronized boolean isComplete() { - return (isComplete); - } - - @Override - public void run() { - logger.trace("starting modem db builder thread"); - while (!isComplete()) { - startDownload(); - try { - Thread.sleep(timeoutMillis); // wait for download to complete - } catch (InterruptedException e) { - logger.warn("modem db builder thread interrupted"); - break; - } - if (!isComplete()) { - logger.warn("modem database download unsuccessful, restarting!"); - } - } - logger.trace("exiting modem db builder thread"); + public boolean isComplete() { + return isComplete; } private void getFirstLinkRecord() { @@ -105,7 +109,10 @@ private void getFirstLinkRecord() { * {@inheritDoc} */ @Override - public void msg(Msg msg, String fromPort) { + public void msg(Msg msg) { + lastMessageTimestamp = System.currentTimeMillis(); + messageCount++; + if (msg.isPureNack()) { return; } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Driver.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Driver.java index 7b905669ed7c4..d8f7b2b32b0ad 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Driver.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Driver.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.locks.ReentrantLock; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -23,49 +24,31 @@ import org.openhab.binding.insteon.internal.device.InsteonAddress; import org.openhab.binding.insteon.internal.message.Msg; import org.openhab.binding.insteon.internal.message.MsgListener; -import org.openhab.binding.insteon.internal.utils.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** - * The driver class manages the modem ports. - * XXX: at this time, only a single modem has ever been used. Expect - * the worst if you connect multiple modems. When multiple modems - * are required, this code needs to be tested and fixed. + * The driver class manages the modem port. * * @author Bernd Pfrommer - Initial contribution * @author Rob Nielsen - Port to openHAB 2 insteon binding */ @NonNullByDefault -@SuppressWarnings("null") public class Driver { - private final Logger logger = LoggerFactory.getLogger(Driver.class); - - // maps device name to serial port, i.e /dev/insteon -> Port object - private Map ports = new HashMap<>(); - private @Nullable DriverListener listener = null; // single listener for notifications + private Port port; + private String portName; + private DriverListener listener; private Map modemDBEntries = new HashMap<>(); private ReentrantLock modemDBEntriesLock = new ReentrantLock(); - private int modemDBRetryTimeout = 120000; // in milliseconds - public void setDriverListener(DriverListener listener) { + public Driver(String portName, DriverListener listener, @Nullable SerialPortManager serialPortManager, + ScheduledExecutorService scheduler) { this.listener = listener; - } + this.portName = portName; - public void setModemDBRetryTimeout(int timeout) { - modemDBRetryTimeout = timeout; - for (Port p : ports.values()) { - p.setModemDBRetryTimeout(modemDBRetryTimeout); - } + port = new Port(portName, this, serialPortManager, scheduler); } public boolean isReady() { - for (Port p : ports.values()) { - if (!p.isRunning()) { - return false; - } - } - return true; + return port.isRunning(); } public Map lockModemDBEntries() { @@ -77,128 +60,45 @@ public void unlockModemDBEntries() { modemDBEntriesLock.unlock(); } - /** - * Add new port (modem) to the driver - * - * @param name the name of the port (from the config file, e.g. port_0, port_1, etc - * @param port the device name, e.g. /dev/insteon, /dev/ttyUSB0 etc - */ - public void addPort(String name, String port, @Nullable SerialPortManager serialPortManager) { - if (ports.keySet().contains(port)) { - logger.warn("ignored attempt to add duplicate port: {} {}", name, port); - } else { - Port p = new Port(port, this, serialPortManager); - p.setModemDBRetryTimeout(modemDBRetryTimeout); - ports.put(port, p); - logger.debug("added new port: {} {}", name, Utils.redactPassword(port)); - } + public void addMsgListener(MsgListener listener) { + port.addListener(listener); } - /** - * Register a message listener with a port - * - * @param listener the listener who wants to listen to port messages - * @param port the port (e.g. /dev/ttyUSB0) to which the listener listens - */ - public void addMsgListener(MsgListener listener, String port) { - if (ports.keySet().contains(port)) { - ports.get(port).addListener(listener); - } else { - logger.warn("referencing unknown port {}!", port); - } + public void start() { + port.start(); } - public void startAllPorts() { - for (Port p : ports.values()) { - p.start(); - } + public void stop() { + port.stop(); } - public void stopAllPorts() { - for (Port p : ports.values()) { - p.stop(); - } + public void writeMessage(Msg m) throws IOException { + port.writeMessage(m); } - /** - * Write message to a port - * - * @param port name of the port to write to (e.g. '/dev/ttyUSB0') - * @param m the message to write - * @throws IOException - */ - public void writeMessage(String port, Msg m) throws IOException { - Port p = getPort(port); - if (p == null) { - logger.warn("cannot write to unknown port {}", port); - throw new IOException(); - } - p.writeMessage(m); + public String getPortName() { + return portName; } - public @Nullable String getDefaultPort() { - return (ports.isEmpty() ? null : ports.keySet().iterator().next()); - } - - public int getNumberOfPorts() { - int n = 0; - for (Port p : ports.values()) { - if (p.isRunning()) { - n++; - } - } - return n; + public boolean isRunning() { + return port.isRunning(); } public boolean isMsgForUs(@Nullable InsteonAddress toAddr) { - if (toAddr == null) { - return false; - } - for (Port p : ports.values()) { - if (p.getAddress().equals(toAddr)) { - return true; - } - } - return false; - } - - /** - * Get port object corresponding to device - * - * @param port device name of port (e.g. /dev/ttyUSB0) - * @return corresponding Port object or null if not found - */ - public @Nullable Port getPort(String port) { - if (port.equalsIgnoreCase("DEFAULT")) { - if (ports.isEmpty()) { - logger.warn("no default port found!"); - return null; - } - return ports.values().iterator().next(); - } - if (!ports.containsKey(port)) { - logger.warn("no port of name {} found!", port); - return null; - } - return ports.get(port); + return port.getAddress().equals(toAddr); } public void modemDBComplete(Port port) { - // check if all ports have a complete device list - if (!isModemDBComplete()) { - return; + if (isModemDBComplete()) { + listener.driverCompletelyInitialized(); } - // if yes, notify listener - listener.driverCompletelyInitialized(); } public boolean isModemDBComplete() { - // check if all ports have a complete device list - for (Port p : ports.values()) { - if (!p.isModemDBComplete()) { - return false; - } - } - return true; + return port.isModemDBComplete(); + } + + public void disconnected() { + listener.disconnected(); } } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/DriverListener.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/DriverListener.java index d066519d5965a..cea7b3c83de33 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/DriverListener.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/DriverListener.java @@ -27,4 +27,9 @@ public interface DriverListener { * Notification that querying of the modems on all ports has successfully completed. */ public abstract void driverCompletelyInitialized(); + + /** + * Notification that the driver was disconnected + */ + public abstract void disconnected(); } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/IOStream.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/IOStream.java index d21ee81b5e569..e8c276384d456 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/IOStream.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/IOStream.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.insteon.internal.driver; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -37,7 +38,11 @@ public abstract class IOStream { private static final Logger logger = LoggerFactory.getLogger(IOStream.class); protected @Nullable InputStream in = null; protected @Nullable OutputStream out = null; - private boolean stopped = false; + private volatile boolean stopped = false; + + public void start() { + stopped = false; + } public void stop() { stopped = true; @@ -51,20 +56,16 @@ public void stop() { * @param readSize size to read * @return number of bytes read */ - public int read(byte[] b, int offset, int readSize) throws InterruptedException { + public int read(byte[] b, int offset, int readSize) throws InterruptedException, IOException { int len = 0; while (!stopped && len < 1) { - try { - len = in.read(b, offset, readSize); - if (Thread.interrupted()) { - throw new InterruptedException(); - } - } catch (IOException e) { - logger.trace("got exception while reading: {}", e.getMessage()); - while (!stopped && !reconnect()) { - logger.trace("sleeping before reconnecting"); - Thread.sleep(10000); - } + len = in.read(b, offset, readSize); + if (len == -1) { + throw new EOFException(); + } + + if (Thread.interrupted()) { + throw new InterruptedException(); } } return (len); @@ -75,20 +76,8 @@ public int read(byte[] b, int offset, int readSize) throws InterruptedException * * @param b byte array to write */ - public void write(byte @Nullable [] b) { - try { - out.write(b); - } catch (IOException e) { - logger.trace("got exception while writing: {}", e.getMessage()); - while (!stopped && !reconnect()) { - try { - logger.trace("sleeping before reconnecting"); - Thread.sleep(10000); - } catch (InterruptedException ie) { - logger.warn("interrupted while sleeping on write reconnect"); - } - } - } + public void write(byte @Nullable [] b) throws IOException { + out.write(b); } /** @@ -103,16 +92,6 @@ public void write(byte @Nullable [] b) { */ public abstract void close(); - /** - * reconnects the stream - * - * @return true if reconnect succeeded - */ - private synchronized boolean reconnect() { - close(); - return (open()); - } - /** * Creates an IOStream from an allowed config string: * diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Poller.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Poller.java index fb68dc35c3221..e675f1c834e49 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Poller.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Poller.java @@ -297,5 +297,4 @@ public static synchronized Poller instance() { poller.start(); return (poller); } - } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java index 9b2c24e4bcac9..2737eee2735ac 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java @@ -17,6 +17,8 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -83,6 +85,7 @@ enum ReplyType { private ModemDBBuilder mdbb; private ArrayList listeners = new ArrayList<>(); private LinkedBlockingQueue writeQueue = new LinkedBlockingQueue<>(); + private AtomicBoolean disconnected = new AtomicBoolean(false); /** * Constructor @@ -90,7 +93,8 @@ enum ReplyType { * @param devName the name of the port, i.e. '/dev/insteon' * @param d The Driver object that manages this port */ - public Port(String devName, Driver d, @Nullable SerialPortManager serialPortManager) { + public Port(String devName, Driver d, @Nullable SerialPortManager serialPortManager, + ScheduledExecutorService scheduler) { this.devName = devName; this.driver = d; this.logName = Utils.redactPassword(devName); @@ -99,7 +103,7 @@ public Port(String devName, Driver d, @Nullable SerialPortManager serialPortMana this.ioStream = IOStream.create(serialPortManager, devName); this.reader = new IOStreamReader(); this.writer = new IOStreamWriter(); - this.mdbb = new ModemDBBuilder(this); + this.mdbb = new ModemDBBuilder(this, scheduler); } public boolean isModem(InsteonAddress a) { @@ -126,10 +130,6 @@ public Driver getDriver() { return driver; } - public void setModemDBRetryTimeout(int timeout) { - mdbb.setRetryTimeout(timeout); - } - public void addListener(MsgListener l) { synchronized (listeners) { if (!listeners.contains(l)) { @@ -163,11 +163,15 @@ public void start() { logger.debug("starting port {}", logName); if (running) { logger.debug("port {} already running, not started again", logName); + return; } + + writeQueue.clear(); if (!ioStream.open()) { logger.debug("failed to open port {}", logName); return; } + ioStream.start(); readThread = new Thread(reader); readThread.setName("Insteon " + logName + " Reader"); readThread.setDaemon(true); @@ -176,9 +180,14 @@ public void start() { writeThread.setName("Insteon " + logName + " Writer"); writeThread.setDaemon(true); writeThread.start(); - modem.initialize(); - mdbb.start(); // start downloading the device list + + if (!mdbb.isComplete()) { + modem.initialize(); + mdbb.start(); // start downloading the device list + } + running = true; + disconnected.set(false); } /** @@ -216,10 +225,10 @@ public void stop() { } catch (InterruptedException e) { logger.debug("got interrupted waiting for write thread to exit."); } + readThread = null; + writeThread = null; + logger.debug("all threads for port {} stopped.", logName); - synchronized (listeners) { - listeners.clear(); - } } /** @@ -243,7 +252,6 @@ public void writeMessage(@Nullable Msg m) throws IOException { } catch (IllegalStateException e) { logger.warn("cannot write message {}, write queue is full!", m); } - } /** @@ -256,6 +264,15 @@ public void modemDBComplete() { driver.modemDBComplete(this); } + public void disconnected() { + if (isRunning()) { + if (!disconnected.getAndSet(true)) { + logger.warn("port {} disconnected", logName); + driver.disconnected(); + } + } + } + /** * The IOStreamReader uses the MsgFactory to turn the incoming bytes into * Msgs for the listeners. It also communicates with the IOStreamWriter @@ -295,6 +312,9 @@ public void run() { } } catch (InterruptedException e) { logger.debug("reader thread got interrupted!"); + } catch (IOException e) { + logger.debug("got an io exception in the reader thread"); + disconnected(); } logger.debug("reader thread exiting!"); } @@ -375,7 +395,7 @@ private void toAllListeners(Msg msg) { tempList = (ArrayList) listeners.clone(); } for (MsgListener l : tempList) { - l.msg(msg, devName); // deliver msg to listener + l.msg(msg); // deliver msg to listener } } @@ -454,6 +474,10 @@ public void run() { } catch (InterruptedException e) { logger.debug("got interrupted exception in write thread"); break; + } catch (IOException e) { + logger.debug("got an io exception in the write thread"); + disconnected(); + break; } } logger.debug("writer thread exiting!"); @@ -477,7 +501,7 @@ InsteonDevice getDevice() { } @Override - public void msg(Msg msg, String fromPort) { + public void msg(Msg msg) { try { if (msg.isPureNack()) { return; @@ -495,7 +519,6 @@ public void msg(Msg msg, String fromPort) { device.setProductKey(prodKey); device.setDriver(driver); device.setIsModem(true); - device.addPort(fromPort); logger.debug("found modem {} in device_types: {}", a, device.toString()); mdbb.updateModemDB(a, Port.this, null); } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/TcpIOStream.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/TcpIOStream.java index 928982848eb46..792e449d0153d 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/TcpIOStream.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/TcpIOStream.java @@ -60,10 +60,10 @@ public boolean open() { in = socket.getInputStream(); out = socket.getOutputStream(); } catch (UnknownHostException e) { - logger.warn("unknown host name: {}", host, e); + logger.warn("unknown host name: {}", host); return (false); } catch (IOException e) { - logger.warn("cannot open connection to {} port {}: ", host, port, e); + logger.warn("cannot open connection to {} port {}: {}", host, port, e.getMessage()); return (false); } return true; diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonNetworkHandler.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonNetworkHandler.java index 9d74c571c1b56..7a370a54dffe7 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonNetworkHandler.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/handler/InsteonNetworkHandler.java @@ -48,6 +48,7 @@ @SuppressWarnings("null") public class InsteonNetworkHandler extends BaseBridgeHandler { private static final int LOG_DEVICE_STATISTICS_DELAY_IN_SECONDS = 600; + private static final int RETRY_DELAY_IN_SECONDS = 30; private static final int SETTLE_TIME_IN_SECONDS = 5; private final Logger logger = LoggerFactory.getLogger(InsteonNetworkHandler.class); @@ -56,6 +57,7 @@ public class InsteonNetworkHandler extends BaseBridgeHandler { private @Nullable InsteonBinding insteonBinding; private @Nullable InsteonDeviceDiscoveryService insteonDeviceDiscoveryService; private @Nullable ScheduledFuture pollingJob = null; + private @Nullable ScheduledFuture reconnectJob = null; private @Nullable ScheduledFuture settleJob = null; private long lastInsteonDeviceCreatedTimestamp = 0; private @Nullable SerialPortManager serialPortManager; @@ -80,7 +82,7 @@ public void initialize() { updateStatus(ThingStatus.UNKNOWN); scheduler.execute(() -> { - insteonBinding = new InsteonBinding(this, config, serialPortManager); + insteonBinding = new InsteonBinding(this, config, serialPortManager, scheduler); // hold off on starting to poll until devices that already are defined as things are added. // wait SETTLE_TIME_IN_SECONDS to start then check every second afterwards until it has been at @@ -105,7 +107,7 @@ public void initialize() { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); } - settleJob.cancel(true); + settleJob.cancel(false); settleJob = null; } }, SETTLE_TIME_IN_SECONDS, 1, TimeUnit.SECONDS); @@ -121,6 +123,11 @@ public void dispose() { pollingJob = null; } + if (reconnectJob != null) { + reconnectJob.cancel(true); + reconnectJob = null; + } + if (settleJob != null) { settleJob.cancel(true); settleJob = null; @@ -142,6 +149,18 @@ public void updateState(ChannelUID channelUID, State state) { super.updateState(channelUID, state); } + public void bindingDisconnected() { + reconnectJob = scheduler.scheduleWithFixedDelay(() -> { + if (insteonBinding.reconnect()) { + updateStatus(ThingStatus.ONLINE); + reconnectJob.cancel(false); + reconnectJob = null; + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Port disconnected."); + } + }, 0, RETRY_DELAY_IN_SECONDS, TimeUnit.SECONDS); + } + public void insteonDeviceWasCreated() { lastInsteonDeviceCreatedTimestamp = System.currentTimeMillis(); } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgListener.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgListener.java index 18200f28f01a5..a824d08d85416 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgListener.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgListener.java @@ -26,7 +26,6 @@ public interface MsgListener { * Invoked whenever a valid message comes in from the modem * * @param msg the message received - * @param fromPort on which port (e.g. '/dev/ttyUSB0') this message arrived */ - public abstract void msg(Msg msg, String fromPort); + public abstract void msg(Msg msg); } diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgType.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgType.java index a6047092dcc4e..c0eac34a86bda 100644 --- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgType.java +++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgType.java @@ -80,5 +80,4 @@ public static MsgType fromValue(byte b) throws IllegalArgumentException { } return mt; } - } diff --git a/bundles/org.openhab.binding.insteon/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.insteon/src/main/resources/ESH-INF/thing/thing-types.xml index eac9323cfebb4..efe3885aea8b3 100644 --- a/bundles/org.openhab.binding.insteon/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.insteon/src/main/resources/ESH-INF/thing/thing-types.xml @@ -19,12 +19,6 @@ Device poll interval in seconds. - - - Modem DB retry timeout in seconds. - - - Optional file with additional device types. @@ -39,7 +33,7 @@ - + @@ -55,7 +49,7 @@ Insteon binding product key that is used to identify the model of the device. - + @@ -95,7 +89,7 @@ - + @@ -321,7 +315,7 @@ - Number + Number:Energy @@ -349,7 +343,7 @@ Number - + Contact @@ -481,7 +475,7 @@ - Number + Number:Power diff --git a/bundles/org.openhab.binding.insteon/src/main/resources/device_features.xml b/bundles/org.openhab.binding.insteon/src/main/resources/device_features.xml index 3b0cabe232eb7..6dbfd7fb1bf30 100644 --- a/bundles/org.openhab.binding.insteon/src/main/resources/device_features.xml +++ b/bundles/org.openhab.binding.insteon/src/main/resources/device_features.xml @@ -1,844 +1,873 @@ - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - FlexPollHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + FlexPollHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + - - DefaultDispatcher - - - RampDimmerHandler - RampPercentHandler - RampOnOffCommandHandler - + + DefaultDispatcher + + + RampDimmerHandler + RampPercentHandler + RampOnOffCommandHandler + - - DefaultDispatcher - - RampDimmerHandler - RampPercentHandler - RampOnOffCommandHandler - + + DefaultDispatcher + + RampDimmerHandler + RampPercentHandler + RampOnOffCommandHandler + - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOffSwitchHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOffSwitchHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOffSwitchHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOffSwitchHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOffSwitchHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOffSwitchHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOffSwitchHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOffSwitchHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - FlexPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOffSwitchHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOffSwitchHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOffSwitchHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOffSwitchHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOffSwitchHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOffSwitchHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOffSwitchHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOffSwitchHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + FlexPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - LightOnSwitchHandler - SwitchRequestReplyHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnDimmerHandler - LightOnDimmerHandler - LightOffDimmerHandler - LightOffDimmerHandler - NoOpMsgHandler - DimmerStopManualChangeHandler - DimmerRequestReplyHandler - PercentHandler - LightOnOffCommandHandler - FlexPollHandler - - - DefaultDispatcher - LightOnDimmerHandler - LightOffDimmerHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + LightOnSwitchHandler + SwitchRequestReplyHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnDimmerHandler + LightOnDimmerHandler + LightOffDimmerHandler + LightOffDimmerHandler + NoOpMsgHandler + DimmerStopManualChangeHandler + DimmerRequestReplyHandler + PercentHandler + LightOnOffCommandHandler + FlexPollHandler + + + DefaultDispatcher + LightOnDimmerHandler + LightOffDimmerHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - - - RampDimmerHandler - RampPercentHandler - RampOnOffCommandHandler - + + DefaultDispatcher + + + RampDimmerHandler + RampPercentHandler + RampOnOffCommandHandler + - - DefaultGroupDispatcher - FlexPollHandler - - - DefaultGroupDispatcher - NoPollHandler - - - DefaultGroupDispatcher - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultGroupDispatcher + FlexPollHandler + + + DefaultGroupDispatcher + NoPollHandler + + + DefaultGroupDispatcher + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - DefaultDispatcher - NoOpMsgHandler - LightOnSwitchHandler - LightOnSwitchHandler - LightOffSwitchHandler - LightOffSwitchHandler - SwitchRequestReplyHandler - LightOnOffCommandHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - FastOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - StartManualChangeHandler - StopManualChangeHandler - ManualChangeCommandHandler - NoPollHandler - + + DefaultDispatcher + NoOpMsgHandler + LightOnSwitchHandler + LightOnSwitchHandler + LightOffSwitchHandler + LightOffSwitchHandler + SwitchRequestReplyHandler + LightOnOffCommandHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + FastOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + StartManualChangeHandler + StopManualChangeHandler + ManualChangeCommandHandler + NoPollHandler + - - PassThroughDispatcher - LastTimeHandler - NoOpCommandHandler - - - DefaultDispatcher - NoOpMsgHandler - LightOnDimmerHandler - LightOnDimmerHandler - LightOffDimmerHandler - LightOffDimmerHandler - NoOpMsgHandler - DimmerStopManualChangeHandler - DimmerRequestReplyHandler - PercentHandler - IncreaseDecreaseCommandHandler - LightOnOffCommandHandler - FlexPollHandler - - - DefaultDispatcher - NoOpMsgHandler - OpenedContactHandler - ClosedContactHandler - ContactRequestReplyHandler - NoOpCommandHandler - FlexPollHandler - - - DefaultDispatcher - NoOpMsgHandler - NoOpMsgHandler - NoOpMsgHandler - SwitchRequestReplyHandler - IOLincOnOffCommandHandler - FlexPollHandler - - - DefaultDispatcher - NoOpMsgHandler - OpenedSleepingContactHandler - ClosedSleepingContactHandler - NoOpMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - OpenedSleepingContactHandler - ClosedSleepingContactHandler - NoOpMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - OpenedSleepingContactHandler - ClosedSleepingContactHandler - NoOpMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - SimpleDispatcher - NoOpMsgHandler - NoOpMsgHandler - NoOpMsgHandler - MotionSensorDataReplyHandler - NoOpCommandHandler - NoPollHandler - - - SimpleDispatcher - NoOpMsgHandler - NoOpMsgHandler - NoOpMsgHandler - HiddenDoorSensorDataReplyHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - OpenedContactHandler - ClosedContactHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - NoOpMsgHandler - OpenedOrClosedContactHandler - OpenedOrClosedContactHandler - NoOpCommandHandler - NoPollHandler - - - NoOpDispatcher - GroupBroadcastCommandHandler - NoOpMsgHandler - - - SimpleDispatcher - NoOpMsgHandler - PowerMeterResetHandler - PowerMeterUpdateHandler - PowerMeterCommandHandler - FlexPollHandler - - - X10Dispatcher - X10OnHandler - X10OffHandler - X10BrightHandler - X10DimHandler - NoOpMsgHandler - X10OnOffCommandHandler - X10PercentCommandHandler - X10IncreaseDecreaseCommandHandler - NoPollHandler - - - X10Dispatcher - X10OnHandler - X10OffHandler - NoOpMsgHandler - X10OnOffCommandHandler - NoOpCommandHandler - NoOpCommandHandler - NoPollHandler - - - X10Dispatcher - X10OpenHandler - X10ClosedHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - PollGroupDispatcher - FlexPollHandler - - - PollGroupDispatcher - FlexPollHandler - - - PollGroupDispatcher - FlexPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - ThermostatSystemModeMsgHandler - - ThermostatSystemModeReplyHandler - - NumberMsgHandler - NoOpMsgHandler - ThermostatSystemModeCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - ThermostatFanModeReplyHandler - - NumberMsgHandler - NoOpMsgHandler - ThermostatFanModeCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - FanLincFanReplyHandler - FanLincFanCommandHandler - FlexPollHandler - - - DefaultDispatcher - SwitchRequestReplyHandler - LightOnOffCommandHandler - FlexPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - - NumberMsgHandler - - ThermostatSystemModeReplyHandler - - NumberMsgHandler - NoOpMsgHandler - ThermostatSystemModeCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - ThermostatFanModeReplyHandler - - NumberMsgHandler - NoOpMsgHandler - ThermostatFanModeCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - NumberMsgHandler - - NumberMsgHandler - NoOpMsgHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - NoOpMsgHandler - NoPollHandler - - - PollGroupDispatcher - FlexPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - LightOnSwitchHandler - LightOffSwitchHandler - LEDOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - SwitchRequestReplyHandler - RampOnOffCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - - - DefaultDispatcher - - NumberMsgHandler - - TriggerPollMsgHandler - NoOpMsgHandler - NumberCommandHandler - NoOpCommandHandler - NoPollHandler - + + PassThroughDispatcher + LastTimeHandler + NoOpCommandHandler + + + DefaultDispatcher + NoOpMsgHandler + LightOnDimmerHandler + LightOnDimmerHandler + LightOffDimmerHandler + LightOffDimmerHandler + NoOpMsgHandler + DimmerStopManualChangeHandler + DimmerRequestReplyHandler + PercentHandler + IncreaseDecreaseCommandHandler + LightOnOffCommandHandler + FlexPollHandler + + + DefaultDispatcher + NoOpMsgHandler + OpenedContactHandler + ClosedContactHandler + ContactRequestReplyHandler + NoOpCommandHandler + FlexPollHandler + + + DefaultDispatcher + NoOpMsgHandler + NoOpMsgHandler + NoOpMsgHandler + SwitchRequestReplyHandler + IOLincOnOffCommandHandler + FlexPollHandler + + + DefaultDispatcher + NoOpMsgHandler + OpenedSleepingContactHandler + ClosedSleepingContactHandler + NoOpMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + OpenedSleepingContactHandler + ClosedSleepingContactHandler + NoOpMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + OpenedSleepingContactHandler + ClosedSleepingContactHandler + NoOpMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + SimpleDispatcher + NoOpMsgHandler + NoOpMsgHandler + NoOpMsgHandler + MotionSensorDataReplyHandler + NoOpCommandHandler + NoPollHandler + + + SimpleDispatcher + NoOpMsgHandler + NoOpMsgHandler + NoOpMsgHandler + HiddenDoorSensorDataReplyHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + OpenedContactHandler + ClosedContactHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + NoOpMsgHandler + OpenedOrClosedContactHandler + OpenedOrClosedContactHandler + NoOpCommandHandler + NoPollHandler + + + NoOpDispatcher + GroupBroadcastCommandHandler + NoOpMsgHandler + + + SimpleDispatcher + NoOpMsgHandler + PowerMeterResetHandler + PowerMeterUpdateHandler + PowerMeterCommandHandler + FlexPollHandler + + + X10Dispatcher + X10OnHandler + X10OffHandler + X10BrightHandler + X10DimHandler + NoOpMsgHandler + X10OnOffCommandHandler + X10PercentCommandHandler + X10IncreaseDecreaseCommandHandler + NoPollHandler + + + X10Dispatcher + X10OnHandler + X10OffHandler + NoOpMsgHandler + X10OnOffCommandHandler + NoOpCommandHandler + NoOpCommandHandler + NoPollHandler + + + X10Dispatcher + X10OpenHandler + X10ClosedHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + PollGroupDispatcher + FlexPollHandler + + + PollGroupDispatcher + FlexPollHandler + + + PollGroupDispatcher + FlexPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + ThermostatSystemModeMsgHandler + + ThermostatSystemModeReplyHandler + + NumberMsgHandler + NoOpMsgHandler + ThermostatSystemModeCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + ThermostatFanModeReplyHandler + + NumberMsgHandler + NoOpMsgHandler + ThermostatFanModeCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + FanLincFanReplyHandler + FanLincFanCommandHandler + FlexPollHandler + + + DefaultDispatcher + SwitchRequestReplyHandler + LightOnOffCommandHandler + FlexPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + + NumberMsgHandler + + ThermostatSystemModeReplyHandler + + NumberMsgHandler + NoOpMsgHandler + ThermostatSystemModeCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + ThermostatFanModeReplyHandler + + NumberMsgHandler + NoOpMsgHandler + ThermostatFanModeCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + NumberMsgHandler + + NumberMsgHandler + NoOpMsgHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + NoOpMsgHandler + NoPollHandler + + + PollGroupDispatcher + FlexPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + LightOnSwitchHandler + LightOffSwitchHandler + LEDOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + SwitchRequestReplyHandler + RampOnOffCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + + + DefaultDispatcher + + NumberMsgHandler + + TriggerPollMsgHandler + NoOpMsgHandler + NumberCommandHandler + NoOpCommandHandler + NoPollHandler + diff --git a/bundles/org.openhab.binding.insteon/src/main/resources/device_types.xml b/bundles/org.openhab.binding.insteon/src/main/resources/device_types.xml index f0f4e310b6692..14d567c881fd1 100644 --- a/bundles/org.openhab.binding.insteon/src/main/resources/device_types.xml +++ b/bundles/org.openhab.binding.insteon/src/main/resources/device_types.xml @@ -1,580 +1,587 @@ - - - - - - 2450 - IO Link - IOLincContact - GenericLastTime - IOLincSwitch - - - - 2486D - KeypadLinc Dimmer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2663-222 - On/Off Outlet - GenericSwitch - BottomOutlet - GenericLastTime - - - - 2484DWH8 - KeypadLinc Countdown Timer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2413U - PowerLinc 2413U USB modem - GroupBroadcastOnOff - - - - 2843-222 - Wireless Open/Close Sensor - GenericContact - GenericLastTime - - - - 2842-222 - Motion Sensor - WirelessMotionSensorContact - WirelessMotionSensorLightLevelAboveThreshold - WirelessMotionSensorLowBattery - MotionSensorData - GenericLastTime - - - 2486DWH6 - KeypadLinc Dimmer - 6 Button - LoadDimmerButton - LoadDimmerRamp - ManualChange - LoadDimmerFastOnOff - - KeyPadButton3 - KeyPadButton4 - KeyPadButton5 - KeyPadButton6 - - GenericLastTime - - - 2486DWH8 - KeypadLinc Dimmer - 8 Button - LoadDimmerButton - LoadDimmerRamp - ManualChange - LoadDimmerFastOnOff - - KeyPadButton2 - KeyPadButton3 - KeyPadButton4 - KeyPadButton5 - KeyPadButton6 - KeyPadButton7 - KeyPadButton8 - - - GenericLastTime - - - - 2472D - OutletLincDimmer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - - - - - - X10 switch - any simple X10 switch - X10Switch - - - X10 dimmer - Generic X10 Dimmer without preset - X10Switch - X10Dimmer - - - X10 motion sensor - Generic X10 motion sensor - X10Contact - - - - - - 2477D - SwitchLinc Dimmer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - LEDOnOff - Beep - - LEDBrightness - RampRate - OnLevel - - - - - 2477S - SwitchLinc Switch - GenericSwitch - FastOnOff - GenericLastTime - LEDOnOff - Beep - - LEDBrightness - - - - - 2845-222 - Hidden Door Sensor - WirelessMotionSensorContact - HiddenDoorSensorData - GenericLastTime - - - - 2876S - ICON Switch - GenericSwitch - GenericLastTime - - - - 2456D3 - LampLinc V2 - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2442-222 - Micro Dimmer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2453-222 - DIN Rail On/Off - GenericSwitch - GenericLastTime - - - - 2452-222 - DIN Rail Dimmer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2458-A1 - MorningLinc RF Lock Controller - GenericSwitch - - - - 2852-222 - Leak Sensor - LeakSensorContact - GenericLastTime - - - - 2672-422 - LED Dimmer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2476D - SwitchLinc Dimmer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2634-222 - On/Off Dual-Band Outdoor Module - GenericSwitch - GenericLastTime - LEDOnOff - Beep - - - - 2342-2 - Mini Remote - RemoteButton1 - RemoteButton2 - RemoteButton3 - RemoteButton4 - GenericLastTime - - - - 2466D - ToggleLinc Dimmer - GenericDimmer - RampDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2466S - ToggleLinc Switch - GenericSwitch - GenericLastTime - - - - 2672-222 - LED Bulb - GenericDimmer - RampDimmer_3435 - ManualChange - FastOnOff - GenericLastTime - - - - 2487S - KeypadLinc On/Off 6-Button Scene Control - LoadSwitchButton - LoadSwitchManualChange - LoadSwitchFastOnOff - - KeyPadButton3 - KeyPadButton4 - KeyPadButton5 - KeyPadButton6 - - - FastOnOffButton3 - FastOnOffButton4 - FastOnOffButton5 - FastOnOffButton6 - - - ManualChangeButton3 - ManualChangeButton4 - ManualChangeButton5 - ManualChangeButton6 - - GenericLastTime - - - - 2334-232 - Keypad Dimmer Switch, 6-Button - LoadDimmerButton - LoadDimmerRamp - ManualChange - LoadDimmerFastOnOff - - KeyPadButton3 - KeyPadButton4 - KeyPadButton5 - KeyPadButton6 - - - FastOnOffButton3 - FastOnOffButton4 - FastOnOffButton5 - FastOnOffButton6 - - - ManualChangeButton3 - ManualChangeButton4 - ManualChangeButton5 - ManualChangeButton6 - - - LEDBrightness - RampRate - OnLevel - - LEDOnOff - Beep - GenericLastTime - - - - 2334-232 - Keypad Dimmer Switch, 8-Button - LoadDimmerButton - LoadDimmerRamp - ManualChange - LoadDimmerFastOnOff - - KeyPadButton2 - KeyPadButton3 - KeyPadButton4 - KeyPadButton5 - KeyPadButton6 - KeyPadButton7 - KeyPadButton8 - - - FastOnOffButton2 - FastOnOffButton3 - FastOnOffButton4 - FastOnOffButton5 - FastOnOffButton6 - FastOnOffButton7 - FastOnOffButton8 - - - ManualChangeButton2 - ManualChangeButton3 - ManualChangeButton4 - ManualChangeButton5 - ManualChangeButton6 - ManualChangeButton7 - ManualChangeButton8 - - - LEDBrightness - RampRate - OnLevel - - LEDOnOff - Beep - GenericLastTime - - - - 2423A1 - iMeter Solo Power Meter - PowerMeter - GenericLastTime - - - - 2441TH - Insteon Thermostat - - ThermostatBackLightDuration - ThermostatACDelay - - - ThermostatHumidityHigh - ThermostatHumidityLow - ThermostatStage1Duration - - - ThermostatCoolSetPoint - ThermostatHeatSetPoint - ThermostatSystemMode - ThermostatFanMode - ThermostatIsHeating - ThermostatIsCooling - ThermostatTemperatureFahrenheit - - ThermostatHumidity - - GenericLastTime - - - - 2457D2 - LampLinc Dimmer - GenericDimmer - ManualChange - FastOnOff - GenericLastTime - LEDOnOff - Beep - - - - 2475SDB - In-LineLinc Relay - GenericSwitch - GenericLastTime - - - - 2635-222 - On/Off Module - GenericSwitch - GenericLastTime - LEDOnOff - Beep - - - - 2475F - FanLinc Module - GenericDimmer - FanLincFan - GenericLastTime - - - - 2456S3 - ApplianceLinc - GenericSwitch - GenericLastTime - - - - 2674-222 - LED Bulb (recessed) - GenericDimmer - RampDimmer - ManualChange - FastOnOff - GenericLastTime - - - - 2477SA1 - 220V 30-amp Load Controller N/O - GenericSwitch - FastOnOff - GenericLastTime - - - 2342-222 - Mini Remote (8 Button) - RemoteButton2 - RemoteButton1 - RemoteButton4 - RemoteButton3 - RemoteButton6 - RemoteButton5 - RemoteButton8 - RemoteButton7 - GenericLastTime - - - 2441V - Insteon Thermostat Adaptor for Venstar - - VenstarCoolSetPoint - VenstarHeatSetPoint - VenstarSystemMode - VenstarFanMode - VenstarTemperatureFahrenheit - VenstarHumidity - VenstarIsHeating - VenstarIsCooling - - GenericLastTime - - - 2982-222 - Insteon Smoke Bridge - ReceiveBroadcast - GenericLastTime - - - - 2487S - KeypadLinc On/Off 8-Button Scene Control - LoadSwitchButton - LoadSwitchManualChange - LoadSwitchFastOnOff - - KeyPadButton2 - KeyPadButton3 - KeyPadButton4 - KeyPadButton5 - KeyPadButton6 - KeyPadButton7 - KeyPadButton8 - - - FastOnOffButton2 - FastOnOffButton3 - FastOnOffButton4 - FastOnOffButton5 - FastOnOffButton6 - FastOnOffButton7 - FastOnOffButton8 - - - ManualChangeButton2 - ManualChangeButton3 - ManualChangeButton4 - ManualChangeButton5 - ManualChangeButton6 - ManualChangeButton7 - ManualChangeButton8 - - GenericLastTime - - + + + + + + 2450 + IO Link + IOLincContact + GenericLastTime + IOLincSwitch + + + + 2486D + KeypadLinc Dimmer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2663-222 + On/Off Outlet + GenericSwitch + BottomOutlet + GenericLastTime + + + + 2484DWH8 + KeypadLinc Countdown Timer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2413U + PowerLinc 2413U USB modem + GroupBroadcastOnOff + + + + 2843-222 + Wireless Open/Close Sensor + GenericContact + GenericLastTime + + + + 2842-222 + Motion Sensor + WirelessMotionSensorContact + WirelessMotionSensorLightLevelAboveThreshold + WirelessMotionSensorLowBattery + MotionSensorData + GenericLastTime + + + + 2486DWH6 + KeypadLinc Dimmer - 6 Button + LoadDimmerButton + LoadDimmerRamp + ManualChange + LoadDimmerFastOnOff + + KeyPadButton3 + KeyPadButton4 + KeyPadButton5 + KeyPadButton6 + + GenericLastTime + + + + 2486DWH8 + KeypadLinc Dimmer - 8 Button + LoadDimmerButton + LoadDimmerRamp + ManualChange + LoadDimmerFastOnOff + + KeyPadButton2 + KeyPadButton3 + KeyPadButton4 + KeyPadButton5 + KeyPadButton6 + KeyPadButton7 + KeyPadButton8 + + + GenericLastTime + + + + 2472D + OutletLinc Dimmer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + LEDOnOff + Beep + + LEDBrightness + RampRate + + + + + + + X10 switch + any simple X10 switch + X10Switch + + + X10 dimmer + Generic X10 Dimmer without preset + X10Switch + X10Dimmer + + + X10 motion sensor + Generic X10 motion sensor + X10Contact + + + + + + 2477D + SwitchLinc Dimmer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + LEDOnOff + Beep + + LEDBrightness + RampRate + OnLevel + + + + + 2477S + SwitchLinc Switch + GenericSwitch + FastOnOff + GenericLastTime + LEDOnOff + Beep + + LEDBrightness + + + + + 2845-222 + Hidden Door Sensor + WirelessMotionSensorContact + HiddenDoorSensorData + GenericLastTime + + + + 2876S + ICON Switch + GenericSwitch + GenericLastTime + + + + 2456D3 + LampLinc V2 + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2442-222 + Micro Dimmer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2453-222 + DIN Rail On/Off + GenericSwitch + GenericLastTime + + + + 2452-222 + DIN Rail Dimmer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2458-A1 + MorningLinc RF Lock Controller + GenericSwitch + + + + 2852-222 + Leak Sensor + LeakSensorContact + GenericLastTime + + + + 2672-422 + LED Dimmer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2476D + SwitchLinc Dimmer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2634-222 + On/Off Dual-Band Outdoor Module + GenericSwitch + GenericLastTime + LEDOnOff + Beep + + + + 2342-2 + Mini Remote + RemoteButton1 + RemoteButton2 + RemoteButton3 + RemoteButton4 + GenericLastTime + + + + 2466D + ToggleLinc Dimmer + GenericDimmer + RampDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2466S + ToggleLinc Switch + GenericSwitch + GenericLastTime + + + + 2672-222 + LED Bulb + GenericDimmer + RampDimmer_3435 + ManualChange + FastOnOff + GenericLastTime + + + + 2487S + KeypadLinc On/Off 6-Button Scene Control + LoadSwitchButton + LoadSwitchManualChange + LoadSwitchFastOnOff + + KeyPadButton3 + KeyPadButton4 + KeyPadButton5 + KeyPadButton6 + + + FastOnOffButton3 + FastOnOffButton4 + FastOnOffButton5 + FastOnOffButton6 + + + ManualChangeButton3 + ManualChangeButton4 + ManualChangeButton5 + ManualChangeButton6 + + GenericLastTime + + + + 2334-232 + Keypad Dimmer Switch, 6-Button + LoadDimmerButton + LoadDimmerRamp + ManualChange + LoadDimmerFastOnOff + + KeyPadButton3 + KeyPadButton4 + KeyPadButton5 + KeyPadButton6 + + + FastOnOffButton3 + FastOnOffButton4 + FastOnOffButton5 + FastOnOffButton6 + + + ManualChangeButton3 + ManualChangeButton4 + ManualChangeButton5 + ManualChangeButton6 + + + LEDBrightness + RampRate + OnLevel + + LEDOnOff + Beep + GenericLastTime + + + + 2334-232 + Keypad Dimmer Switch, 8-Button + LoadDimmerButton + LoadDimmerRamp + ManualChange + LoadDimmerFastOnOff + + KeyPadButton2 + KeyPadButton3 + KeyPadButton4 + KeyPadButton5 + KeyPadButton6 + KeyPadButton7 + KeyPadButton8 + + + FastOnOffButton2 + FastOnOffButton3 + FastOnOffButton4 + FastOnOffButton5 + FastOnOffButton6 + FastOnOffButton7 + FastOnOffButton8 + + + ManualChangeButton2 + ManualChangeButton3 + ManualChangeButton4 + ManualChangeButton5 + ManualChangeButton6 + ManualChangeButton7 + ManualChangeButton8 + + + LEDBrightness + RampRate + OnLevel + + LEDOnOff + Beep + GenericLastTime + + + + 2423A1 + iMeter Solo Power Meter + PowerMeter + GenericLastTime + + + + 2441TH + Insteon Thermostat + + ThermostatBackLightDuration + ThermostatACDelay + + + ThermostatHumidityHigh + ThermostatHumidityLow + ThermostatStage1Duration + + + ThermostatCoolSetPoint + ThermostatHeatSetPoint + ThermostatSystemMode + ThermostatFanMode + ThermostatIsHeating + ThermostatIsCooling + ThermostatTemperatureFahrenheit + + ThermostatHumidity + + GenericLastTime + + + + 2457D2 + LampLinc Dimmer + GenericDimmer + ManualChange + FastOnOff + GenericLastTime + LEDOnOff + Beep + + + + 2475SDB + In-LineLinc Relay + GenericSwitch + GenericLastTime + + + + 2635-222 + On/Off Module + GenericSwitch + GenericLastTime + LEDOnOff + Beep + + + + 2475F + FanLinc Module + GenericDimmer + FanLincFan + GenericLastTime + + + + 2456S3 + ApplianceLinc + GenericSwitch + GenericLastTime + + + + 2674-222 + LED Bulb (recessed) + GenericDimmer + RampDimmer + ManualChange + FastOnOff + GenericLastTime + + + + 2477SA1 + 220V 30-amp Load Controller N/O + GenericSwitch + FastOnOff + GenericLastTime + + + 2342-222 + Mini Remote (8 Button) + RemoteButton2 + RemoteButton1 + RemoteButton4 + RemoteButton3 + RemoteButton6 + RemoteButton5 + RemoteButton8 + RemoteButton7 + GenericLastTime + + + 2441V + Insteon Thermostat Adaptor for Venstar + + VenstarCoolSetPoint + VenstarHeatSetPoint + VenstarSystemMode + VenstarFanMode + VenstarTemperatureFahrenheit + VenstarHumidity + VenstarIsHeating + VenstarIsCooling + + GenericLastTime + + + 2982-222 + Insteon Smoke Bridge + ReceiveBroadcast + GenericLastTime + + + + 2487S + KeypadLinc On/Off 8-Button Scene Control + LoadSwitchButton + LoadSwitchManualChange + LoadSwitchFastOnOff + + KeyPadButton2 + KeyPadButton3 + KeyPadButton4 + KeyPadButton5 + KeyPadButton6 + KeyPadButton7 + KeyPadButton8 + + + FastOnOffButton2 + FastOnOffButton3 + FastOnOffButton4 + FastOnOffButton5 + FastOnOffButton6 + FastOnOffButton7 + FastOnOffButton8 + + + ManualChangeButton2 + ManualChangeButton3 + ManualChangeButton4 + ManualChangeButton5 + ManualChangeButton6 + ManualChangeButton7 + ManualChangeButton8 + + GenericLastTime + diff --git a/bundles/org.openhab.binding.insteon/src/main/resources/msg_definitions.xml b/bundles/org.openhab.binding.insteon/src/main/resources/msg_definitions.xml index d4c1cf08aeff2..26a8db7c89a9b 100644 --- a/bundles/org.openhab.binding.insteon/src/main/resources/msg_definitions.xml +++ b/bundles/org.openhab.binding.insteon/src/main/resources/msg_definitions.xml @@ -1,110 +1,110 @@ - +
0x02 0x15
- +
0x02 - 0x50 -
-
- + 0x50 +
+
+
- - + +
- +
- 0x02 - 0x51 -
-
- 0x10 + 0x02 + 0x51 +
+
+ 0x10
- - - - - - - - - - - - - - - - -
- + + + + + + + + + + + + + + + + + +
0x02 - 0x52 + 0x52
- - + +
- +
0x02 - 0x53 + 0x53
- - -
- - - + + +
+ + + - +
0x02 - 0x54 + 0x54
- +
- +
0x02 - 0x55 + 0x55
- +
0x02 - 0x56 + 0x56
- -
+ +
- +
- 0x02 - 0x57 + 0x02 + 0x57
@@ -113,298 +113,298 @@
- +
0x02 - 0x58 + 0x58
- +
- +
0x02 - 0x5c -
-
- + 0x5c +
+
+
- - + +
- +
- 0x02 - 0x60 + 0x02 + 0x60
- +
- 0x02 - 0x60 + 0x02 + 0x60
-
- - - - +
+ + + + - +
- 0x02 - 0x61 + 0x02 + 0x61
- 0x00 - 0x00 - 0x00 + 0x00 + 0x00 + 0x00
- +
- 0x02 - 0x61 + 0x02 + 0x61
- 0x00 - 0x00 - 0x00 - + 0x00 + 0x00 + 0x00 +
- +
- 0x02 - 0x62 -
- + 0x02 + 0x62 +
+
- +
- 0x02 - 0x62 -
- + 0x02 + 0x62 +
+
- +
- +
- 0x02 - 0x62 -
- 0x10 + 0x02 + 0x62 +
+ 0x10
0x00 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 - 0x00 -
- + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + +
- 0x02 - 0x62 -
- 0x10 + 0x02 + 0x62 +
+ 0x10
- - - - - - - - - - - - - - - -
- + + + + + + + + + + + + + + + + +
- 0x02 - 0x63 + 0x02 + 0x63
- - 0x00 + + 0x00
- +
- 0x02 - 0x63 + 0x02 + 0x63
- - 0x00 - + + 0x00 +
- +
- 0x02 - 0x64 + 0x02 + 0x64
- - 0x00 + + 0x00
- +
- 0x02 - 0x64 + 0x02 + 0x64
- - 0x00 - + + 0x00 +
- +
- 0x02 - 0x65 + 0x02 + 0x65
- +
- 0x02 - 0x65 + 0x02 + 0x65
- +
- +
- 0x02 - 0x66 + 0x02 + 0x66
- - - + + +
- +
- 0x02 - 0x66 + 0x02 + 0x66
- - - - + + + +
- +
- 0x02 - 0x67 + 0x02 + 0x67
- +
- 0x02 - 0x67 + 0x02 + 0x67
- +
- +
- 0x02 - 0x68 + 0x02 + 0x68
- +
- +
- 0x02 - 0x68 + 0x02 + 0x68
- - + +
- +
- 0x02 - 0x69 + 0x02 + 0x69
- +
- 0x02 - 0x69 + 0x02 + 0x69
- +
- +
- 0x02 - 0x6a + 0x02 + 0x6a
- +
- 0x02 - 0x6a + 0x02 + 0x6a
- +
- +
- 0x02 - 0x6f + 0x02 + 0x6f
-
+
- +
- 0x02 - 0x6f + 0x02 + 0x6f
-
+
- + - +
- 0x02 - 0x77 + 0x02 + 0x77
- +
- 0x02 - 0x77 + 0x02 + 0x77
- +
- +
- 0x02 - 0x7F + 0x02 + 0x7F
- +
diff --git a/bundles/org.openhab.binding.ipp/pom.xml b/bundles/org.openhab.binding.ipp/pom.xml index 3ad7c62b517fd..7d099b64db127 100644 --- a/bundles/org.openhab.binding.ipp/pom.xml +++ b/bundles/org.openhab.binding.ipp/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.ipp @@ -24,15 +26,15 @@ compile - org.simpleframework - simple-xml - 2.7.1 - compile + org.simpleframework + simple-xml + 2.7.1 + compile - xmlpull - xmlpull - 1.1.3.1 + xmlpull + xmlpull + 1.1.3.1 commons-io diff --git a/bundles/org.openhab.binding.ipp/src/main/feature/feature.xml b/bundles/org.openhab.binding.ipp/src/main/feature/feature.xml index d6f3bf93935e1..6a4f223a1150c 100644 --- a/bundles/org.openhab.binding.ipp/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.ipp/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - mvn:org.openhab.addons.bundles/org.openhab.binding.ipp/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + mvn:org.openhab.addons.bundles/org.openhab.binding.ipp/${project.version} + diff --git a/bundles/org.openhab.binding.ipp/src/main/java/org/openhab/binding/ipp/internal/handler/IppPrinterHandler.java b/bundles/org.openhab.binding.ipp/src/main/java/org/openhab/binding/ipp/internal/handler/IppPrinterHandler.java index 33c514054bae4..60595d1298e8b 100644 --- a/bundles/org.openhab.binding.ipp/src/main/java/org/openhab/binding/ipp/internal/handler/IppPrinterHandler.java +++ b/bundles/org.openhab.binding.ipp/src/main/java/org/openhab/binding/ipp/internal/handler/IppPrinterHandler.java @@ -172,5 +172,4 @@ public Collection removeOlderResults(DiscoveryService source, long tim Collection thingTypeUIDs, ThingUID bridgeUID) { return Collections.emptyList(); } - } diff --git a/bundles/org.openhab.binding.ipp/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.ipp/src/main/resources/ESH-INF/binding/binding.xml index 573c0d3103df1..dd73b4c15dbd8 100644 --- a/bundles/org.openhab.binding.ipp/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.ipp/src/main/resources/ESH-INF/binding/binding.xml @@ -1,12 +1,12 @@ - + IPP Binding This is the binding for the Internet Printing Protocol (IPP). You can - show how many jobs are done/waiting on an IPP/CUPS Printer + show how many jobs are done/waiting + on an IPP/CUPS Printer Tobias Braeutigam diff --git a/bundles/org.openhab.binding.ipp/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.ipp/src/main/resources/ESH-INF/thing/thing-types.xml index f0661f3d59492..554fdccdf0ce4 100644 --- a/bundles/org.openhab.binding.ipp/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.ipp/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,6 +1,5 @@ - @@ -8,9 +7,9 @@ A IPP Printer - - - + + + diff --git a/bundles/org.openhab.binding.irtrans/pom.xml b/bundles/org.openhab.binding.irtrans/pom.xml index ec7343b38e85a..2e3f65b2cd1a8 100644 --- a/bundles/org.openhab.binding.irtrans/pom.xml +++ b/bundles/org.openhab.binding.irtrans/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.irtrans diff --git a/bundles/org.openhab.binding.irtrans/src/main/feature/feature.xml b/bundles/org.openhab.binding.irtrans/src/main/feature/feature.xml index babf7b7bf1a41..56856dfe10aad 100644 --- a/bundles/org.openhab.binding.irtrans/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.irtrans/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.irtrans/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.irtrans/${project.version} + diff --git a/bundles/org.openhab.binding.irtrans/src/main/java/org/openhab/binding/irtrans/internal/handler/BlasterHandler.java b/bundles/org.openhab.binding.irtrans/src/main/java/org/openhab/binding/irtrans/internal/handler/BlasterHandler.java index 082cdc2670cfd..629c3d0b73b22 100644 --- a/bundles/org.openhab.binding.irtrans/src/main/java/org/openhab/binding/irtrans/internal/handler/BlasterHandler.java +++ b/bundles/org.openhab.binding.irtrans/src/main/java/org/openhab/binding/irtrans/internal/handler/BlasterHandler.java @@ -22,8 +22,8 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.irtrans.internal.IrCommand; import org.openhab.binding.irtrans.internal.IRtransBindingConstants.Led; +import org.openhab.binding.irtrans.internal.IrCommand; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/binding/binding.xml index 0ebdf77abc4e4..5e6b3c06ce483 100644 --- a/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - IRtrans Binding diff --git a/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/thing/blaster.xml b/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/thing/blaster.xml index 465c1b1ca7369..af912655533be 100644 --- a/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/thing/blaster.xml +++ b/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/thing/blaster.xml @@ -1,19 +1,20 @@ - - + This is an infrared transmitter that can send infrared commands - + @@ -24,12 +25,14 @@ - The remote or manufacturer name which's commands will be allowed, as defined in the IRtrans server database and flashed into the transceiver. Can be '*' for any remote + The remote or manufacturer name which's commands will be allowed, as defined in the IRtrans server + database and flashed into the transceiver. Can be '*' for any remote - The name of the command will be allowed, as defined in the IRtrans server database and flashed into the transceiver. Can be '*' for any command + The name of the command will be allowed, as defined in the IRtrans server database and flashed into the + transceiver. Can be '*' for any command diff --git a/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/thing/ethernetbridge.xml b/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/thing/ethernetbridge.xml index f1bc118ae4ec2..60e3df21c2d42 100644 --- a/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/thing/ethernetbridge.xml +++ b/bundles/org.openhab.binding.irtrans/src/main/resources/ESH-INF/thing/ethernetbridge.xml @@ -1,5 +1,6 @@ - @@ -44,7 +45,8 @@ String - The Blaster Channel allows to send (filtered) infrared commands over the specified blaster led of the transceiver + The Blaster Channel allows to send (filtered) infrared commands over the specified blaster led of the + transceiver @@ -52,11 +54,13 @@ - The remote or manufacturer name which's commands will be allowed, as defined in the IRtrans server database and flashed into the transceiver. Can be '*' for any remote + The remote or manufacturer name which's commands will be allowed, as defined in the IRtrans server + database and flashed into the transceiver. Can be '*' for any remote - The name of the command will be allowed, as defined in the IRtrans server database and flashed into the transceiver. Can be '*' for any command + The name of the command will be allowed, as defined in the IRtrans server database and flashed into the + transceiver. Can be '*' for any command @@ -64,15 +68,18 @@ String - The Receiver Channel allows to receive (filtered) infrared commands on the receiver led of the transceiver + The Receiver Channel allows to receive (filtered) infrared commands on the receiver led of the + transceiver - The remote or manufacturer name which's commands will be allowed, as defined in the IRtrans server database and flashed into the transceiver. Can be '*' for any remote + The remote or manufacturer name which's commands will be allowed, as defined in the IRtrans server + database and flashed into the transceiver. Can be '*' for any remote - The name of the command will be allowed, as defined in the IRtrans server database and flashed into the transceiver. Can be '*' for any command + The name of the command will be allowed, as defined in the IRtrans server database and flashed into the + transceiver. Can be '*' for any command diff --git a/bundles/org.openhab.binding.jeelink/pom.xml b/bundles/org.openhab.binding.jeelink/pom.xml index 83dd93f6d011b..5d1b819a35789 100644 --- a/bundles/org.openhab.binding.jeelink/pom.xml +++ b/bundles/org.openhab.binding.jeelink/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.jeelink diff --git a/bundles/org.openhab.binding.jeelink/src/main/feature/feature.xml b/bundles/org.openhab.binding.jeelink/src/main/feature/feature.xml index 2af682e8814fe..d2a4d28dac53a 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.jeelink/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.jeelink/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.jeelink/${project.version} + diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/JeeLinkBindingConstants.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/JeeLinkBindingConstants.java index b4a28cd33966d..d59ccee260e61 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/JeeLinkBindingConstants.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/JeeLinkBindingConstants.java @@ -70,7 +70,7 @@ private JeeLinkBindingConstants() { public static final String ELECTRIC_CURRENT_CHANNEL = "electricCurrent"; public static final String ELECTRIC_POTENTIAL_CHANNEL = "electricPotential"; public static final String FREQUENCY_CHANNEL = "powerFrequency"; - + // List of all additional channel ids for tx22 sensor things public static final String PRESSURE_CHANNEL = "pressure"; public static final String RAIN_CHANNEL = "rain"; diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/JeeLinkHandler.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/JeeLinkHandler.java index bbdc7dc97c0d2..08a7646d14881 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/JeeLinkHandler.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/JeeLinkHandler.java @@ -29,10 +29,13 @@ import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.thing.binding.BridgeHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.jeelink.internal.config.JeeLinkConfig; -import org.openhab.binding.jeelink.internal.connection.AbstractJeeLinkConnection; import org.openhab.binding.jeelink.internal.connection.ConnectionListener; import org.openhab.binding.jeelink.internal.connection.JeeLinkConnection; +import org.openhab.binding.jeelink.internal.connection.JeeLinkSerialConnection; +import org.openhab.binding.jeelink.internal.connection.JeeLinkTcpConnection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,11 +47,12 @@ public class JeeLinkHandler extends BaseBridgeHandler implements BridgeHandler, ConnectionListener { private final Logger logger = LoggerFactory.getLogger(JeeLinkHandler.class); - private JeeLinkConnection connection; - private List> converters = new ArrayList<>(); - private Map> sensorTypeConvertersMap = new HashMap<>(); - private Map, Set>> readingClassHandlerMap = new HashMap<>(); + private final List> converters = new ArrayList<>(); + private final Map> sensorTypeConvertersMap = new HashMap<>(); + private final Map, Set>> readingClassHandlerMap = new HashMap<>(); + private final SerialPortManager serialPortManager; + private JeeLinkConnection connection; private AtomicBoolean connectionInitialized = new AtomicBoolean(false); private ScheduledFuture connectJob; private ScheduledFuture initJob; @@ -56,19 +60,30 @@ public class JeeLinkHandler extends BaseBridgeHandler implements BridgeHandler, private long lastReadingTime; private ScheduledFuture monitorJob; - public JeeLinkHandler(Bridge bridge) { + public JeeLinkHandler(Bridge bridge, SerialPortManager serialPortManager) { super(bridge); + this.serialPortManager = serialPortManager; } @Override public void initialize() { JeeLinkConfig cfg = getConfig().as(JeeLinkConfig.class); - try { - connection = AbstractJeeLinkConnection.createFor(cfg, scheduler, this); + if (cfg.serialPort != null && cfg.baudRate != null) { + SerialPortIdentifier serialPortIdentifier = serialPortManager.getIdentifier(cfg.serialPort); + if (serialPortIdentifier == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Port not found: " + cfg.serialPort); + return; + } + connection = new JeeLinkSerialConnection(serialPortIdentifier, cfg.baudRate, this); + connection.openConnection(); + } else if (cfg.ipAddress != null && cfg.port != null) { + connection = new JeeLinkTcpConnection(cfg.ipAddress + ":" + cfg.port, scheduler, this); connection.openConnection(); - } catch (java.net.ConnectException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage()); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Connection configuration incomplete"); } } @@ -151,10 +166,10 @@ public void addReadingHandler(ReadingHandler h) { Set> handlers = readingClassHandlerMap.get(h.getReadingClass()); if (handlers == null) { handlers = new HashSet<>(); - + // this is the first handler for this reading class => also setup converter readingClassHandlerMap.put(h.getReadingClass(), handlers); - + if (SensorDefinition.ALL_TYPE == h.getSensorType()) { converters.addAll(SensorDefinition.getDiscoveryConverters()); } else { @@ -184,7 +199,7 @@ public void removeReadingHandler(ReadingHandler h) { if (handlers.isEmpty()) { // this was the last handler for this reading class => also remove converter readingClassHandlerMap.remove(h.getReadingClass()); - + if (SensorDefinition.ALL_TYPE == h.getSensorType()) { converters.removeAll(SensorDefinition.getDiscoveryConverters()); } else { @@ -205,11 +220,11 @@ public void handleCommand(ChannelUID channelUid, Command command) { @Override public void handleInput(String input) { lastReadingTime = System.currentTimeMillis(); - + // try all associated converters to find the correct one for (JeeLinkReadingConverter c : converters) { Reading r = c.createReading(input); - + if (r != null) { // this converter is responsible intializeConnection(); @@ -217,12 +232,12 @@ public void handleInput(String input) { // propagate to the appropriate sensor handler synchronized (readingClassHandlerMap) { Set> handlers = getAllHandlers(r.getClass()); - + for (ReadingHandler h : handlers) { h.handleReading(r); } } - + break; } } @@ -230,7 +245,7 @@ public void handleInput(String input) { private Set> getAllHandlers(Class readingClass) { Set> handlers = new HashSet<>(); - + Set> typeHandlers = readingClassHandlerMap.get(readingClass); if (typeHandlers != null) { handlers.addAll(typeHandlers); @@ -239,10 +254,10 @@ private Set> getAllHandlers(Class> discoveryServiceRegs = new HashMap<>(); + private final Map> discoveryServiceRegs = new HashMap<>(); + private final SerialPortManager serialPortManager; + + @Activate + public JeeLinkHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUid) { @@ -57,7 +66,7 @@ protected ThingHandler createHandler(Thing thing) { || thingTypeUid.equals(LGW_TCP_STICK_THING_TYPE) || thingTypeUid.equals(LGW_USB_STICK_THING_TYPE)) { logger.debug("creating JeeLinkHandler for thing {}...", thing.getUID().getId()); - handler = new JeeLinkHandler((Bridge) thing); + handler = new JeeLinkHandler((Bridge) thing, serialPortManager); registerSensorDiscoveryService((JeeLinkHandler) handler); } else { handler = SensorDefinition.createHandler(thingTypeUid, thing); diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/SensorDefinition.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/SensorDefinition.java index 7b5ef1cab500c..f545a19262c7f 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/SensorDefinition.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/SensorDefinition.java @@ -35,7 +35,7 @@ */ public abstract class SensorDefinition { public static final String ALL_TYPE = "All"; - + private static final Set> SENSOR_DEFS = Stream .of(new LaCrosseSensorDefinition(), new Ec3kSensorDefinition(), new Pca301SensorDefinition(), new Tx22SensorDefinition(), new RevoltSensorDefinition(), new LgwSensorDefinition()) diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/AbstractJeeLinkConnection.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/AbstractJeeLinkConnection.java index 54ad884089cf4..551e3e8af3a5e 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/AbstractJeeLinkConnection.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/AbstractJeeLinkConnection.java @@ -15,12 +15,8 @@ import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.net.ConnectException; -import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicBoolean; -import org.openhab.binding.jeelink.internal.JeeLinkHandler; -import org.openhab.binding.jeelink.internal.config.JeeLinkConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -90,7 +86,7 @@ public void sendCommands(String commands) { OutputStreamWriter w = new OutputStreamWriter(initStream); for (String cmd : commands.split(";")) { logger.debug("Writing to device on port {}: {} ", port, cmd); - + w.write(cmd + "\n"); } w.flush(); @@ -101,19 +97,4 @@ public void sendCommands(String commands) { notifyAbort("propagate: " + ex.getMessage()); } } - - public static JeeLinkConnection createFor(JeeLinkConfig config, ScheduledExecutorService scheduler, - JeeLinkHandler h) throws ConnectException { - JeeLinkConnection connection; - - if (config.serialPort != null && config.baudRate != null) { - connection = new JeeLinkSerialConnection(config.serialPort, config.baudRate, h); - } else if (config.ipAddress != null && config.port != null) { - connection = new JeeLinkTcpConnection(config.ipAddress + ":" + config.port, scheduler, h); - } else { - throw new ConnectException("Connection configuration incomplete"); - } - - return connection; - } } diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/JeeLinkSerialConnection.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/JeeLinkSerialConnection.java index b889338bece9a..98dd585745f1f 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/JeeLinkSerialConnection.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/connection/JeeLinkSerialConnection.java @@ -18,17 +18,15 @@ import java.io.OutputStream; import java.util.TooManyListenersException; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * Reads lines from serial port and propagates them to registered InputListeners. * @@ -37,16 +35,18 @@ public class JeeLinkSerialConnection extends AbstractJeeLinkConnection { private final Logger logger = LoggerFactory.getLogger(JeeLinkSerialConnection.class); - private int baudRate; - + private final int baudRate; private SerialPort serialPort; + private final SerialPortIdentifier serialPortIdentifier; private boolean open; - public JeeLinkSerialConnection(String portName, int baudRate, ConnectionListener l) { - super(portName, l); + public JeeLinkSerialConnection(SerialPortIdentifier serialPortIdentifier, int baudRate, + ConnectionListener listener) { + super(serialPortIdentifier.getName(), listener); - logger.debug("Creating serial connection for port {} with baud rate {}...", portName, baudRate); + logger.debug("Creating serial connection for port {} with baud rate {}...", port, baudRate); this.baudRate = baudRate; + this.serialPortIdentifier = serialPortIdentifier; } @Override @@ -68,11 +68,7 @@ public synchronized void openConnection() { try { if (!open) { logger.debug("Opening serial connection to port {} with baud rate {}...", port, baudRate); - - CommPortIdentifier portIdentifier; - - portIdentifier = CommPortIdentifier.getPortIdentifier(port); - serialPort = portIdentifier.open("openhab", 3000); + serialPort = serialPortIdentifier.open("openhab", 3000); open = true; serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, @@ -101,8 +97,6 @@ public void serialEvent(SerialPortEvent event) { } catch (UnsupportedCommOperationException | IOException | TooManyListenersException ex) { closeConnection(); notifyAbort(ex.getMessage()); - } catch (NoSuchPortException ex) { - notifyAbort("Port not found: " + port); } catch (PortInUseException ex) { notifyAbort("Port in use: " + port); } diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/ec3k/Ec3kSensorDefinition.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/ec3k/Ec3kSensorDefinition.java index 68130e3a6f127..7de200de1057a 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/ec3k/Ec3kSensorDefinition.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/ec3k/Ec3kSensorDefinition.java @@ -43,5 +43,4 @@ public Class getReadingClass() { public JeeLinkSensorHandler createHandler(Thing thing) { return new Ec3kSensorHandler(thing, type); } - } diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwReading.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwReading.java index 669785af8d8e7..4318d440a1628 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwReading.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwReading.java @@ -44,7 +44,7 @@ public Float getTemperature() { public Integer getHumidity() { return humidity; } - + public Integer getPressure() { return pressure; } @@ -63,7 +63,7 @@ public boolean hasTemperature() { @Override public String toString() { - return "sensorId=" + sensorId + ": temp=" + temp + (hasHumidity() ? ", hum=" + humidity : "") + return "sensorId=" + sensorId + ": temp=" + temp + (hasHumidity() ? ", hum=" + humidity : "") + (hasPressure() ? ", pressure=" + pressure : ""); } } diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwReadingConverter.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwReadingConverter.java index 516f7053e3ed8..9ba06c9e9e772 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwReadingConverter.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwReadingConverter.java @@ -35,21 +35,24 @@ public LgwReading createReading(String inputLine) { if (inputLine != null) { Matcher matcher = LINE_P.matcher(inputLine); if (matcher.matches()) { - /* Format - OK WS 71 4 4 203 53 255 255 255 255 255 255 255 255 0 3 219 255 255 255 255 255 255 255 255 255 - OK WS 75 4 4 195 61 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 255 - OK WS 213 4 5 126 40 255 255 255 255 255 255 255 255 0 40 53 0 48 57 - OK WS ID XXX TTT TTT HHH RRR RRR DDD DDD SSS SSS GGG GGG FFF PPP PPP GAS GAS GAS DEB DEB DEB LUX LUX LUX - | | | | | | | | | | | | | | | | | |-------------------------------------- Pressure LSB - | | | | | | | | | | | | | | | | |------------------------------------------ Pressure MSB - | | | | | | | | | | | | | | | |-- Fix 0 - | | | | | | |-------------------------------------- Humidity (1 ... 99 %rH) FF = none - | | | | | |------------------------------------------ Temp * 10 + 1000 LSB (-40 ... +60 °C) FF/FF = none - | | | | |---------------------------------------------- Temp * 10 + 1000 MSB - | | | |-------------------------------------------------- fix "4" - | | |------------------------------------------------------ Sensor ID (1 ... 63) - | |--------------------------------------------------------- fix "WS" - |------------------------------------------------------------ fix "OK" + /* + * Format + * OK WS 71 4 4 203 53 255 255 255 255 255 255 255 255 0 3 219 255 255 255 255 255 255 255 255 255 + * OK WS 75 4 4 195 61 255 255 255 255 255 255 255 255 0 255 255 255 255 255 255 255 255 255 255 255 + * OK WS 213 4 5 126 40 255 255 255 255 255 255 255 255 0 40 53 0 48 57 + * OK WS ID XXX TTT TTT HHH RRR RRR DDD DDD SSS SSS GGG GGG FFF PPP PPP GAS GAS GAS DEB DEB DEB LUX LUX + * LUX + * | | | | | | | | | | | | | | | | | |-------------------------------------- Pressure LSB + * | | | | | | | | | | | | | | | | |------------------------------------------ Pressure MSB + * | | | | | | | | | | | | | | | |-- Fix 0 + * | | | | | | |-------------------------------------- Humidity (1 ... 99 %rH) FF = none + * | | | | | |------------------------------------------ Temp * 10 + 1000 LSB (-40 ... +60 °C) FF/FF = + * none + * | | | | |---------------------------------------------- Temp * 10 + 1000 MSB + * | | | |-------------------------------------------------- fix "4" + * | | |------------------------------------------------------ Sensor ID (1 ... 63) + * | |--------------------------------------------------------- fix "WS" + * |------------------------------------------------------------ fix "OK" */ logger.trace("Creating reading from: {}", inputLine); @@ -57,7 +60,7 @@ public LgwReading createReading(String inputLine) { Float temperature = "255".equals(matcher.group(2)) ? null : (float) (Integer.parseInt(matcher.group(2)) * 256 + Integer.parseInt(matcher.group(3)) - 1000) - / 10; + / 10; Integer humidity = "255".equals(matcher.group(4)) ? null : Integer.parseInt(matcher.group(4)); diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwSensorHandler.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwSensorHandler.java index eab696412f284..f3b737f230aea 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwSensorHandler.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/lacrosse/LgwSensorHandler.java @@ -71,17 +71,17 @@ public void publish(LgwReading reading) { updateState(TEMPERATURE_CHANNEL, new QuantityType<>(temp, SIUnits.CELSIUS)); } - if (reading.hasHumidity()) { if (!hasHumidityChannel) { ThingBuilder thingBuilder = editThing(); thingBuilder.withChannel(ChannelBuilder .create(new ChannelUID(getThing().getUID(), HUMIDITY_CHANNEL), "Number:Humidity") - .withType(new ChannelTypeUID(getThing().getThingTypeUID().getBindingId(), HUMIDITY_CHANNEL)) + .withType(new ChannelTypeUID(getThing().getThingTypeUID().getBindingId(), + HUMIDITY_CHANNEL)) .withLabel(StringUtils.capitalize(HUMIDITY_CHANNEL)).build()); updateThing(thingBuilder.build()); - hasHumidityChannel=true; + hasHumidityChannel = true; } updateState(HUMIDITY_CHANNEL, @@ -93,11 +93,12 @@ public void publish(LgwReading reading) { ThingBuilder thingBuilder = editThing(); thingBuilder.withChannel(ChannelBuilder .create(new ChannelUID(getThing().getUID(), PRESSURE_CHANNEL), "Number:Pressure") - .withType(new ChannelTypeUID(getThing().getThingTypeUID().getBindingId(), PRESSURE_CHANNEL)) + .withType(new ChannelTypeUID(getThing().getThingTypeUID().getBindingId(), + PRESSURE_CHANNEL)) .withLabel(StringUtils.capitalize(PRESSURE_CHANNEL)).build()); updateThing(thingBuilder.build()); - hasPressureChannel=true; + hasPressureChannel = true; } updateState(PRESSURE_CHANNEL, new QuantityType<>(reading.getPressure(), HECTO(SIUnits.PASCAL))); diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/pca301/Pca301SensorDefinition.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/pca301/Pca301SensorDefinition.java index b9abbbd8c2b34..58f63a04750ef 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/pca301/Pca301SensorDefinition.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/pca301/Pca301SensorDefinition.java @@ -43,5 +43,4 @@ public Class getReadingClass() { public JeeLinkSensorHandler createHandler(Thing thing) { return new Pca301SensorHandler(thing, type); } - } diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltReading.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltReading.java index 161ff784254a2..ce255e936c422 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltReading.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltReading.java @@ -41,8 +41,8 @@ public RevoltReading(String sensorId, int voltage, float current, int frequency, @Override public String toString() { - return "sensorId=" + sensorId + ": voltage=" + voltage + ", current=" + current + ", frequency=" + frequency + - ", power=" + power + ", powerFact=" + powerFact + ", consumption=" + consumption; + return "sensorId=" + sensorId + ": voltage=" + voltage + ", current=" + current + ", frequency=" + frequency + + ", power=" + power + ", powerFact=" + powerFact + ", consumption=" + consumption; } @Override diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltReadingConverter.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltReadingConverter.java index f51ba4eeeafa1..628a300da0c83 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltReadingConverter.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltReadingConverter.java @@ -35,14 +35,14 @@ public RevoltReading createReading(String inputLine) { /* * r4F1BE400513206875B312F25 */ - String id = matcher.group(1); // 4F1B - - int voltage = toInt(matcher.group(2)); // 0xE4 = 228 => 228 V - float current = toInt(matcher.group(3)) / 100f; // 0x0051 = 81 => 0,81 A - int frequency = toInt(matcher.group(4)); // 0x32 = 50 => 50 Hz - float power = toInt(matcher.group(5)) / 10f; // 0x0687 = 1671 => 167,1 W - float powerFact = toInt(matcher.group(6)) / 100f; // 0x5B = 91 => 0,91 VA - float consumption = toInt(matcher.group(7)) / 100f; // 0x312F = 12591 => 125,91 Wh + String id = matcher.group(1); // 4F1B + + int voltage = toInt(matcher.group(2)); // 0xE4 = 228 => 228 V + float current = toInt(matcher.group(3)) / 100f; // 0x0051 = 81 => 0,81 A + int frequency = toInt(matcher.group(4)); // 0x32 = 50 => 50 Hz + float power = toInt(matcher.group(5)) / 10f; // 0x0687 = 1671 => 167,1 W + float powerFact = toInt(matcher.group(6)) / 100f; // 0x5B = 91 => 0,91 VA + float consumption = toInt(matcher.group(7)) / 100f; // 0x312F = 12591 => 125,91 Wh return new RevoltReading(id, voltage, current, frequency, power, powerFact, consumption); } @@ -50,7 +50,7 @@ public RevoltReading createReading(String inputLine) { return null; } - + private int toInt(String hex) { Integer i = Integer.parseInt(hex, 16); return i.intValue(); diff --git a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltSensorHandler.java b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltSensorHandler.java index 2ed2f72ecd3c9..ba252ffce77df 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltSensorHandler.java +++ b/bundles/org.openhab.binding.jeelink/src/main/java/org/openhab/binding/jeelink/internal/revolt/RevoltSensorHandler.java @@ -57,13 +57,15 @@ public void publish(RevoltReading reading) { logger.debug( "updating states for thing {}: power={}, powerFactor={}, consumption={}, current={}, voltage={}, frequency={} ", - getThing().getUID().getId(), power, powerFactor, consumption, current, reading.getVoltage(), reading.getFrequency()); + getThing().getUID().getId(), power, powerFactor, consumption, current, reading.getVoltage(), + reading.getFrequency()); updateState(CURRENT_POWER_CHANNEL, new QuantityType<>(power, SmartHomeUnits.WATT)); updateState(POWER_FACTOR_CHANNEL, new DecimalType(powerFactor)); updateState(CONSUMPTION_CHANNEL, new QuantityType<>(consumption, SmartHomeUnits.WATT_HOUR)); updateState(ELECTRIC_CURRENT_CHANNEL, new QuantityType<>(current, SmartHomeUnits.AMPERE)); - updateState(ELECTRIC_POTENTIAL_CHANNEL, new QuantityType<>(reading.getVoltage(), SmartHomeUnits.VOLT)); + updateState(ELECTRIC_POTENTIAL_CHANNEL, + new QuantityType<>(reading.getVoltage(), SmartHomeUnits.VOLT)); updateState(FREQUENCY_CHANNEL, new QuantityType<>(reading.getFrequency(), SmartHomeUnits.HERTZ)); } } diff --git a/bundles/org.openhab.binding.jeelink/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.jeelink/src/main/resources/ESH-INF/binding/binding.xml index 76007509ca346..cbe28ee96e6f6 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.jeelink/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - @text/binding.jeelink.name diff --git a/bundles/org.openhab.binding.jeelink/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.jeelink/src/main/resources/ESH-INF/thing/thing-types.xml index 2c7ea07d8da15..1539455ccdbc1 100644 --- a/bundles/org.openhab.binding.jeelink/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.jeelink/src/main/resources/ESH-INF/thing/thing-types.xml @@ -13,6 +13,7 @@ serial-port + false @text/parameter.serialport.description @@ -49,6 +50,7 @@ serial-port + false @text/parameter.serialportlgw.description @@ -152,20 +154,20 @@ - - - - + + + + @text/thing-type.lacrosse.description - - - - + + + + @@ -211,22 +213,22 @@ - - - - + + + + @text/thing-type.ec3k.description - - - - - - + + + + + + @@ -256,19 +258,19 @@ - - - - + + + + @text/thing-type.pca301.description - - - + + + @@ -292,22 +294,22 @@ - - - - + + + + @text/thing-type.revolt.description - - - - - - + + + + + + @@ -326,24 +328,24 @@ - - - - + + + + @text/thing-type.tx22.description - - - - - - - - + + + + + + + + @text/gust-strength.description @@ -366,17 +368,17 @@ - - - - + + + + @text/thing-type.lgw.description - + @@ -397,7 +399,7 @@ @text/channel-type.wind-angle.description Wind - + @@ -405,7 +407,7 @@ @text/channel-type.wind-strength.description Wind - + @@ -413,7 +415,7 @@ @text/channel-type.rain.description Rain - + @@ -421,7 +423,7 @@ @text/channel-type.pressure.description Pressure - + @@ -429,7 +431,7 @@ Number:Power @text/channel-type.current-power.description - + @@ -437,7 +439,7 @@ Number:Power @text/channel-type.max-power.description - + @@ -445,7 +447,7 @@ Number:Energy @text/channel-type.consumption-total.description - + @@ -453,7 +455,7 @@ Number:Time @text/channel-type.appliance-time.description - + @@ -461,7 +463,7 @@ Number:Time @text/channel-type.sensor-time.description - + @@ -469,7 +471,7 @@ Number @text/channel-type.resets.description - + @@ -478,7 +480,7 @@ @text/channel-type.temperature.description Temperature - + @@ -487,7 +489,7 @@ @text/channel-type.humidity.description Humidity - + @@ -495,7 +497,7 @@ Switch @text/channel-type.battery-new.description - + @@ -504,7 +506,7 @@ @text/channel-type.switching-state.description - + Number:ElectricCurrent @@ -518,14 +520,14 @@ @text/channel-type.power-factor.description - + Number:ElectricPotential @text/channel-type.electric-potential.description - + Number:Frequency diff --git a/bundles/org.openhab.binding.keba/pom.xml b/bundles/org.openhab.binding.keba/pom.xml index 0e8f3a92fddbf..60a4da11e5cae 100644 --- a/bundles/org.openhab.binding.keba/pom.xml +++ b/bundles/org.openhab.binding.keba/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.keba diff --git a/bundles/org.openhab.binding.keba/src/main/feature/feature.xml b/bundles/org.openhab.binding.keba/src/main/feature/feature.xml index be67517836124..561d37933c44f 100644 --- a/bundles/org.openhab.binding.keba/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.keba/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.keba/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.keba/${project.version} + diff --git a/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/handler/KeContactTransceiver.java b/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/handler/KeContactTransceiver.java index eb2e984d679b5..3cae32b000db7 100644 --- a/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/handler/KeContactTransceiver.java +++ b/bundles/org.openhab.binding.keba/src/main/java/org/openhab/binding/keba/internal/handler/KeContactTransceiver.java @@ -398,7 +398,7 @@ protected ByteBuffer send(String message, KeContactHandler handler) { } else { return; } - } catch (InterruptedException e) { + } catch (InterruptedException | ClosedSelectorException e) { Thread.currentThread().interrupt(); return; } diff --git a/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/binding/binding.xml index 9b6a91ef1e81e..f38a763b37fa1 100644 --- a/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Keba Binding This is the binding for Keba EV Charging Stations diff --git a/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/thing/kecontact.xml b/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/thing/kecontact.xml index 17786a3238f97..1739420b74679 100644 --- a/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/thing/kecontact.xml +++ b/bundles/org.openhab.binding.keba/src/main/resources/ESH-INF/thing/kecontact.xml @@ -9,24 +9,24 @@ A KeContact EV Charging Station - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -45,16 +45,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -258,5 +258,5 @@ Authenticate and start a charging session - + diff --git a/bundles/org.openhab.binding.km200/pom.xml b/bundles/org.openhab.binding.km200/pom.xml index ef4c3f5926e95..fe59c134864ec 100644 --- a/bundles/org.openhab.binding.km200/pom.xml +++ b/bundles/org.openhab.binding.km200/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.km200 diff --git a/bundles/org.openhab.binding.km200/src/main/feature/feature.xml b/bundles/org.openhab.binding.km200/src/main/feature/feature.xml index 31c128009bdb6..6446b8753135e 100644 --- a/bundles/org.openhab.binding.km200/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.km200/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - mvn:org.openhab.addons.bundles/org.openhab.binding.km200/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + mvn:org.openhab.addons.bundles/org.openhab.binding.km200/${project.version} + diff --git a/bundles/org.openhab.binding.km200/src/main/java/org/openhab/binding/km200/internal/KM200Comm.java b/bundles/org.openhab.binding.km200/src/main/java/org/openhab/binding/km200/internal/KM200Comm.java index 45e33d87adcc8..dcd7b367af39a 100644 --- a/bundles/org.openhab.binding.km200/src/main/java/org/openhab/binding/km200/internal/KM200Comm.java +++ b/bundles/org.openhab.binding.km200/src/main/java/org/openhab/binding/km200/internal/KM200Comm.java @@ -145,6 +145,5 @@ public Integer sendDataToService(String service, byte[] data) { logger.debug("Call to {} {} timed out.", remoteDevice.getIP4Address(), service); } return rCode; - } } diff --git a/bundles/org.openhab.binding.km200/src/main/java/org/openhab/binding/km200/internal/KM200Device.java b/bundles/org.openhab.binding.km200/src/main/java/org/openhab/binding/km200/internal/KM200Device.java index d25c627544f87..972274bbd1ad5 100644 --- a/bundles/org.openhab.binding.km200/src/main/java/org/openhab/binding/km200/internal/KM200Device.java +++ b/bundles/org.openhab.binding.km200/src/main/java/org/openhab/binding/km200/internal/KM200Device.java @@ -188,7 +188,6 @@ public void listAllServices() { logger.debug("readable;writeable;recordable;virtual;type;service;value;allowed;min;max;unit"); printAllServices(serviceTreeMap); logger.debug("##################################################################"); - } /** diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/binding/binding.xml index 7bf490b7a1780..7001d295d6ba2 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/binding/binding.xml @@ -1,12 +1,13 @@ - + KM200 Binding - The KM200 Binding is communicating with a Buderus Logamatic web KM200 / KM100 / KM50 gateway. - These devices are gateways for heating systems and allows to control them. It is possible to receive and send parameters. + The KM200 Binding is communicating with a Buderus Logamatic web KM200 / KM100 / KM50 gateway. + These devices + are gateways for heating systems and allows to control them. It is possible to receive and send parameters. + Markus Eckhardt diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/appliance.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/appliance.xml index f1824805b2927..a681c4b7579dc 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/appliance.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/appliance.xml @@ -6,7 +6,7 @@ - + This thing is representing the appliance (The heater inside of this heating system). diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/device.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/device.xml index c68a4d2b06278..d0bfab44f4e99 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/device.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/device.xml @@ -6,7 +6,8 @@ - The KM200 binding is communicating with a Buderus Logamatic web KM200 / KM100 / KM50. It is possible to receive and send parameters like string or float values. + The KM200 binding is communicating with a Buderus Logamatic web KM200 / KM100 / KM50. It is possible to + receive and send parameters like string or float values. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/dhwCircuit.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/dhwCircuit.xml index 60dfb1941c3e8..8dbea321506bf 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/dhwCircuit.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/dhwCircuit.xml @@ -6,7 +6,7 @@ - + This thing is representing a hot water circuit. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/gateway.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/gateway.xml index c9d45388345a5..02d186ef8ccc1 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/gateway.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/gateway.xml @@ -6,7 +6,7 @@ - + This thing is representing the gateway. (The connected KM200/100/50 device) diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/heatSource.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/heatSource.xml index b6d706ca1d5cf..bc05add0af56a 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/heatSource.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/heatSource.xml @@ -6,7 +6,7 @@ - + This thing is representing the heat source. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/heatingCircuit.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/heatingCircuit.xml index 0b7230b35de7c..41bfb081b23f3 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/heatingCircuit.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/heatingCircuit.xml @@ -6,7 +6,7 @@ - + This thing is representing a heating circuit. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/holidayMode.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/holidayMode.xml index be7dfd404a6f9..b03c69a6c63ca 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/holidayMode.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/holidayMode.xml @@ -6,7 +6,7 @@ - + This thing is representing the holiday modes configuration. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/notification.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/notification.xml index e128e9bc84c79..6460aff2e3b95 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/notification.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/notification.xml @@ -6,7 +6,7 @@ - + This thing is representing the notifications. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/sensor.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/sensor.xml index b9b0657b853c6..c9da80b9927ee 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/sensor.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/sensor.xml @@ -6,7 +6,7 @@ - + This thing is representing the sensors. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/solarCircuit.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/solarCircuit.xml index 05df815cd2b0d..f8077093d666b 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/solarCircuit.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/solarCircuit.xml @@ -6,7 +6,7 @@ - + This thing is representing a solar circuit. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/switchProgram.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/switchProgram.xml index 9257318ddfcd5..d38bb6155ddc5 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/switchProgram.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/switchProgram.xml @@ -6,12 +6,12 @@ - + This thing is representing a switch program. - + diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/system.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/system.xml index 6184248157c7b..5f577e41a2662 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/system.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/system.xml @@ -6,7 +6,7 @@ - + This thing is representing the system without sensors and appliance. diff --git a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/systemStates.xml b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/systemStates.xml index f9a7965eca61a..2205266ff02f0 100644 --- a/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/systemStates.xml +++ b/bundles/org.openhab.binding.km200/src/main/resources/ESH-INF/thing/systemStates.xml @@ -6,7 +6,7 @@ - + This thing is representing the systems states. diff --git a/bundles/org.openhab.binding.knx/pom.xml b/bundles/org.openhab.binding.knx/pom.xml index b8e1a9760bc89..c9f46849bdeee 100644 --- a/bundles/org.openhab.binding.knx/pom.xml +++ b/bundles/org.openhab.binding.knx/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.knx @@ -13,7 +15,7 @@ openHAB Add-ons :: Bundles :: KNX Binding - javax.microedition.io.*;resolution:="optional",javax.usb.*;resolution:="optional",org.usb4java.*;resolution:="optional" + gnu.io;version="[3.12,6)",javax.microedition.io.*;resolution:="optional",javax.usb.*;resolution:="optional",org.usb4java.*;resolution:="optional" diff --git a/bundles/org.openhab.binding.knx/src/main/feature/feature.xml b/bundles/org.openhab.binding.knx/src/main/feature/feature.xml index e004818d86b39..2cf3b869c0191 100644 --- a/bundles/org.openhab.binding.knx/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.knx/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.knx/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.knx/${project.version} + diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXBindingConstants.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXBindingConstants.java index 8ade2ed862250..1b66cbf4fa735 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXBindingConstants.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXBindingConstants.java @@ -95,5 +95,4 @@ public class KNXBindingConstants { public static final String STOP_MOVE_GA = "stopMove"; public static final String SWITCH_GA = "switch"; public static final String UP_DOWN_GA = "upDown"; - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXTypeMapper.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXTypeMapper.java index 378cb3e7b4a62..56a11337d400c 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXTypeMapper.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXTypeMapper.java @@ -53,5 +53,4 @@ public interface KNXTypeMapper { @Nullable public Class toTypeClass(@Nullable String dpt); - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/AbstractSpec.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/AbstractSpec.java index a6ec05d3c220f..c1eaec52373d1 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/AbstractSpec.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/AbstractSpec.java @@ -64,5 +64,4 @@ protected final GroupAddress toGroupAddress(GroupAddressConfiguration ga) { public final String getDPT() { return dpt; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ChannelConfiguration.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ChannelConfiguration.java index 8c8a6d48b6c70..9adf1aeabb6ef 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ChannelConfiguration.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ChannelConfiguration.java @@ -55,5 +55,4 @@ public List getListenGAs() { public List getReadGAs() { return getListenGAs().stream().filter(ga -> ga.isRead()).collect(toList()); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/GroupAddressConfiguration.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/GroupAddressConfiguration.java index 61e59356bd04b..038733b6f78a5 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/GroupAddressConfiguration.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/GroupAddressConfiguration.java @@ -49,5 +49,4 @@ public String getGA() { public boolean isRead() { return read; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelType.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelType.java index b8e009ecb3b2d..2856466984790 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelType.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelType.java @@ -212,5 +212,4 @@ public final List getReadSpec(Configuration configuration) throws K public String toString() { return channelTypeIDs.toString(); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelTypes.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelTypes.java index 05bd8477af9df..da42468c1093a 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelTypes.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/KNXChannelTypes.java @@ -56,5 +56,4 @@ public static KNXChannelType getType(@Nullable ChannelTypeUID channelTypeUID) th } throw new IllegalArgumentException(channelTypeUID.getId() + " is not a valid value channel type ID"); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ListenSpecImpl.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ListenSpecImpl.java index d5743438171b9..026f2ae80e55d 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ListenSpecImpl.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ListenSpecImpl.java @@ -45,5 +45,4 @@ public ListenSpecImpl(@Nullable ChannelConfiguration channelConfiguration, Strin public List getGroupAddresses() { return listenAddresses; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ReadRequestSpecImpl.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ReadRequestSpecImpl.java index 12ff69ad25b3e..dda4f4a36e3c5 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ReadRequestSpecImpl.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ReadRequestSpecImpl.java @@ -47,5 +47,4 @@ public ReadRequestSpecImpl(@Nullable ChannelConfiguration channelConfiguration, public List getGroupAddresses() { return readAddresses; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ReadResponseSpecImpl.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ReadResponseSpecImpl.java index 70c599ebeef26..1bc33a6389f99 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ReadResponseSpecImpl.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/ReadResponseSpecImpl.java @@ -50,5 +50,4 @@ public ReadResponseSpecImpl(@Nullable ChannelConfiguration channelConfiguration, public Type getType() { return type; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeContact.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeContact.java index b36926522a605..1e935515a397c 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeContact.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeContact.java @@ -43,5 +43,4 @@ protected Set getAllGAKeys() { protected String getDefaultDPT(String gaConfigKey) { return DPTXlatorBoolean.DPT_OPENCLOSE.getID(); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDateTime.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDateTime.java index 0dcb7ea605711..80fd933b006bb 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDateTime.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDateTime.java @@ -43,5 +43,4 @@ protected Set getAllGAKeys() { protected String getDefaultDPT(String gaConfigKey) { return DPTXlatorDateTime.DPT_DATE_TIME.getID(); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeNumber.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeNumber.java index 1ee1eae73c070..c5404bc591efd 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeNumber.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeNumber.java @@ -41,5 +41,4 @@ protected String getDefaultDPT(String gaConfigKey) { protected Set getAllGAKeys() { return Collections.singleton(GA); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java index fcb26012ff0ff..8e30f5f3cedd6 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java @@ -55,5 +55,4 @@ protected String getDefaultDPT(String gaConfigKey) { protected Set getAllGAKeys() { return Stream.of(UP_DOWN_GA, STOP_MOVE_GA, POSITION_GA).collect(toSet()); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeString.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeString.java index ad7267a753b8f..01ca52914ef49 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeString.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeString.java @@ -43,5 +43,4 @@ protected Set getAllGAKeys() { protected String getDefaultDPT(String gaConfigKey) { return DPTXlatorString.DPT_STRING_8859_1.getID(); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeSwitch.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeSwitch.java index 1e97dee1cb813..0ef7f108ea7f0 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeSwitch.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeSwitch.java @@ -43,5 +43,4 @@ protected Set getAllGAKeys() { protected String getDefaultDPT(String gaConfigKey) { return DPTXlatorBoolean.DPT_SWITCH.getID(); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/WriteSpecImpl.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/WriteSpecImpl.java index dd72b7fa0067b..9dad8d8244eab 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/WriteSpecImpl.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/WriteSpecImpl.java @@ -50,5 +50,4 @@ public Type getType() { public @Nullable GroupAddress getGroupAddress() { return groupAddress; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java index 435cbfd15f810..ff56a5d239f1b 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java @@ -469,7 +469,5 @@ private void sendToKNX(ProcessCommunicationBase communicator, KNXNetworkLink lin } } } - } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/BusMessageListener.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/BusMessageListener.java index d9543ff09508f..661d617fe70d0 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/BusMessageListener.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/BusMessageListener.java @@ -52,5 +52,4 @@ public interface BusMessageListener { */ public void onGroupReadResponse(AbstractKNXClient client, IndividualAddress source, GroupAddress destination, byte[] asdu); - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/CustomKNXNetworkLinkIP.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/CustomKNXNetworkLinkIP.java index 87a4debc28cc3..78fa204c9bc54 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/CustomKNXNetworkLinkIP.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/CustomKNXNetworkLinkIP.java @@ -33,5 +33,4 @@ public class CustomKNXNetworkLinkIP extends KNXNetworkLinkIP { throws KNXException, InterruptedException { super(serviceMode, conn, settings); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInfoClient.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInfoClient.java index 976df0823382e..211ddfea6242a 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInfoClient.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInfoClient.java @@ -36,5 +36,4 @@ public interface DeviceInfoClient { final int propertyId, final int start, final int elements, boolean authenticate, long timeout); public boolean isConnected(); - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInfoClientImpl.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInfoClientImpl.java index e0cf6b499ae23..bc131a4e97b07 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInfoClientImpl.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInfoClientImpl.java @@ -115,5 +115,4 @@ private void authorize(boolean authenticate, Destination destination) throws KNX public boolean isConnected() { return managementClient.isOpen(); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInspector.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInspector.java index 5434c79cc62df..bdd8f513d25e1 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInspector.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/DeviceInspector.java @@ -67,7 +67,6 @@ public Map getProperties() { public Set getGroupAddresses() { return groupAddresses; } - } public DeviceInspector(DeviceInfoClient client, IndividualAddress address) { @@ -131,7 +130,6 @@ private Map readDeviceProperties(IndividualAddress address) { e.getMessage()); } return ret; - } private @Nullable String toHex(byte @Nullable [] input, String separator) { @@ -171,5 +169,4 @@ private int toUnsigned(final byte @Nullable [] data) { value = value << 16 | data[2] & 0xff << 8 | data[3] & 0xff; return value; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/IPClient.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/IPClient.java index 26c9b22aab979..4afa7ba31e7aa 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/IPClient.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/IPClient.java @@ -126,5 +126,4 @@ private KNXnetIPConnection getConnection(int serviceMode, @Nullable InetSocketAd } return conn; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/InboundSpec.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/InboundSpec.java index 4de85a22626f1..bb99c24160a71 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/InboundSpec.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/InboundSpec.java @@ -40,5 +40,4 @@ public interface InboundSpec { * @return a list of group addresses. */ List getGroupAddresses(); - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/KNXClient.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/KNXClient.java index 845509a95b114..099e1bab6b25f 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/KNXClient.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/KNXClient.java @@ -98,5 +98,4 @@ public interface KNXClient { * @throws KNXException if any problem with the communication arises. */ void respondToKNX(OutboundSpec responseSpec) throws KNXException; - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/NoOpClient.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/NoOpClient.java index 26794830bfd11..578897d18348d 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/NoOpClient.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/NoOpClient.java @@ -69,5 +69,4 @@ public void writeToKNX(OutboundSpec commandSpec) throws KNXException { @Override public void respondToKNX(OutboundSpec responseSpec) throws KNXException { } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/OutboundSpec.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/OutboundSpec.java index 57876eb902a0c..6d3d312df77c8 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/OutboundSpec.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/OutboundSpec.java @@ -48,5 +48,4 @@ public interface OutboundSpec { * @return the command/state */ Type getType(); - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/ReadDatapoint.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/ReadDatapoint.java index 9334132fc4b1e..156afd1936384 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/ReadDatapoint.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/ReadDatapoint.java @@ -76,5 +76,4 @@ public boolean equals(Object obj) { } return true; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/SerialClient.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/SerialClient.java index 924b458b4686c..5cb90304845a1 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/SerialClient.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/SerialClient.java @@ -76,5 +76,4 @@ public SerialClient(int autoReconnectPeriod, ThingUID thingUID, int responseTime } } } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/StatusUpdateCallback.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/StatusUpdateCallback.java index df8c4046c4843..c8bb28256d8fb 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/StatusUpdateCallback.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/StatusUpdateCallback.java @@ -38,5 +38,4 @@ public interface StatusUpdateCallback { * @param status */ void updateStatus(ThingStatus status, ThingStatusDetail thingStatusDetail, String message); - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/DeviceConfig.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/DeviceConfig.java index d7a0003ec131f..479c807353c7e 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/DeviceConfig.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/DeviceConfig.java @@ -42,5 +42,4 @@ public BigDecimal getPingInterval() { public BigDecimal getReadInterval() { return readInterval; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/IPBridgeConfiguration.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/IPBridgeConfiguration.java index ed36e5faf1ad9..40832e6c1afdf 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/IPBridgeConfiguration.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/IPBridgeConfiguration.java @@ -52,5 +52,4 @@ public String getLocalIp() { public String getLocalSourceAddr() { return localSourceAddr; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/SerialBridgeConfiguration.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/SerialBridgeConfiguration.java index 0ce69d146b1d7..307b5830ffd4c 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/SerialBridgeConfiguration.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/config/SerialBridgeConfiguration.java @@ -25,5 +25,4 @@ public class SerialBridgeConfiguration extends BridgeConfiguration { public String getSerialPort() { return serialPort; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/factory/KNXHandlerFactory.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/factory/KNXHandlerFactory.java index 8ed3b027470e4..a87cc15ac5e9d 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/factory/KNXHandlerFactory.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/factory/KNXHandlerFactory.java @@ -105,5 +105,4 @@ protected void setNetworkAddressService(NetworkAddressService networkAddressServ protected void unsetNetworkAddressService(NetworkAddressService networkAddressService) { this.networkAddressService = null; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/AbstractKNXThingHandler.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/AbstractKNXThingHandler.java index 2221842f715c4..88f437d0c6e56 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/AbstractKNXThingHandler.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/AbstractKNXThingHandler.java @@ -29,8 +29,8 @@ import org.eclipse.smarthome.core.thing.ThingStatusInfo; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.openhab.binding.knx.internal.client.DeviceInspector; -import org.openhab.binding.knx.internal.client.KNXClient; import org.openhab.binding.knx.internal.client.DeviceInspector.Result; +import org.openhab.binding.knx.internal.client.KNXClient; import org.openhab.binding.knx.internal.config.DeviceConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,7 +51,7 @@ public abstract class AbstractKNXThingHandler extends BaseThingHandler implement private static final int INITIAL_PING_DELAY = 5; private final Logger logger = LoggerFactory.getLogger(AbstractKNXThingHandler.class); - private @Nullable IndividualAddress address; + protected @Nullable IndividualAddress address; private @Nullable Future descriptionJob; private boolean filledDescription = false; private final Random random = new Random(); @@ -217,5 +217,4 @@ protected void detachFromClient() { } } } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceConstants.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceConstants.java index f9873503fbe95..43e0e10b41137 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceConstants.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceConstants.java @@ -43,5 +43,4 @@ private DeviceConstants() { // Property IDs for device information; public static final int HARDWARE_TYPE = 78; - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java index 243a99fd22f43..5f5f92b31b7c0 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java @@ -74,7 +74,6 @@ public class DeviceThingHandler extends AbstractKNXThingHandler { private final Set groupAddressesRespondingSpec = new HashSet<>(); private final Map> readFutures = new HashMap<>(); private final Map> channelFutures = new HashMap<>(); - private @Nullable IndividualAddress address; private int readInterval; public DeviceThingHandler(Thing thing) { @@ -97,6 +96,28 @@ private void initializeGroupAddresses() { }); } + @Override + public void dispose() { + cancelChannelFutures(); + freeGroupAdresses(); + super.dispose(); + } + + private void cancelChannelFutures() { + for (ScheduledFuture future : channelFutures.values()) { + if (future != null && !future.isDone()) { + future.cancel(true); + } + } + channelFutures.clear(); + } + + private void freeGroupAdresses() { + groupAddresses.clear(); + groupAddressesWriteBlockedOnce.clear(); + groupAddressesRespondingSpec.clear(); + } + @Override protected void cancelReadFutures() { for (ScheduledFuture future : readFutures.values()) { @@ -411,5 +432,4 @@ private boolean isDPTSupported(@Nullable String dpt) { private KNXChannelType getKNXChannelType(Channel channel) { return KNXChannelTypes.getType(channel.getChannelTypeUID()); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/Firmware.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/Firmware.java index 705a2d333da8b..ca414cdaa153a 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/Firmware.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/Firmware.java @@ -46,5 +46,4 @@ public static String getName(int code) { } return null; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/GroupAddressListener.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/GroupAddressListener.java index 590165206cf42..94037f0d01877 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/GroupAddressListener.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/GroupAddressListener.java @@ -33,5 +33,4 @@ public interface GroupAddressListener extends BusMessageListener { * @param destination */ public boolean listensTo(GroupAddress destination); - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/IPBridgeThingHandler.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/IPBridgeThingHandler.java index 04514512b9a42..c9d5a36a2dba6 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/IPBridgeThingHandler.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/IPBridgeThingHandler.java @@ -123,5 +123,4 @@ protected KNXClient getClient() { } return ret; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/KNXBridgeBaseThingHandler.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/KNXBridgeBaseThingHandler.java index 42c0d681f3950..a4c911eb5cafc 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/KNXBridgeBaseThingHandler.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/KNXBridgeBaseThingHandler.java @@ -78,5 +78,4 @@ public void updateStatus(ThingStatus status) { public void updateStatus(ThingStatus status, ThingStatusDetail statusDetail, @Nullable String description) { super.updateStatus(status, statusDetail, description); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/SerialBridgeThingHandler.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/SerialBridgeThingHandler.java index 19292521319ea..84cf69018a96c 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/SerialBridgeThingHandler.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/SerialBridgeThingHandler.java @@ -57,5 +57,4 @@ public void dispose() { protected AbstractKNXClient getClient() { return client; } - } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/profiles/KNXProfileAdvisor.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/profiles/KNXProfileAdvisor.java index 4cc49ea40bb1a..d2ab523a79675 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/profiles/KNXProfileAdvisor.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/profiles/KNXProfileAdvisor.java @@ -59,5 +59,4 @@ private ProfileTypeUID getSuggestedProfieTypeUID(ChannelTypeUID channelTypeUID) public static boolean isControl(ChannelTypeUID channelTypeUID) { return CONTROL_CHANNEL_TYPES.contains(channelTypeUID.getId()); } - } diff --git a/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/binding/binding.xml index a1e42ea9fd8a1..18bab196ea2e9 100644 --- a/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - KNX Binding diff --git a/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/config/channelConfig.xml b/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/config/channelConfig.xml index 94f4a2aaffaa2..4f8f11338100c 100644 --- a/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/config/channelConfig.xml +++ b/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/config/channelConfig.xml @@ -1,5 +1,6 @@ - @@ -40,11 +41,12 @@ - Increase/decrease send frequency if dimming should be handled by the binding (in ms) - set to 0 if the KNX device sends them repeatedly itself + Increase/decrease send frequency if dimming should be handled by the binding (in ms) - set to 0 if the + KNX device sends them repeatedly itself 0 - + @@ -91,7 +93,8 @@ - Increase/decrease send frequency if color should be handled by the binding (in ms) - set to 0 if the KNX device sends them repeatedly itself + Increase/decrease send frequency if color should be handled by the binding (in ms) - set to 0 if the KNX + device sends them repeatedly itself 0 diff --git a/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/thing/device.xml b/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/thing/device.xml index c869d4fc29c96..9751c56dae2d2 100644 --- a/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/thing/device.xml +++ b/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/thing/device.xml @@ -6,8 +6,8 @@ - - + + @@ -41,13 +41,13 @@ Switch A channel to manage a generic Group Addresses with a DPT compatible with Switch Items - + Switch Control a switch item via KNX (i.e. the status is not owned by KNX) - + @@ -55,13 +55,13 @@ Dimmer A channel to control a dimmer - + Dimmer Control a dimmer item via KNX (i.e. the status is not owned by KNX) - + @@ -69,13 +69,13 @@ Rollershutter A channel to control a rollershutter - + Rollershutter Control a rollershutter item (i.e. the status is not owned by KNX) - + @@ -83,13 +83,13 @@ Color A channel to control color information (RGB) - + Color Control a color item (i.e. the status is not owned by KNX) - + @@ -97,13 +97,13 @@ Contact A channel to manage a generic Group Addresses with a DPT compatible with Contact Items - + Contact Control a contact item (i.e. the status is not owned by KNX) - + @@ -111,13 +111,13 @@ Number A channel to manage a generic Group Addresses with a DPT compatible with Number Items - + Number Control a number item (i.e. the status is not owned by KNX) - + @@ -125,13 +125,13 @@ String A channel to manage a generic Group Addresses with a DPT compatible with String Items - + String Control a string item (i.e. the status is not owned by KNX) - + @@ -139,13 +139,13 @@ DateTime A channel to manage a generic Group Addresses with a DPT compatible with DateTime Items - + DateTime Control Control a date/time item (i.e. the status is not owned by KNX) - + diff --git a/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/thing/ip.xml b/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/thing/ip.xml index 3a0932b8768fe..36fb253ed5669 100644 --- a/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/thing/ip.xml +++ b/bundles/org.openhab.binding.knx/src/main/resources/ESH-INF/thing/ip.xml @@ -36,7 +36,8 @@ - The Physical Address (Individual Address) in x.y.z notation for identification of this KNX/IP gateway within the KNX bus + The Physical Address (Individual Address) in x.y.z notation for identification of this KNX/IP gateway + within the KNX bus 0.0.0 @@ -60,7 +61,7 @@ Limits the read retries while initialization from the KNX bus 3 - + Seconds between connection retries when KNX link has been lost, 0 means never retry, minimum 30s 60 diff --git a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTypeTest.java b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTypeTest.java index 3de771c22bb9b..f8a161b66f091 100644 --- a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTypeTest.java +++ b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTypeTest.java @@ -109,7 +109,5 @@ public MyKNXChannelType(String channelTypeID) { protected @NonNull String getDefaultDPT(@NonNull String gaConfigKey) { return ""; } - } - } diff --git a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/KNXCoreTypeMapperTest.java b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/KNXCoreTypeMapperTest.java index c69fff45f0b5a..1456e49839ba9 100644 --- a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/KNXCoreTypeMapperTest.java +++ b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/dpt/KNXCoreTypeMapperTest.java @@ -29,5 +29,4 @@ public void testToDPTValue_trailingZeroesStrippedOff() { assertEquals("3", new KNXCoreTypeMapper().toDPTValue(new DecimalType("3"), "17.001")); assertEquals("3", new KNXCoreTypeMapper().toDPTValue(new DecimalType("3.0"), "17.001")); } - } diff --git a/bundles/org.openhab.binding.kodi/pom.xml b/bundles/org.openhab.binding.kodi/pom.xml index 18e7fbf0d6d09..f3c90bc07f701 100644 --- a/bundles/org.openhab.binding.kodi/pom.xml +++ b/bundles/org.openhab.binding.kodi/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.kodi diff --git a/bundles/org.openhab.binding.kodi/src/main/feature/feature.xml b/bundles/org.openhab.binding.kodi/src/main/feature/feature.xml index a483c6b1c465c..2aab955449c8e 100644 --- a/bundles/org.openhab.binding.kodi/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.kodi/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.kodi/${project.version} - + + openhab-runtime-base + openhab-transport-http + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.kodi/${project.version} + diff --git a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/discovery/KodiUpnpDiscoveryParticipant.java b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/discovery/KodiUpnpDiscoveryParticipant.java index 3a3a55d45bd3a..1b6f79f46db1e 100644 --- a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/discovery/KodiUpnpDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/discovery/KodiUpnpDiscoveryParticipant.java @@ -19,7 +19,6 @@ import java.util.Map; import java.util.Set; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.DiscoveryResult; @@ -62,7 +61,7 @@ protected void modified(ComponentContext componentContext) { private void activateOrModifyService(ComponentContext componentContext) { Dictionary properties = componentContext.getProperties(); String autoDiscoveryPropertyValue = (String) properties.get("background"); - if (StringUtils.isNotEmpty(autoDiscoveryPropertyValue)) { + if (autoDiscoveryPropertyValue != null && !autoDiscoveryPropertyValue.isEmpty()) { isAutoDiscoveryEnabled = Boolean.valueOf(autoDiscoveryPropertyValue); } } @@ -77,8 +76,9 @@ public Set getSupportedThingTypeUIDs() { if (isAutoDiscoveryEnabled) { ThingUID thingUid = getThingUID(device); if (thingUid != null) { - String label = StringUtils.isEmpty(device.getDetails().getFriendlyName()) ? device.getDisplayString() - : device.getDetails().getFriendlyName(); + String friendlyName = device.getDetails().getFriendlyName(); + String label = friendlyName == null || friendlyName.isEmpty() ? device.getDisplayString() + : friendlyName; Map properties = new HashMap<>(); properties.put(HOST_PARAMETER, device.getIdentity().getDescriptorURL().getHost()); @@ -94,16 +94,18 @@ public Set getSupportedThingTypeUIDs() { @Override public @Nullable ThingUID getThingUID(RemoteDevice device) { String manufacturer = device.getDetails().getManufacturerDetails().getManufacturer(); - if (StringUtils.containsIgnoreCase(manufacturer, MANUFACTURER)) { - logger.debug("Manufacturer matched: search: {}, device value: {}.", MANUFACTURER, - device.getDetails().getManufacturerDetails().getManufacturer()); - if (StringUtils.containsIgnoreCase(device.getType().getType(), UPNP_DEVICE_TYPE)) { - logger.debug("Device type matched: search: {}, device value: {}.", UPNP_DEVICE_TYPE, - device.getType().getType()); + if (containsIgnoreCase(manufacturer, MANUFACTURER)) { + logger.debug("Manufacturer matched: search: {}, device value: {}.", MANUFACTURER, manufacturer); + String type = device.getType().getType(); + if (containsIgnoreCase(type, UPNP_DEVICE_TYPE)) { + logger.debug("Device type matched: search: {}, device value: {}.", UPNP_DEVICE_TYPE, type); return new ThingUID(THING_TYPE_KODI, device.getIdentity().getUdn().getIdentifierString()); } } return null; } + private boolean containsIgnoreCase(final @Nullable String str, final String searchStr) { + return str != null && str.toLowerCase().contains(searchStr.toLowerCase()); + } } diff --git a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/handler/KodiHandler.java b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/handler/KodiHandler.java index 2f9d63f4bbc55..5a264661a7a2b 100644 --- a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/handler/KodiHandler.java +++ b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/handler/KodiHandler.java @@ -25,7 +25,6 @@ import javax.measure.Unit; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.smarthome.core.library.types.DecimalType; @@ -348,7 +347,8 @@ private URI getImageBaseUrl() throws URISyntaxException { int httpPort = config.getHttpPort(); String httpUser = config.getHttpUser(); String httpPassword = config.getHttpPassword(); - String userInfo = (StringUtils.isEmpty(httpUser) || StringUtils.isEmpty(httpPassword)) ? null + String userInfo = httpUser == null || httpUser.isEmpty() || httpPassword == null || httpPassword.isEmpty() + ? null : String.format("%s:%s", httpUser, httpPassword); return new URI("http", userInfo, host, httpPort, "/image/", null, null); } @@ -366,9 +366,9 @@ private void playFavorite(Command command) { if (favorite != null) { String path = favorite.getPath(); String windowParameter = favorite.getWindowParameter(); - if (StringUtils.isNotEmpty(path)) { + if (path != null && !path.isEmpty()) { connection.playURI(path); - } else if (StringUtils.isNotEmpty(windowParameter)) { + } else if (windowParameter != null && !windowParameter.isEmpty()) { String[] windowParameters = { windowParameter }; connection.activateWindow(favorite.getWindow(), windowParameters); } else { diff --git a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/model/KodiProfile.java b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/model/KodiProfile.java index 42b5e15e96bb0..6d4379916c660 100644 --- a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/model/KodiProfile.java +++ b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/model/KodiProfile.java @@ -1,42 +1,42 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.kodi.internal.model; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * Class representing a Kodi profile (see https://kodi.wiki/view/JSON-RPC_API/v8#Profiles.GetProfiles) - * - * @author Jan Hendriks - Initial contribution - */ -@NonNullByDefault -public class KodiProfile extends KodiBaseItem { - private int lockmode; - private String thumbnail = ""; - - public int getLockmode() { - return lockmode; - } - - public void setLockmode(int lockmode) { - this.lockmode = lockmode; - } - - public String getThumbnail() { - return thumbnail; - } - - public void setThumbnail(String thumbnail) { - this.thumbnail = thumbnail; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.kodi.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Class representing a Kodi profile (see https://kodi.wiki/view/JSON-RPC_API/v8#Profiles.GetProfiles) + * + * @author Jan Hendriks - Initial contribution + */ +@NonNullByDefault +public class KodiProfile extends KodiBaseItem { + private int lockmode; + private String thumbnail = ""; + + public int getLockmode() { + return lockmode; + } + + public void setLockmode(int lockmode) { + this.lockmode = lockmode; + } + + public String getThumbnail() { + return thumbnail; + } + + public void setThumbnail(String thumbnail) { + this.thumbnail = thumbnail; + } +} diff --git a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/model/KodiSubtitle.java b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/model/KodiSubtitle.java index 9b5a6e78e8475..17386de63f708 100644 --- a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/model/KodiSubtitle.java +++ b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/model/KodiSubtitle.java @@ -1,51 +1,51 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.kodi.internal.model; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * Class representing a Kodi subtitle stream (see https://kodi.wiki/view/JSON-RPC_API/v9#Player.Subtitle) - * - * @author Meng Yiqi - Initial contribution - */ -@NonNullByDefault -public class KodiSubtitle { - private int index; - private String language = ""; - private String name = ""; - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - public String getLanguage() { - return language; - } - - public void setLanguage(String language) { - this.language = language; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.kodi.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Class representing a Kodi subtitle stream (see https://kodi.wiki/view/JSON-RPC_API/v9#Player.Subtitle) + * + * @author Meng Yiqi - Initial contribution + */ +@NonNullByDefault +public class KodiSubtitle { + private int index; + private String language = ""; + private String name = ""; + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public String getLanguage() { + return language; + } + + public void setLanguage(String language) { + this.language = language; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiClientSocket.java b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiClientSocket.java index e1c071151a3b9..3b6c5dc4f04da 100644 --- a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiClientSocket.java +++ b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiClientSocket.java @@ -167,7 +167,6 @@ public void onError(Throwable error) { logger.trace("Error occured: {}", error.getMessage()); onClose(0, error.getMessage()); } - } private void sendMessage(String str) throws IOException { diff --git a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiClientSocketEventListener.java b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiClientSocketEventListener.java index bb6e8661ab8ad..c90ef03cb87d3 100644 --- a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiClientSocketEventListener.java +++ b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiClientSocketEventListener.java @@ -26,5 +26,4 @@ public interface KodiClientSocketEventListener { void onConnectionClosed(); void onConnectionOpened(); - } diff --git a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiConnection.java b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiConnection.java index e8e6216c66efd..4df1dd63975d3 100644 --- a/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiConnection.java +++ b/bundles/org.openhab.binding.kodi/src/main/java/org/openhab/binding/kodi/internal/protocol/KodiConnection.java @@ -25,7 +25,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.websocket.client.WebSocketClient; import org.eclipse.smarthome.core.cache.ExpiringCacheMap; @@ -379,10 +378,10 @@ public synchronized List getFavorites() { * @param favoriteTitle the title of the favorite * @return the ({@link KodiFavorite}) with the given title */ - @Nullable - public KodiFavorite getFavorite(final String favoriteTitle) { + public @Nullable KodiFavorite getFavorite(final String favoriteTitle) { for (KodiFavorite favorite : getFavorites()) { - if (StringUtils.equalsIgnoreCase(favorite.getTitle(), favoriteTitle)) { + String title = favorite.getTitle(); + if (favoriteTitle.equalsIgnoreCase(title)) { return favorite; } } @@ -862,7 +861,7 @@ private List convertFromArrayToList(JsonArray data) { // we have to strip ending "/" here because Kodi returns a not valid path and filename // "fanart":"image://http%3a%2f%2fthetvdb.com%2fbanners%2ffanart%2foriginal%2f263365-31.jpg/" // "thumbnail":"image://http%3a%2f%2fthetvdb.com%2fbanners%2fepisodes%2f263365%2f5640869.jpg/" - String encodedURL = URLEncoder.encode(StringUtils.stripEnd(url, "/"), StandardCharsets.UTF_8.name()); + String encodedURL = URLEncoder.encode(stripEnd(url, '/'), StandardCharsets.UTF_8.name()); return imageUri.resolve(encodedURL).toString(); } catch (UnsupportedEncodingException e) { logger.debug("exception during encoding {}", url, e); @@ -870,6 +869,17 @@ private List convertFromArrayToList(JsonArray data) { } } + private String stripEnd(final String str, final char suffix) { + int end = str.length(); + if (end == 0) { + return str; + } + while (end > 0 && str.charAt(end - 1) == suffix) { + end--; + } + return str.substring(0, end); + } + private @Nullable RawType downloadImage(String url) { logger.debug("Trying to download the content of URL '{}'", url); RawType downloadedImage = HttpUtil.downloadImage(url); @@ -1175,7 +1185,8 @@ public synchronized List getPVRChannelGroups(final String p public int getPVRChannelGroupId(final String channelType, final String pvrChannelGroupName) { List pvrChannelGroups = getPVRChannelGroups(channelType); for (KodiPVRChannelGroup pvrChannelGroup : pvrChannelGroups) { - if (StringUtils.equalsIgnoreCase(pvrChannelGroup.getLabel(), pvrChannelGroupName)) { + String label = pvrChannelGroup.getLabel(); + if (pvrChannelGroupName.equalsIgnoreCase(label)) { return pvrChannelGroup.getId(); } } @@ -1214,7 +1225,8 @@ public synchronized List getPVRChannels(final int pvrChannelGrou public int getPVRChannelId(final int pvrChannelGroupId, final String pvrChannelName) { for (KodiPVRChannel pvrChannel : getPVRChannels(pvrChannelGroupId)) { - if (StringUtils.equalsIgnoreCase(pvrChannel.getLabel(), pvrChannelName)) { + String label = pvrChannel.getLabel(); + if (pvrChannelName.equalsIgnoreCase(label)) { return pvrChannel.getId(); } } diff --git a/bundles/org.openhab.binding.kodi/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.kodi/src/main/resources/ESH-INF/thing/thing-types.xml index 7266484f0afa4..b70664295710c 100644 --- a/bundles/org.openhab.binding.kodi/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.kodi/src/main/resources/ESH-INF/thing/thing-types.xml @@ -10,31 +10,31 @@ Kodi Mediacenter Binding - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -51,8 +51,8 @@ Audio codec of currently playing media - - + + @@ -72,10 +72,10 @@ - - - - + + + + media_id in kodi database @@ -104,8 +104,8 @@ example usage - http://www.themoviedb.org/tv/12225/ - - + + @@ -117,7 +117,7 @@ ipAddress - + @@ -140,21 +140,21 @@ String Play the given PVR TV channel by sending a command with the channel's name - - + + String Play the given PVR Radio channel by sending a command with the channel's name - - + + String Shows a notification on the UI - + String @@ -439,7 +439,7 @@ String Comma-separated list of genres of the current file - + Image @@ -457,31 +457,31 @@ String Codec of currently playing media - + Number:Time Current time of currently playing media - + Number:Dimensionless Current time of currently playing media - + Number:Time Length of currently playing media - + Number id in kodi database - + Switch @@ -492,66 +492,66 @@ Number Channels - + Number Video Width - + Number Video Height - + Number stream index - + String Name - + String UniqueID - + String stream Language - + String file path and name - + Number Rating - + String MPAA Rating - + String Profile of Kodi - + diff --git a/bundles/org.openhab.binding.konnected/pom.xml b/bundles/org.openhab.binding.konnected/pom.xml index be7bbfe5f7e96..fa2b3fd0acfc8 100644 --- a/bundles/org.openhab.binding.konnected/pom.xml +++ b/bundles/org.openhab.binding.konnected/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.konnected diff --git a/bundles/org.openhab.binding.konnected/src/main/feature/feature.xml b/bundles/org.openhab.binding.konnected/src/main/feature/feature.xml index ce6d9a129ff7f..eaeefd9b50e02 100644 --- a/bundles/org.openhab.binding.konnected/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.konnected/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.konnected/${project.version} - + + openhab-runtime-base + openhab-transport-http + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.konnected/${project.version} + diff --git a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/KonnectedBindingConstants.java b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/KonnectedBindingConstants.java index 7c85e78bbbb26..075b961d2a0e0 100644 --- a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/KonnectedBindingConstants.java +++ b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/KonnectedBindingConstants.java @@ -59,5 +59,4 @@ public class KonnectedBindingConstants { public static final String CHANNEL_ACTUATOR_PAUSE = "pause"; public static final String CHANNEL_ONVALUE = "onvalue"; - } diff --git a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/KonnectedConfiguration.java b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/KonnectedConfiguration.java index 45359f2aa28e5..0d894f32eb3ee 100644 --- a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/KonnectedConfiguration.java +++ b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/KonnectedConfiguration.java @@ -22,7 +22,7 @@ public class KonnectedConfiguration extends Configuration { /** - * @param blink identifies whether the Konnected Alarm Panel LED will blink on transmission of Wifi Commands + * @param blink identifies whether the Konnected Alarm Panel LED will blink on transmission of Wifi Commands * @param discovery identifies whether the Konnected Alarm Panel will be discoverable via UPnP */ public boolean blink; diff --git a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/gson/KonnectedModulePayload.java b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/gson/KonnectedModulePayload.java index 8a16366b2bc1c..68d76a60d1038 100644 --- a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/gson/KonnectedModulePayload.java +++ b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/gson/KonnectedModulePayload.java @@ -110,5 +110,4 @@ public void setDiscovery(Boolean setDiscovery) { public void setBlink(Boolean setBlink) { this.blink = setBlink; } - } diff --git a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/handler/KonnectedHandler.java b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/handler/KonnectedHandler.java index b26e3e9b33235..1bd2d5e097734 100644 --- a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/handler/KonnectedHandler.java +++ b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/handler/KonnectedHandler.java @@ -520,5 +520,4 @@ private String getOnState(Channel channel) { return config; } } - } diff --git a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/servlet/KonnectedHTTPServlet.java b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/servlet/KonnectedHTTPServlet.java index 2e883c69598cc..dfad5eb49f868 100644 --- a/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/servlet/KonnectedHTTPServlet.java +++ b/bundles/org.openhab.binding.konnected/src/main/java/org/openhab/binding/konnected/internal/servlet/KonnectedHTTPServlet.java @@ -99,5 +99,4 @@ private void setHeaders(HttpServletResponse response) { response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); } - } diff --git a/bundles/org.openhab.binding.konnected/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.konnected/src/main/resources/ESH-INF/config/config.xml index 5451820b401a2..157ecb5b20662 100644 --- a/bundles/org.openhab.binding.konnected/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.konnected/src/main/resources/ESH-INF/config/config.xml @@ -7,7 +7,7 @@ - + @@ -17,19 +17,26 @@ - If set to false the device will not respond to discovery requests via UPnP. Make sure you have statically assigned an IP address to the module before turning this setting off. See https://help.konnected.io/support/solutions/articles/32000023968-disabling-device-discovery + If set to false the device will not respond to discovery requests via UPnP. Make sure you have + statically assigned an IP address to the module before turning this setting off. See + https://help.konnected.io/support/solutions/articles/32000023968-disabling-device-discovery true true - The number of times the binding attempts to send http requests to the Konnected Alarm Panel. Increase this setting if you are experiencing situations where the module is reporting as offline but you can access the website of the Alarm Panel to confirm that the Alarm Panel is Konnected to the Network. This will allow the binding to attempt more retries before it considers the connection a failure and marks the thing as offline. + The number of times the binding attempts to send http requests to the Konnected Alarm Panel. Increase + this setting if you are experiencing situations where the module is reporting as offline but you can access the + website of the Alarm Panel to confirm that the Alarm Panel is Konnected to the Network. This will allow the binding + to attempt more retries before it considers the connection a failure and marks the thing as offline. 2 true - The timeout period in seconds for HTTP requests to the Konnected Alarm Panel. The default is 30. Adjusting this setting can help in networks situations with high latency where the binding is erroneously reporting the thing as offline. + The timeout period in seconds for HTTP requests to the Konnected Alarm Panel. The default is 30. + Adjusting this setting can help in networks situations with high latency where the binding is erroneously reporting + the thing as offline. 30 true @@ -47,7 +54,8 @@ - Manually sends the settings to the module. The binding will send settings on every restart and if there are any configuration changes but this can be used to manually update the settings as needed. + Manually sends the settings to the module. The binding will send settings on every restart and if there + are any configuration changes but this can be used to manually update the settings as needed. true false diff --git a/bundles/org.openhab.binding.konnected/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.konnected/src/main/resources/ESH-INF/thing/thing-types.xml index 8ea88a9992c89..7aa42317d8e4c 100644 --- a/bundles/org.openhab.binding.konnected/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.konnected/src/main/resources/ESH-INF/thing/thing-types.xml @@ -16,14 +16,14 @@ - + Switch This zone is a read only switch type zone - + @@ -41,7 +41,8 @@ - The value that will be treated by the binding as the on value. For sensors that activate with a high value leave at the default of 1 and sensors that activate with a low value set to 0. + The value that will be treated by the binding as the on value. For sensors that activate with a high + value leave at the default of 1 and sensors that activate with a low value set to 0. 1 @@ -54,7 +55,7 @@ Number:Temperature This zone measures temperature - + @@ -87,7 +88,7 @@ Number:Dimensionless This zone measures humidity - + @@ -125,7 +126,8 @@ - The value that will be treated by the binding as an on command. For actuators that activate with a high command set to 1 and actuators that activate with a low value set to 0. + The value that will be treated by the binding as an on command. For actuators that activate with a high + command set to 1 and actuators that activate with a low value set to 0. 1 diff --git a/bundles/org.openhab.binding.kostalinverter/README.md b/bundles/org.openhab.binding.kostalinverter/README.md index 8d01c6ab51f2b..9a3d8ec745919 100644 --- a/bundles/org.openhab.binding.kostalinverter/README.md +++ b/bundles/org.openhab.binding.kostalinverter/README.md @@ -32,6 +32,10 @@ Currently supported things are: Others may be supported (like future devices using the same SCB or offering the same Web API, branded OEM devices, ...), but they were not tested! +Kostal bindings to third generation devices require Java's strong cryptography to be enabled in order to establish connections. In case you are allowed to use +strong cryptography in your country, you can achieve this by modifying the $JAVA_HOME/jre/lib/security/java.security file (find the line *crypto.policy=limited* and set it to *unlimited*). +If you're using the official openHAB docker image you may also enable Java's strong cryptography by specifying an environment variable *CRYPTO_POLICY="unlimited"*. + ## Discovery None diff --git a/bundles/org.openhab.binding.kostalinverter/pom.xml b/bundles/org.openhab.binding.kostalinverter/pom.xml index 92a6e08650b7b..3b7208726427d 100644 --- a/bundles/org.openhab.binding.kostalinverter/pom.xml +++ b/bundles/org.openhab.binding.kostalinverter/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.kostalinverter diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/feature/feature.xml b/bundles/org.openhab.binding.kostalinverter/src/main/feature/feature.xml index de27f2842de5d..a4d722ce5b4b3 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.kostalinverter/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.kostalinverter/${project.version} + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/KostalInverterFactory.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/KostalInverterFactory.java index 0706235229006..66013d8f47557 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/KostalInverterFactory.java +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/KostalInverterFactory.java @@ -102,5 +102,4 @@ protected void setHttpClientFactory(HttpClientFactory httpClientFactory) { protected void unsetHttpClientFactory(HttpClientFactory httpClientFactory) { this.httpClient = null; } - } diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/firstgeneration/WebscrapeHandler.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/firstgeneration/WebscrapeHandler.java index 05c78aed4952c..f3ea1a239c273 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/firstgeneration/WebscrapeHandler.java +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/firstgeneration/WebscrapeHandler.java @@ -130,5 +130,4 @@ private State getState(String value, Unit unit) { } } } - } diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationBindingConstants.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationBindingConstants.java index f797cfc5a27c4..718186d6204af 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationBindingConstants.java +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationBindingConstants.java @@ -141,5 +141,4 @@ public class ThirdGenerationBindingConstants { public static final String CHANNEL_STATISTIC_YIELD_MONTH = "statisticYieldMonth"; public static final String CHANNEL_STATISTIC_YIELD_TOTAL = "statisticYieldTotal"; public static final String CHANNEL_STATISTIC_YIELD_YEAR = "statisticYieldYear"; - } diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationChannelMappingToWebApi.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationChannelMappingToWebApi.java index dd4579570074b..6493527a5e10f 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationChannelMappingToWebApi.java +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationChannelMappingToWebApi.java @@ -28,10 +28,10 @@ class ThirdGenerationChannelMappingToWebApi { /** * Constructor of {@link ThirdGenerationChannelMappingToWebApi} * - * @param channelUID The channel UUID - * @param moduleId module id (as defined by the web api) + * @param channelUID The channel UUID + * @param moduleId module id (as defined by the web api) * @param processdataId process data id (as defined by the web api) - * @param dataType data type of this channel + * @param dataType data type of this channel */ ThirdGenerationChannelMappingToWebApi(String channelUID, String moduleId, String processdataId, ThirdGenerationChannelDatatypes dataType) { diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationEncryptionHelper.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationEncryptionHelper.java index 63ab7feb3658d..4c783597bbfb6 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationEncryptionHelper.java +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationEncryptionHelper.java @@ -40,10 +40,10 @@ private ThirdGenerationEncryptionHelper() { /** * This method generates the HMACSha256 encrypted value of the given value * - * @param password Password used for encryption + * @param password Password used for encryption * @param valueToEncrypt value to encrypt * @return encrypted value - * @throws InvalidKeyException thrown if the key generated from the password is invalid + * @throws InvalidKeyException thrown if the key generated from the password is invalid * @throws NoSuchAlgorithmException thrown if HMAC SHA 256 is not supported */ static byte[] getHMACSha256(byte[] password, String valueToEncrypt) @@ -75,11 +75,11 @@ static String createClientProof(byte[] clientSignature, byte[] serverSignature) * Create the PBKDF2 hash * * @param password password - * @param salt salt - * @param rounds rounds + * @param salt salt + * @param rounds rounds * @return hash * @throws NoSuchAlgorithmException if PBKDF2WithHmacSHA256 is not supported - * @throws InvalidKeySpecException if the key specification is not supported + * @throws InvalidKeySpecException if the key specification is not supported */ static byte[] getPBKDF2Hash(String password, byte[] salt, int rounds) throws NoSuchAlgorithmException, InvalidKeySpecException { diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationHandler.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationHandler.java index 4c33fdf4ffea4..44f1fe5dd2ffb 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationHandler.java +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationHandler.java @@ -482,5 +482,4 @@ private final void authenticate() { updateStatus(ThingStatus.ONLINE); } - } diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationHttpHelper.java b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationHttpHelper.java index f8ef554bef911..0653084d387e3 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationHttpHelper.java +++ b/bundles/org.openhab.binding.kostalinverter/src/main/java/org/openhab/binding/internal/kostal/inverter/thirdgeneration/ThirdGenerationHttpHelper.java @@ -53,12 +53,12 @@ private ThirdGenerationHttpHelper() { * Helper function to execute a HTTP post request * * @param httpClient httpClient to use for communication - * @param url IP or hostname or the device - * @param resource web API resource to post to + * @param url IP or hostname or the device + * @param resource web API resource to post to * @param parameters the JSON content to post * @return the HTTP response for the created post request - * @throws ExecutionException Error during the execution of the http request - * @throws TimeoutException Connection timed out + * @throws ExecutionException Error during the execution of the http request + * @throws TimeoutException Connection timed out * @throws InterruptedException Connection interrupted */ static ContentResponse executeHttpPost(HttpClient httpClient, String url, String resource, JsonObject parameters) @@ -70,13 +70,13 @@ static ContentResponse executeHttpPost(HttpClient httpClient, String url, String * Helper function to execute a HTTP post request * * @param httpClient httpClient to use for communication - * @param url IP or hostname or the device - * @param resource web API resource to post to - * @param sessionId optional session ID + * @param url IP or hostname or the device + * @param resource web API resource to post to + * @param sessionId optional session ID * @param parameters the JSON content to post * @return the HTTP response for the created post request - * @throws ExecutionException Error during the execution of the http request - * @throws TimeoutException Connection timed out + * @throws ExecutionException Error during the execution of the http request + * @throws TimeoutException Connection timed out * @throws InterruptedException Connection interrupted */ static ContentResponse executeHttpPost(HttpClient httpClient, String url, String resource, JsonElement parameters, @@ -96,11 +96,11 @@ static ContentResponse executeHttpPost(HttpClient httpClient, String url, String * Helper function to execute a HTTP get request * * @param httpClient httpClient to use for communication - * @param url IP or hostname or the device - * @param resource web API resource to get + * @param url IP or hostname or the device + * @param resource web API resource to get * @return the HTTP response for the created get request - * @throws ExecutionException Error during the execution of the http request - * @throws TimeoutException Connection timed out + * @throws ExecutionException Error during the execution of the http request + * @throws TimeoutException Connection timed out * @throws InterruptedException Connection interrupted */ static ContentResponse executeHttpGet(HttpClient httpClient, String url, String resource) @@ -112,14 +112,14 @@ static ContentResponse executeHttpGet(HttpClient httpClient, String url, String * Helper function to execute a HTTP get request * * @param httpClient httpClient to use for communication - * @param url IP or hostname or the device - * @param resource web API resource to get - * @param sessionId optional session ID + * @param url IP or hostname or the device + * @param resource web API resource to get + * @param sessionId optional session ID * @return the HTTP response for the created get request - * @throws ExecutionException Error during the execution of the http request - * @throws TimeoutException Connection timed out + * @throws ExecutionException Error during the execution of the http request + * @throws TimeoutException Connection timed out * @throws InterruptedException Connection interrupted - * @throws Exception thrown if there are communication problems + * @throws Exception thrown if there are communication problems */ static ContentResponse executeHttpGet(HttpClient httpClient, String url, String resource, @Nullable String sessionId) throws InterruptedException, TimeoutException, ExecutionException { diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/binding/binding.xml index d71428d583cdb..7107ae0507098 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Kostal Inverter Binding Extracts informations from a Kostal Inverter diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/config/ThirdGeneration.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/config/ThirdGeneration.xml index 33e55d0be29d0..1e773f4233ddf 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/config/ThirdGeneration.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/config/ThirdGeneration.xml @@ -1,12 +1,14 @@ - + network-address - Enter the IP address or the hostname of the inverter. Note that DNS resolution must work properly to identify the inverter by its name + Enter the IP address or the hostname of the inverter. Note that DNS resolution must work properly to + identify the inverter by its name @@ -20,4 +22,3 @@ xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https: - diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/Channels.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/Channels.xml index b55b96c61e8dc..8b7d830980521 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/Channels.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/Channels.xml @@ -6,482 +6,482 @@ String - + Number:Energy Current DC power of the inverter Energy - + Number:Energy Current home consumption obtained from the battery Energy - + Number:Energy Current home consumption obtained from the grid Energy - + Number:Energy Current own comsumption Energy - + Number:Energy Current home consumption obtained from photovoltaic Energy - + Number:Energy Current total homeconsumption Energy - + Number:Energy Permitted feed-in quantity as absolute value as specified by the energy supplier Energy - + Number:Dimensionless Permitted feed-in quantity as relative value as specified by the energy supplier - + Number:Time Uptime of the inverter Time - + Number:ElectricCurrent Amperage of phase 1 Energy - + Number:Energy Power of phase 1 Energy - + Number:ElectricPotential Voltage of phase 1 Energy - + Number:ElectricCurrent Amperage of phase 2 Energy - + Number:Energy Power of phase 2 Energy - + Number:ElectricPotential Voltage of phase 2 Energy - + Number:ElectricCurrent Amperage of phase 3 Energy - + Number:Energy Power of phase 3 Energy - + Number:ElectricPotential Voltage of phase 3 Energy - + Number:Energy Current AC power of the inverter Energy - + Number:Dimensionless Amount of loading cycles done by the battery - + Number:ElectricCharge Capacity of the battery if charged fully BatteryLevel - + Number:ElectricCurrent Current amperage of the battery Energy - + Number:Energy Current battery charge Energy - + Number:Dimensionless Current battery charge status BatteryLevel - + Number:ElectricPotential Current voltage of the battery Energy - + Number:ElectricCurrent Current amperage of photovoltaic string 1 Energy - + Number:Energy Current power of photovoltaic string 1 Energy - + Number:ElectricPotential Current voltage of photovoltaic string 1 Energy - + Number:ElectricCurrent Current amperage of photovoltaic string 2 Energy - + Number:Energy Current power of photovoltaic string 2 Energy - + Number:ElectricPotential Current voltage of photovoltaic string 2 Energy - + Number:ElectricCurrent Current amperage of photovoltaic string 3 Energy - + Number:Energy - Current power of photovoltaic string 3 + Current power of photovoltaic string 3 Energy - + Number:ElectricPotential Current voltage of photovoltaic string 3 Energy - + Number:Dimensionless Number of errors reported by the main controller - + Number:Dimensionless Number of errors reported by the grid interface controller - + Number:Dimensionless Number of errors reported by the smart communication board - + Number:Dimensionless Number of warnings reported by the smart communication board - + Number:Dimensionless Autarky ratio of this day - + Number:Dimensionless Autarky ratio of this month - + Number:Dimensionless Autarky ratio overall - + Number:Dimensionless Autarky ratio of this year - + Number:Mass Savings in Co2 emissions today CarbonDioxide - + Number:Mass Savings in Co2 emissions this month CarbonDioxide - + Number:Mass Savings in Co2 emissions overall CarbonDioxide - + Number:Mass Savings in Co2 emissions this year CarbonDioxide - + Number:Energy Home consumption today Energy - + Number:Energy Home consumption this month Energy - + Number:Energy Home consumption overall Energy - + Number:Energy Home consumption this year Energy - + Number:Energy Home consumption obtained from the battery today Energy - + Number:Energy Home consumption obtained from the battery this month Energy - + Number:Energy Home consumption obtained from the battery overall Energy - + Number:Energy Home consumption obtained from the battery this year Energy - + Number:Energy Home consumption obtained from the grid today Energy - + Number:Energy Home consumption obtained from the grid this month Energy - + Number:Energy Home consumption obtained from the grid overall Energy - + Number:Energy Home consumption obtained from the grid this year Energy - + Number:Energy Home consumption obtained from the photovoltaic plant today Energy - + Number:Energy Home consumption obtained from the photovoltaic plant this month Energy - + Number:Energy Home consumption obtained from the photovoltaic plant overall Energy - + Number:Energy Home consumption obtained from the photovoltaic plant this year Energy - + Number:Dimensionless Percentage of electricity demand covered by photovoltaics today - + Number:Dimensionless Percentage of electricity demand covered by photovoltaics this month - + Number:Dimensionless Percentage of electricity demand covered by photovoltaics overall - + Number:Dimensionless Percentage of electricity demand covered by photovoltaics this year - + Number:Energy Yield of the photovoltaic plant today Energy - + Number:Energy Yield of the photovoltaic plant this month Energy - + Number:Energy Yield of the photovoltaic plant overall Energy - + Number:Energy Yield of the photovoltaic plant this year Energy - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ100.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ100.xml index acf639eb2c72b..789fc821c974c 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ100.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ100.xml @@ -8,66 +8,66 @@ Bindings for the KOSTAL PIKO IQ 10.0 solar inverter Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ42.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ42.xml index 39cf5014437bc..17f83d2663a7e 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ42.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ42.xml @@ -8,66 +8,66 @@ Bindings for the KOSTAL PIKO IQ 4.2 solar inverter Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ55.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ55.xml index 73a27f3fec492..6fdebca021ec8 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ55.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ55.xml @@ -8,66 +8,66 @@ Bindings for the KOSTAL PIKO IQ 5.5 solar inverter Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ70.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ70.xml index 35044d6510182..484dbcbb56ec0 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ70.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ70.xml @@ -8,66 +8,66 @@ Bindings for the KOSTAL PIKO IQ 7.0 solar inverter Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ85.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ85.xml index 52732f0d11ba3..1b970830d58eb 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ85.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PIKOIQ85.xml @@ -8,67 +8,66 @@ Bindings for the KOSTAL PIKO IQ 8.5 solar inverter Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + - diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS100WITHBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS100WITHBATTERY.xml index 33e4199b8365d..7cf7c17ce5440 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS100WITHBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS100WITHBATTERY.xml @@ -8,81 +8,77 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 10.0 solar inverter (with battery attached on PV string 3) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS100WITHOUTBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS100WITHOUTBATTERY.xml index e4fabd5dbf4ef..8db1d98e5bcba 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS100WITHOUTBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS100WITHOUTBATTERY.xml @@ -8,69 +8,69 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 10.0 solar inverter (no battery attached) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS42WITHBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS42WITHBATTERY.xml index b3171753a6edc..1f100e851aa74 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS42WITHBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS42WITHBATTERY.xml @@ -8,81 +8,77 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 4.2 solar inverter (with battery attached on PV string 3) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS42WITHOUTBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS42WITHOUTBATTERY.xml index 8c3042bd83f61..dfcd4d0da62eb 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS42WITHOUTBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS42WITHOUTBATTERY.xml @@ -8,69 +8,69 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 4.2 solar inverter (no battery attached) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS55WITHBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS55WITHBATTERY.xml index 4ded8b0ce1282..2860434b592bb 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS55WITHBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS55WITHBATTERY.xml @@ -8,81 +8,77 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 5.5 solar inverter (with battery attached on PV string 3) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS55WITHOUTBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS55WITHOUTBATTERY.xml index 052e795a3466d..e9208610bea74 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS55WITHOUTBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS55WITHOUTBATTERY.xml @@ -8,69 +8,69 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 5.5 solar inverter (no battery attached) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS70WITHBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS70WITHBATTERY.xml index c96783309b61d..4e99f2301611b 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS70WITHBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS70WITHBATTERY.xml @@ -8,81 +8,77 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 7.0 solar inverter (with battery attached on PV string 3) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS70WITHOUTBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS70WITHOUTBATTERY.xml index 6e73eed746c66..524cb7d3850c2 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS70WITHOUTBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS70WITHOUTBATTERY.xml @@ -8,69 +8,69 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 7.0 solar inverter (no battery attached) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS85WITHBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS85WITHBATTERY.xml index 957ef414cc23a..c7050564bc19a 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS85WITHBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS85WITHBATTERY.xml @@ -8,81 +8,77 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 8.5 solar inverter (with battery attached on PV string 3) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS85WITHOUTBATTERY.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS85WITHOUTBATTERY.xml index 31483ab8aabef..9df186e33bd28 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS85WITHOUTBATTERY.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/PLENTICOREPLUS85WITHOUTBATTERY.xml @@ -8,69 +8,69 @@ Bindings for the KOSTAL PIKO PLENTICORE plus 8.5 solar inverter (no battery attached) Inverter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + KOSTAL Solar Electric GmbH - + diff --git a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/thing-types.xml index 691a34b3c7f0f..ac5a679bc2f83 100644 --- a/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.kostalinverter/src/main/resources/ESH-INF/thing/thing-types.xml @@ -8,20 +8,20 @@ Kostal Inverter - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.lametrictime/.classpath b/bundles/org.openhab.binding.lametrictime/.classpath index a5d95095ccaaf..9465c8288ee24 100644 --- a/bundles/org.openhab.binding.lametrictime/.classpath +++ b/bundles/org.openhab.binding.lametrictime/.classpath @@ -11,11 +11,13 @@ - + + + + - diff --git a/bundles/org.openhab.binding.lametrictime/NOTICE b/bundles/org.openhab.binding.lametrictime/NOTICE index 6e0a5bb9c3454..f862503998d43 100644 --- a/bundles/org.openhab.binding.lametrictime/NOTICE +++ b/bundles/org.openhab.binding.lametrictime/NOTICE @@ -14,12 +14,11 @@ https://github.com/openhab/openhab-addons == Third-party Content -liblametrictime-java +The sources of liblametrictime-java are included in src/3rdparty/java and have been slightly adapted. * License: Apache 2.0 License * Project: https://github.com/syphr42/liblametrictime-java -* Source: https://github.com/syphr42/liblametrictime-java -provider-gson -* License: EPL 1.0 License -* Project: https://github.com/hstaudacher/osgi-jax-rs-connector -* Source: https://github.com/hstaudacher/osgi-jax-rs-connector + +This binding includes a class from Jersey in the src/3rdparty/java folder. +* License: CDDL License +* Project: https://eclipse-ee4j.github.io/jersey/ \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/pom.xml b/bundles/org.openhab.binding.lametrictime/pom.xml index 32a46a049344a..6840d097f9b0d 100644 --- a/bundles/org.openhab.binding.lametrictime/pom.xml +++ b/bundles/org.openhab.binding.lametrictime/pom.xml @@ -1,34 +1,65 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.lametrictime openHAB Add-ons :: Bundles :: LaMetric Time Binding - - provider-gson - + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + add-source + + generate-sources + + + src/3rdparty/java + + + + + add-test-source + generate-sources + + add-test-source + + + + src/3rdparty/test + + + + + + + - org.syphr - lametrictime-api - 0.1.0 - compile + junit + junit + 4.12 + test - com.eclipsesource.jaxrs - provider-gson - 2.3 - compile + com.googlecode.junit-toolbox + junit-toolbox + 2.2 + test - diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/Configuration.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/Configuration.java new file mode 100644 index 0000000000000..08601d054aa8d --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/Configuration.java @@ -0,0 +1,162 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api; + +import org.openhab.binding.lametrictime.api.cloud.CloudConfiguration; +import org.openhab.binding.lametrictime.api.local.LocalConfiguration; + +public class Configuration +{ + private String deviceHost; + private String deviceApiKey; + + private boolean ignoreDeviceCertificateValidation = true; + private boolean ignoreDeviceHostnameValidation = true; + + private boolean logging = false; + private String logLevel = "INFO"; + private int logMax = 104857600; // 100kb + + public String getDeviceHost() + { + return deviceHost; + } + + public void setDeviceHost(String deviceHost) + { + this.deviceHost = deviceHost; + } + + public Configuration withDeviceHost(String deviceHost) + { + this.deviceHost = deviceHost; + return this; + } + + public String getDeviceApiKey() + { + return deviceApiKey; + } + + public void setDeviceApiKey(String deviceApiKey) + { + this.deviceApiKey = deviceApiKey; + } + + public Configuration withDeviceApiKey(String deviceApiKey) + { + this.deviceApiKey = deviceApiKey; + return this; + } + + public boolean isIgnoreDeviceCertificateValidation() + { + return ignoreDeviceCertificateValidation; + } + + public void setIgnoreDeviceCertificateValidation(boolean ignoreDeviceCertificateValidation) + { + this.ignoreDeviceCertificateValidation = ignoreDeviceCertificateValidation; + } + + public Configuration withIgnoreDeviceCertificateValidation(boolean ignoreDeviceCertificateValidation) + { + this.ignoreDeviceCertificateValidation = ignoreDeviceCertificateValidation; + return this; + } + + public boolean isIgnoreDeviceHostnameValidation() + { + return ignoreDeviceHostnameValidation; + } + + public void setIgnoreDeviceHostnameValidation(boolean ignoreDeviceHostnameValidation) + { + this.ignoreDeviceHostnameValidation = ignoreDeviceHostnameValidation; + } + + public Configuration withIgnoreDeviceHostnameValidation(boolean ignoreDeviceHostnameValidation) + { + this.ignoreDeviceHostnameValidation = ignoreDeviceHostnameValidation; + return this; + } + + public boolean isLogging() + { + return logging; + } + + public void setLogging(boolean logging) + { + this.logging = logging; + } + + public Configuration withLogging(boolean logging) + { + this.logging = logging; + return this; + } + + public String getLogLevel() + { + return logLevel; + } + + public void setLogLevel(String logLevel) + { + this.logLevel = logLevel; + } + + public Configuration withLogLevel(String logLevel) + { + this.logLevel = logLevel; + return this; + } + + public int getLogMax() + { + return logMax; + } + + public void setLogMax(int logMax) + { + this.logMax = logMax; + } + + public Configuration withLogMax(int logMax) + { + this.logMax = logMax; + return this; + } + + public LocalConfiguration getLocalConfig() + { + return new LocalConfiguration().withHost(deviceHost) + .withApiKey(deviceApiKey) + .withIgnoreCertificateValidation(ignoreDeviceCertificateValidation) + .withIgnoreHostnameValidation(ignoreDeviceHostnameValidation) + .withLogging(logging) + .withLogLevel(logLevel) + .withLogMax(logMax); + } + + public CloudConfiguration getCloudConfig() + { + return new CloudConfiguration().withLogging(logging) + .withLogLevel(logLevel) + .withLogMax(logMax); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/LaMetricTime.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/LaMetricTime.java new file mode 100644 index 0000000000000..d331f6e3a177c --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/LaMetricTime.java @@ -0,0 +1,449 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api; + +import javax.ws.rs.client.ClientBuilder; + +import org.openhab.binding.lametrictime.api.cloud.CloudConfiguration; +import org.openhab.binding.lametrictime.api.cloud.LaMetricTimeCloud; +import org.openhab.binding.lametrictime.api.impl.LaMetricTimeImpl; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.local.ApplicationActivationException; +import org.openhab.binding.lametrictime.api.local.ApplicationNotFoundException; +import org.openhab.binding.lametrictime.api.local.LaMetricTimeLocal; +import org.openhab.binding.lametrictime.api.local.LocalConfiguration; +import org.openhab.binding.lametrictime.api.local.NotificationCreationException; +import org.openhab.binding.lametrictime.api.local.UpdateException; +import org.openhab.binding.lametrictime.api.local.model.Application; +import org.openhab.binding.lametrictime.api.local.model.Audio; +import org.openhab.binding.lametrictime.api.local.model.Bluetooth; +import org.openhab.binding.lametrictime.api.local.model.Display; +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; +import org.openhab.binding.lametrictime.api.local.model.Widget; +import org.openhab.binding.lametrictime.api.model.CoreAction; +import org.openhab.binding.lametrictime.api.model.CoreApplication; +import org.openhab.binding.lametrictime.api.model.CoreApps; +import org.openhab.binding.lametrictime.api.model.Icon; +import org.openhab.binding.lametrictime.api.model.enums.BrightnessMode; +import org.openhab.binding.lametrictime.api.model.enums.Priority; +import org.openhab.binding.lametrictime.api.model.enums.Sound; + +public interface LaMetricTime +{ + /** + * Get the version identifier reported by the device. + * + * @return the version + */ + public String getVersion(); + + /** + * Send a low priority message to the device. + * + * @param message + * the text to display + * @return the identifier of the newly created notification + * @throws NotificationCreationException + * if there is a communication error or malformed data + */ + public String notifyInfo(String message) throws NotificationCreationException; + + /** + * Send a medium priority message to the device. + * + * @param message + * the text to display + * @return the identifier of the newly created notification + * @throws NotificationCreationException + * if there is a communication error or malformed data + */ + public String notifyWarning(String message) throws NotificationCreationException; + + /** + * Send an urgent message to the device. The notification will not be + * automatically removed. The user will be required to dismiss this + * notification or it must be deleted through he API. + * + * @param message + * the text to display + * @return the identifier of the newly created notification + * @throws NotificationCreationException + * if there is a communication error or malformed data + */ + public String notifyCritical(String message) throws NotificationCreationException; + + /** + * Send a notification to the device. + * + * Priority is important. It defines the urgency of this notification as + * related to others in the queue and the current state of the device. + *
    + *
  1. {@link Priority#INFO}: lowest priority; not shown when the + * screensaver is active; waits for its turn in the queue + *
  2. {@link Priority#WARNING}: middle priority; not shown when the + * screensaver is active; preempts {@link Priority#INFO} + *
  3. {@link Priority#CRITICAL}: highest priority; shown even when the + * screensaver is active; preempts all other notifications (to be used + * sparingly) + *
+ * + * @param message + * the text to display + * @param priority + * the urgency of this notification; defaults to + * {@link Priority#INFO} + * @param icon + * the icon to display next to the message; can be + * null + * @param sound + * the sound to play when the notification is displayed; can be + * null + * @param messageRepeat + * the number of times the message should be displayed before + * being removed (use 0 to leave the notification on + * the device until it is dismissed by the user or deleted + * through the API) + * @param soundRepeat + * the number of times to repeat the sound (use 0 to + * keep the sound looping until the notification is dismissed by + * the user or deleted through the API) + * @return the identifier of the newly created notification + * @throws NotificationCreationException + * if there is a communication error or malformed data + */ + public String notify(String message, + Priority priority, + Icon icon, + Sound sound, + int messageRepeat, + int soundRepeat) throws NotificationCreationException; + + /** + * Get the built-in clock application. This applications displays the time + * and date. It also provides an alarm feature. + * + * @return the clock app + */ + public Application getClock(); + + /** + * Get the built-in countdown timer application. This application counts + * time down to zero when it sets off a beeper until it is reset. The + * countdown can also be paused. + * + * @return the countdown app + */ + public Application getCountdown(); + + /** + * Get the built-in radio application. The radio can play streams from the + * Internet. The streams are set up in a list and can be navigated using + * 'next' and 'previous' actions. The music can be started and stopped. + * + * @return the radio app + */ + public Application getRadio(); + + /** + * Get the built-in stopwatch application. The stopwatch counts time + * forwards and can be started, paused, and reset. + * + * @return the stopwatch app + */ + public Application getStopwatch(); + + /** + * Get the built-in weather application. This application displays the + * current weather conditions. It can also display the forecast for today + * and tomorrow. + * + * @return the weather app + */ + public Application getWeather(); + + /** + * Get any of the built-in applications. + * + * @param coreApp + * the app to retrieve + * @return the requested app + */ + public Application getApplication(CoreApplication coreApp); + + /** + * Get any application installed on the device. + * + * @param name + * the name of the app to retrieve + * @return the requested app + * @throws ApplicationNotFoundException + * if the requested app is not found on the device + */ + public Application getApplication(String name) throws ApplicationNotFoundException; + + /** + * Display the given built-in application on the device. + * + * @param coreApp + * the app to activate + */ + public void activateApplication(CoreApplication coreApp); + + /** + * Display the first instance (widget) of the given application on the + * device. + * + * @param app + * the app to activate + * @throws ApplicationActivationException + * if the app fails to activate + */ + public void activateApplication(Application app) throws ApplicationActivationException; + + /** + * Display the given widget on the device. A widget is simply an instance of + * an application. Some applications can be installed more than once (e.g. + * the {@link CoreApps#weather() weather} app) and each instance is assigned + * a widget. + * + * @param widget + * the application instance (widget) to activate + * @throws ApplicationActivationException + * if the app fails to activate + */ + public void activateWidget(Widget widget) throws ApplicationActivationException; + + /** + * Perform the given action on the first instance (widget) of the + * corresponding built-in application. The widget will activate + * automatically before carrying out the action. + * + * @param coreAction + * the action to perform + */ + public void doAction(CoreAction coreAction); + + /** + * Perform the given action on the first instance (widget) of the given + * application. The widget will activate automatically before carrying out + * the action. + * + * @param app + * the app which understands the requested action + * @param action + * the action to perform + * @throws ApplicationActionException + * if the action cannot be performed + */ + public void doAction(Application app, UpdateAction action) throws ApplicationActionException; + + /** + * Perform the given core action on the given widget. A widget is simply an + * instance of an application. Some applications can be installed more than + * once (e.g. the {@link CoreApps#weather() weather} app) and each instance + * is assigned a widget. The widget will activate automatically before + * carrying out the action. + * + * @param widget + * the widget which understands the requested core action + * @param action + * the action to perform + * @throws ApplicationActionException + * if the action cannot be performed + */ + public void doAction(Widget widget, CoreAction action) throws ApplicationActionException; + + /** + * Perform the given action on the given widget. A widget is simply an + * instance of an application. Some applications can be installed more than + * once (e.g. the {@link CoreApps#weather() weather} app) and each instance + * is assigned a widget. The widget will activate automatically before + * carrying out the action. + * + * @param widget + * the widget which understands the requested action + * @param action + * the action to perform + * @throws ApplicationActionException + * if the action cannot be performed + */ + public void doAction(Widget widget, UpdateAction action) throws ApplicationActionException; + + /** + * Set the display brightness. The {@link #setBrightnessMode(BrightnessMode) + * brightness mode} will also be set to {@link BrightnessMode#MANUAL}. + * + * @param brightness + * the brightness value to set (must be between 0 and 100, + * inclusive) + * @return the updated state of the display + * @throws UpdateException + * if the update failed + */ + public Display setBrightness(int brightness) throws UpdateException; + + /** + * Set the brightness mode on the display. {@link BrightnessMode#MANUAL} + * will immediately respect the current brightness value while + * {@link BrightnessMode#AUTO} will ignore the brightness value and set the + * brightness based on ambient light intensity. + * + * @param mode + * the mode to set + * @return the updated state of the display + * @throws UpdateException + * if the update failed + */ + public Display setBrightnessMode(BrightnessMode mode) throws UpdateException; + + /** + * Set the speaker volume on the device. + * + * @param volume + * the volume to set (must be between 0 and 100, inclusive) + * @return the update audio state + * @throws UpdateException + * if the update failed + */ + public Audio setVolume(int volume) throws UpdateException; + + /** + * Mute the device's speakers. The current volume will be stored so that + * {@link #unmute()} will restored it. If the volume is currently at zero, + * no action will be taken. + * + * @return the update audio state + * @throws UpdateException + * if the update failed + */ + public Audio mute() throws UpdateException; + + /** + * Restore the volume prior to {@link #mute()}. If the volume has not been + * muted previously and the volume is currently zero, it will be set to 50%. + * + * @return the update audio state + * @throws UpdateException + * if the update failed + */ + public Audio unmute() throws UpdateException; + + /** + * Set the active state of the Bluetooth radio on the device. + * + * @param active + * true to activate Bluetooth; false to + * deactive it + * @return the updated state of Bluetooth on the device + * @throws UpdateException + * if the update failed + */ + public Bluetooth setBluetoothActive(boolean active) throws UpdateException; + + /** + * Set the device name as seen via Bluetooth connectivity. + * + * @param name + * the name to display on other devices + * @return the updated state of Bluetooth on the device + * @throws UpdateException + * if the update failed + */ + public Bluetooth setBluetoothName(String name) throws UpdateException; + + /** + * Get the local API for more advanced interactions as well device inquiry. + * + * @return the local API + */ + public LaMetricTimeLocal getLocalApi(); + + /** + * Get the cloud API for interacting with LaMetric's services. + * + * @return the cloud API + */ + public LaMetricTimeCloud getCloudApi(); + + /** + * Create an instance of this API. For greater control over the + * configuration, see {@link #create(Configuration, ClientBuilder)}, + * {@link #create(LocalConfiguration, CloudConfiguration)}, and + * {@link #create(LocalConfiguration, CloudConfiguration, ClientBuilder)}. + * + * @param config + * the configuration parameters that the new instance will use + * @return the API instance + */ + public static LaMetricTime create(Configuration config) + { + return new LaMetricTimeImpl(config); + } + + /** + * Create an instance of this API. For greater control over the + * configuration, see + * {@link #create(LocalConfiguration, CloudConfiguration, ClientBuilder)}. + * + * @param config + * the configuration parameters that the new instance will use + * @param clientBuilder + * the builder that will be used to create clients for + * communicating with the device and cloud services + * @return the API instance + */ + public static LaMetricTime create(Configuration config, ClientBuilder clientBuilder) + { + return new LaMetricTimeImpl(config, clientBuilder); + } + + /** + * Create an instance of this API specifying detailed configuration for both + * the local and cloud APIs. See also + * {@link #create(LocalConfiguration, CloudConfiguration, ClientBuilder)}. + * + * @param localConfig + * the local API configuration for the new instance + * @param cloudConfig + * the cloud API configuration for the new instance + * @return the API instance + */ + public static LaMetricTime create(LocalConfiguration localConfig, + CloudConfiguration cloudConfig) + { + return new LaMetricTimeImpl(localConfig, cloudConfig); + } + + /** + * Create an instance of this API specifying detailed configuration for both + * the local and cloud APIs as well as the generic client. + * + * @param localConfig + * the local API configuration for the new instance + * @param cloudConfig + * the cloud API configuration for the new instance + * @param clientBuilder + * the builder that will be used to create clients for + * communicating with the device and cloud services + * @return the API instance + */ + public static LaMetricTime create(LocalConfiguration localConfig, + CloudConfiguration cloudConfig, + ClientBuilder clientBuilder) + { + return new LaMetricTimeImpl(localConfig, cloudConfig, clientBuilder); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/BasicAuthenticator.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/BasicAuthenticator.java new file mode 100644 index 0000000000000..3756a9045451a --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/BasicAuthenticator.java @@ -0,0 +1,128 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package org.openhab.binding.lametrictime.api.authentication; + +import java.util.Base64; + +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.core.HttpHeaders; + +/** + * Implementation of Basic Http Authentication method (RFC 2617). + * + * @author Miroslav Fuksa + * @author Jakub Podlesak (jakub.podlesak at oracle.com) + * @author Craig McClanahan + */ +final class BasicAuthenticator { + + private final HttpAuthenticationFilter.Credentials defaultCredentials; + + /** + * Creates a new instance of basic authenticator. + * + * @param defaultCredentials Credentials. Can be {@code null} if no default credentials should be + * used. + */ + BasicAuthenticator(HttpAuthenticationFilter.Credentials defaultCredentials) { + this.defaultCredentials = defaultCredentials; + } + + private String calculateAuthentication(HttpAuthenticationFilter.Credentials credentials) { + String username = credentials.getUsername(); + byte[] password = credentials.getPassword(); + if (username == null) { + username = ""; + } + + if (password == null) { + password = new byte[0]; + } + + final byte[] prefix = (username + ":").getBytes(HttpAuthenticationFilter.CHARACTER_SET); + final byte[] usernamePassword = new byte[prefix.length + password.length]; + + System.arraycopy(prefix, 0, usernamePassword, 0, prefix.length); + System.arraycopy(password, 0, usernamePassword, prefix.length, password.length); + + return "Basic " + Base64.getEncoder().encodeToString(usernamePassword); + } + + /** + * Adds authentication information to the request. + * + * @param request Request context. + * @throws RequestAuthenticationException in case that basic credentials missing or are in invalid format + */ + public void filterRequest(ClientRequestContext request) throws RequestAuthenticationException { + HttpAuthenticationFilter.Credentials credentials = HttpAuthenticationFilter.getCredentials(request, + defaultCredentials, HttpAuthenticationFilter.Type.BASIC); + if (credentials == null) { + throw new RequestAuthenticationException("BasicAuth credentials are missing."); + } + request.getHeaders().add(HttpHeaders.AUTHORIZATION, calculateAuthentication(credentials)); + } + + /** + * Checks the response and if basic authentication is required then performs a new request + * with basic authentication. + * + * @param request Request context. + * @param response Response context (will be updated with newest response data if the request was repeated). + * @return {@code true} if response does not require authentication or if authentication is required, + * new request was done with digest authentication information and authentication was successful. + * @throws ResponseAuthenticationException in case that basic credentials missing or are in invalid format + */ + public boolean filterResponseAndAuthenticate(ClientRequestContext request, ClientResponseContext response) { + final String authenticate = response.getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE); + if (authenticate != null && authenticate.trim().toUpperCase().startsWith("BASIC")) { + HttpAuthenticationFilter.Credentials credentials = HttpAuthenticationFilter.getCredentials(request, + defaultCredentials, HttpAuthenticationFilter.Type.BASIC); + + if (credentials == null) { + throw new ResponseAuthenticationException(null, "BasicAuth credentials are missing."); + } + + return HttpAuthenticationFilter.repeatRequest(request, response, calculateAuthentication(credentials)); + } + return false; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/HttpAuthenticationFeature.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/HttpAuthenticationFeature.java new file mode 100644 index 0000000000000..6e6027c26678f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/HttpAuthenticationFeature.java @@ -0,0 +1,595 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package org.openhab.binding.lametrictime.api.authentication; + +import javax.ws.rs.core.Feature; +import javax.ws.rs.core.FeatureContext; + +/** + * Features that provides Http Basic and Digest client authentication (based on RFC 2617). + *

+ * The feature can work in following modes: + *

    + *
  • BASIC: Basic preemptive authentication. In preemptive mode the authentication information + * is send always with each HTTP request. This mode is more usual than the following non-preemptive mode + * (if you require BASIC authentication you will probably use this preemptive mode). This mode must + * be combined with usage of SSL/TLS as the password is send only BASE64 encoded.
  • + *
  • BASIC NON-PREEMPTIVE: Basic non-preemptive authentication. In non-preemptive mode the + * authentication information is added only when server refuses the request with {@code 401} status code and + * then the request is repeated with authentication information. This mode has negative impact on the performance. + * The advantage is that it does not send credentials when they are not needed. This mode must + * be combined with usage of SSL/TLS as the password is send only BASE64 encoded. + *
  • + *
  • DIGEST: Http digest authentication. Does not require usage of SSL/TLS.
  • + *
  • UNIVERSAL: Combination of basic and digest authentication. The feature works in non-preemptive + * mode which means that it sends requests without authentication information. If {@code 401} status + * code is returned, the request is repeated and an appropriate authentication is used based on the + * authentication requested in the response (defined in {@code WWW-Authenticate} HTTP header. The feature + * remembers which authentication requests were successful for given URI and next time tries to preemptively + * authenticate against this URI with latest successful authentication method. + *
  • + *
+ *

+ *

+ * To initialize the feature use static method of this feature. + *

+ *

+ * Example of building the feature in + * Basic authentication mode: + * + *

+ * HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("user", "superSecretPassword");
+ * 
+ *

+ *

+ * Example of building the feature in basic non-preemptive mode: + * + *

+ * HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().nonPreemptive()
+ *         .credentials("user", "superSecretPassword").build();
+ * 
+ *

+ *

+ * Example of building the feature in universal mode: + * + *

+ * HttpAuthenticationFeature feature = HttpAuthenticationFeature.universal("user", "superSecretPassword");
+ * 
+ *

+ *

+ * Example of building the feature in universal mode with different credentials for basic and digest: + * + *

+ * HttpAuthenticationFeature feature = HttpAuthenticationFeature.universalBuilder()
+ *         .credentialsForBasic("user", "123456").credentials("adminuser", "hello").build();
+ * 
+ *

+ * Example of building the feature in basic preemptive mode with no default credentials. Credentials will have + * to be supplied with each request using request properties (see below): + * + *
+ * HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().build();
+ * 
+ *

+ *

+ * Once the feature is built it needs to be registered into the {@link javax.ws.rs.client.Client}, + * {@link javax.ws.rs.client.WebTarget} or other client configurable object. Example: + * + *

+ * final Client client = ClientBuilder.newClient();
+ * client.register(feature);
+ * 
+ *

+ * + * Then you invoke requests as usual and authentication will be handled by the feature. + * You can change the credentials for each request using properties + * + *
+ * final Response response = client.target("http://localhost:8080/rest/homer/contact").request()
+ *         .property(HTTP_AUTHENTICATION_BASIC_USERNAME, "homer")
+ *         .property(HTTP_AUTHENTICATION_BASIC_PASSWORD, "p1swd745").get();
+ * 
+ *

+ * This class also contains property key definitions for overriding only specific basic or digest credentials: + *

+ * + * @author Miroslav Fuksa + * + * @since 2.5 + */ +public class HttpAuthenticationFeature implements Feature { + + /** + * Feature authentication mode. + */ + static enum Mode { + /** + * Basic preemptive. + **/ + BASIC_PREEMPTIVE, + /** + * Basic non preemptive + */ + BASIC_NON_PREEMPTIVE, + /** + * Digest. + */ + DIGEST, + /** + * Universal. + */ + UNIVERSAL + } + + /** + * Builder that creates instances of {@link HttpAuthenticationFeature}. + */ + public static interface Builder { + + /** + * Set credentials. + * + * @param username Username. + * @param password Password as byte array. + * @return This builder. + */ + public Builder credentials(String username, byte[] password); + + /** + * Set credentials. + * + * @param username Username. + * @param password Password as {@link String}. + * @return This builder. + */ + public Builder credentials(String username, String password); + + /** + * Build the feature. + * + * @return Http authentication feature configured from this builder. + */ + public HttpAuthenticationFeature build(); + } + + /** + * Extension of {@link org.glassfish.jersey.client.authentication.HttpAuthenticationFeature.Builder} + * that builds the http authentication feature configured for basic authentication. + */ + public static interface BasicBuilder extends Builder { + + /** + * Configure the builder to create features in non-preemptive basic authentication mode. + * + * @return This builder. + */ + public BasicBuilder nonPreemptive(); + } + + /** + * that builds the http authentication feature configured in universal mode that supports + * basic and digest authentication. + */ + public static interface UniversalBuilder extends Builder { + + /** + * Set credentials that will be used for basic authentication only. + * + * @param username Username. + * @param password Password as {@link String}. + * @return This builder. + */ + public UniversalBuilder credentialsForBasic(String username, String password); + + /** + * Set credentials that will be used for basic authentication only. + * + * @param username Username. + * @param password Password as {@code byte array}. + * @return This builder. + */ + public UniversalBuilder credentialsForBasic(String username, byte[] password); + + /** + * Set credentials that will be used for digest authentication only. + * + * @param username Username. + * @param password Password as {@link String}. + * @return This builder. + */ + public UniversalBuilder credentialsForDigest(String username, String password); + + /** + * Set credentials that will be used for digest authentication only. + * + * @param username Username. + * @param password Password as {@code byte array}. + * @return This builder. + */ + public UniversalBuilder credentialsForDigest(String username, byte[] password); + } + + /** + * Implementation of all authentication builders. + */ + static class BuilderImpl implements UniversalBuilder, BasicBuilder { + + private String usernameBasic; + private byte[] passwordBasic; + private String usernameDigest; + private byte[] passwordDigest; + private Mode mode; + + /** + * Create a new builder. + * + * @param mode Mode in which the final authentication feature should work. + */ + public BuilderImpl(Mode mode) { + this.mode = mode; + } + + @Override + public Builder credentials(String username, String password) { + return credentials(username, + password == null ? null : password.getBytes(HttpAuthenticationFilter.CHARACTER_SET)); + } + + @Override + public Builder credentials(String username, byte[] password) { + credentialsForBasic(username, password); + credentialsForDigest(username, password); + return this; + } + + @Override + public UniversalBuilder credentialsForBasic(String username, String password) { + return credentialsForBasic(username, + password == null ? null : password.getBytes(HttpAuthenticationFilter.CHARACTER_SET)); + } + + @Override + public UniversalBuilder credentialsForBasic(String username, byte[] password) { + this.usernameBasic = username; + this.passwordBasic = password; + return this; + } + + @Override + public UniversalBuilder credentialsForDigest(String username, String password) { + return credentialsForDigest(username, + password == null ? null : password.getBytes(HttpAuthenticationFilter.CHARACTER_SET)); + } + + @Override + public UniversalBuilder credentialsForDigest(String username, byte[] password) { + this.usernameDigest = username; + this.passwordDigest = password; + return this; + } + + @Override + public HttpAuthenticationFeature build() { + return new HttpAuthenticationFeature(mode, + usernameBasic == null ? null + : new HttpAuthenticationFilter.Credentials(usernameBasic, passwordBasic), + usernameDigest == null ? null + : new HttpAuthenticationFilter.Credentials(usernameDigest, passwordDigest)); + } + + @Override + public BasicBuilder nonPreemptive() { + if (mode == Mode.BASIC_PREEMPTIVE) { + this.mode = Mode.BASIC_NON_PREEMPTIVE; + } + return this; + } + } + + /** + * Key of the property that can be set into the {@link javax.ws.rs.client.ClientRequestContext client request} + * using {@link javax.ws.rs.client.ClientRequestContext#setProperty(String, Object)} in order to override + * the username for http authentication feature for the request. + *

+ * Example: + * + *

+     * Response response = client.target("http://localhost:8080/rest/joe/orders").request()
+     *         .property(HTTP_AUTHENTICATION_USERNAME, "joe").property(HTTP_AUTHENTICATION_PASSWORD, "p1swd745").get();
+     * 
+ *

+ * The property must be always combined with configuration of {@link #HTTP_AUTHENTICATION_PASSWORD} property + * (as shown in the example). This property pair overrides all password settings of the authentication + * feature for the current request. + *

+ * The default value must be instance of {@link String}. + *

+ *

+ * The name of the configuration property is {@value}. + *

+ */ + public static final String HTTP_AUTHENTICATION_USERNAME = "jersey.config.client.http.auth.username"; + /** + * Key of the property that can be set into the {@link javax.ws.rs.client.ClientRequestContext client request} + * using {@link javax.ws.rs.client.ClientRequestContext#setProperty(String, Object)} in order to override + * the password for http authentication feature for the request. + *

+ * Example: + * + *

+     * Response response = client.target("http://localhost:8080/rest/joe/orders").request()
+     *         .property(HTTP_AUTHENTICATION_USERNAME, "joe").property(HTTP_AUTHENTICATION_PASSWORD, "p1swd745").get();
+     * 
+ *

+ * The property must be always combined with configuration of {@link #HTTP_AUTHENTICATION_USERNAME} property + * (as shown in the example). This property pair overrides all password settings of the authentication + * feature for the current request. + *

+ * The value must be instance of {@link String} or {@code byte} array ({@code byte[]}). + *

+ *

+ * The name of the configuration property is {@value}. + *

+ */ + public static final String HTTP_AUTHENTICATION_PASSWORD = "jersey.config.client.http.auth.password"; + + /** + * Key of the property that can be set into the {@link javax.ws.rs.client.ClientRequestContext client request} + * using {@link javax.ws.rs.client.ClientRequestContext#setProperty(String, Object)} in order to override + * the username for http basic authentication feature for the request. + *

+ * Example: + * + *

+     * Response response = client.target("http://localhost:8080/rest/joe/orders").request()
+     *         .property(HTTP_AUTHENTICATION_BASIC_USERNAME, "joe").property(HTTP_AUTHENTICATION_BASIC_PASSWORD, "p1swd745")
+     *         .get();
+     * 
+ *

+ * The property must be always combined with configuration of {@link #HTTP_AUTHENTICATION_PASSWORD} property + * (as shown in the example). The property pair influence only credentials used during basic authentication. + * + *

+ * The value must be instance of {@link String}. + *

+ *

+ * The name of the configuration property is {@value}. + *

+ * + */ + public static final String HTTP_AUTHENTICATION_BASIC_USERNAME = "jersey.config.client.http.auth.basic.username"; + + /** + * Key of the property that can be set into the {@link javax.ws.rs.client.ClientRequestContext client request} + * using {@link javax.ws.rs.client.ClientRequestContext#setProperty(String, Object)} in order to override + * the password for http basic authentication feature for the request. + *

+ * Example: + * + *

+     * Response response = client.target("http://localhost:8080/rest/joe/orders").request()
+     *         .property(HTTP_AUTHENTICATION_BASIC_USERNAME, "joe").property(HTTP_AUTHENTICATION_BASIC_PASSWORD, "p1swd745")
+     *         .get();
+     * 
+ *

+ * The property must be always combined with configuration of {@link #HTTP_AUTHENTICATION_USERNAME} property + * (as shown in the example). The property pair influence only credentials used during basic authentication. + *

+ * The value must be instance of {@link String} or {@code byte} array ({@code byte[]}). + *

+ *

+ * The name of the configuration property is {@value}. + *

+ */ + public static final String HTTP_AUTHENTICATION_BASIC_PASSWORD = "jersey.config.client.http.auth.basic.password"; + + /** + * Key of the property that can be set into the {@link javax.ws.rs.client.ClientRequestContext client request} + * using {@link javax.ws.rs.client.ClientRequestContext#setProperty(String, Object)} in order to override + * the username for http digest authentication feature for the request. + *

+ * Example: + * + *

+     * Response response = client.target("http://localhost:8080/rest/joe/orders").request()
+     *         .property(HTTP_AUTHENTICATION_DIGEST_USERNAME, "joe")
+     *         .property(HTTP_AUTHENTICATION_DIGEST_PASSWORD, "p1swd745").get();
+     * 
+ *

+ * The property must be always combined with configuration of {@link #HTTP_AUTHENTICATION_PASSWORD} property + * (as shown in the example). The property pair influence only credentials used during digest authentication. + *

+ * The value must be instance of {@link String}. + *

+ *

+ * The name of the configuration property is {@value}. + *

+ */ + public static final String HTTP_AUTHENTICATION_DIGEST_USERNAME = "jersey.config.client.http.auth.digest.username"; + + /** + * Key of the property that can be set into the {@link javax.ws.rs.client.ClientRequestContext client request} + * using {@link javax.ws.rs.client.ClientRequestContext#setProperty(String, Object)} in order to override + * the password for http digest authentication feature for the request. + *

+ * Example: + * + *

+     * Response response = client.target("http://localhost:8080/rest/joe/orders").request()
+     *         .property(HTTP_AUTHENTICATION_DIGEST_USERNAME, "joe")
+     *         .property(HTTP_AUTHENTICATION_DIGEST_PASSWORD, "p1swd745").get();
+     * 
+ *

+ * The property must be always combined with configuration of {@link #HTTP_AUTHENTICATION_PASSWORD} property + * (as shown in the example). The property pair influence only credentials used during digest authentication. + *

+ * The value must be instance of {@link String} or {@code byte} array ({@code byte[]}). + *

+ *

+ * The name of the configuration property is {@value}. + *

+ */ + public static final String HTTP_AUTHENTICATION_DIGEST_PASSWORD = "jersey.config.client.http.auth.digest.password"; + + /** + * Create the builder of the http authentication feature working in basic authentication mode. The builder + * can build preemptive and non-preemptive basic authentication features. + * + * @return Basic http authentication builder. + */ + public static BasicBuilder basicBuilder() { + return new BuilderImpl(Mode.BASIC_PREEMPTIVE); + } + + /** + * Create the http authentication feature in basic preemptive authentication mode initialized with credentials. + * + * @param username Username. + * @param password Password as {@code byte array}. + * @return Http authentication feature configured in basic mode. + */ + public static HttpAuthenticationFeature basic(String username, byte[] password) { + return build(Mode.BASIC_PREEMPTIVE, username, password); + } + + /** + * Create the http authentication feature in basic preemptive authentication mode initialized with credentials. + * + * @param username Username. + * @param password Password as {@link String}. + * @return Http authentication feature configured in basic mode. + */ + public static HttpAuthenticationFeature basic(String username, String password) { + return build(Mode.BASIC_PREEMPTIVE, username, password); + } + + /** + * Create the http authentication feature in digest authentication mode initialized without default + * credentials. Credentials will have to be supplied using request properties for each request. + * + * @return Http authentication feature configured in digest mode. + */ + public static HttpAuthenticationFeature digest() { + return build(Mode.DIGEST); + } + + /** + * Create the http authentication feature in digest authentication mode initialized with credentials. + * + * @param username Username. + * @param password Password as {@code byte array}. + * @return Http authentication feature configured in digest mode. + */ + public static HttpAuthenticationFeature digest(String username, byte[] password) { + return build(Mode.DIGEST, username, password); + } + + /** + * Create the http authentication feature in digest authentication mode initialized with credentials. + * + * @param username Username. + * @param password Password as {@link String}. + * @return Http authentication feature configured in digest mode. + */ + public static HttpAuthenticationFeature digest(String username, String password) { + return build(Mode.DIGEST, username, password); + } + + /** + * Create the builder that builds http authentication feature in combined mode supporting both, + * basic and digest authentication. + * + * @return Universal builder. + */ + public static UniversalBuilder universalBuilder() { + return new BuilderImpl(Mode.UNIVERSAL); + } + + /** + * Create the http authentication feature in combined mode supporting both, + * basic and digest authentication. + * + * @param username Username. + * @param password Password as {@code byte array}. + * @return Http authentication feature configured in digest mode. + */ + public static HttpAuthenticationFeature universal(String username, byte[] password) { + return build(Mode.UNIVERSAL, username, password); + } + + /** + * Create the http authentication feature in combined mode supporting both, + * basic and digest authentication. + * + * @param username Username. + * @param password Password as {@link String}. + * @return Http authentication feature configured in digest mode. + */ + public static HttpAuthenticationFeature universal(String username, String password) { + return build(Mode.UNIVERSAL, username, password); + } + + private static HttpAuthenticationFeature build(Mode mode) { + return new BuilderImpl(mode).build(); + } + + private static HttpAuthenticationFeature build(Mode mode, String username, byte[] password) { + return new BuilderImpl(mode).credentials(username, password).build(); + } + + private static HttpAuthenticationFeature build(Mode mode, String username, String password) { + return new BuilderImpl(mode).credentials(username, password).build(); + } + + private final Mode mode; + private final HttpAuthenticationFilter.Credentials basicCredentials; + + private HttpAuthenticationFeature(Mode mode, HttpAuthenticationFilter.Credentials basicCredentials, + HttpAuthenticationFilter.Credentials digestCredentials) { + this.mode = mode; + this.basicCredentials = basicCredentials; + } + + @Override + public boolean configure(FeatureContext context) { + context.register(new HttpAuthenticationFilter(mode, basicCredentials, context.getConfiguration())); + return true; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/HttpAuthenticationFilter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/HttpAuthenticationFilter.java new file mode 100644 index 0000000000000..c61c0293a0ef3 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/HttpAuthenticationFilter.java @@ -0,0 +1,349 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2013-2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ + +package org.openhab.binding.lametrictime.api.authentication; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; + +import javax.annotation.Priority; +import javax.ws.rs.Priorities; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Configuration; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedHashMap; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; + +/** + * Http Authentication filter that provides basic and digest authentication (based on RFC 2617). + * + * @author Miroslav Fuksa + */ +@Priority(Priorities.AUTHENTICATION) +class HttpAuthenticationFilter implements ClientRequestFilter, ClientResponseFilter { + + /** + * Authentication type. + */ + enum Type { + /** + * Basic authentication. + */ + BASIC + } + + private static final String REQUEST_PROPERTY_FILTER_REUSED = "org.openhab.binding.lametrictime.api.authentication.HttpAuthenticationFilter.reused"; + private static final String REQUEST_PROPERTY_OPERATION = "org.openhab.binding.lametrictime.api.authentication.HttpAuthenticationFilter.operation"; + + /** + * Encoding used for authentication calculations. + */ + static final Charset CHARACTER_SET = Charset.forName("iso-8859-1"); + + private final HttpAuthenticationFeature.Mode mode; + + private final BasicAuthenticator basicAuth; + + /** + * Create a new filter instance. + * + * @param mode Mode. + * @param basicCredentials Basic credentials (can be {@code null} if this filter does not work in the + * basic mode or if no default credentials are defined). + * @param digestCredentials Digest credentials (can be {@code null} if this filter does not work in the + * digest mode or if no default credentials are defined). + * @param configuration Configuration (non-{@code null}). + */ + HttpAuthenticationFilter(HttpAuthenticationFeature.Mode mode, Credentials basicCredentials, + Configuration configuration) { + this.mode = mode; + switch (mode) { + case BASIC_PREEMPTIVE: + case BASIC_NON_PREEMPTIVE: + this.basicAuth = new BasicAuthenticator(basicCredentials); + break; + case UNIVERSAL: + this.basicAuth = new BasicAuthenticator(basicCredentials); + break; + default: + throw new IllegalStateException("Not implemented."); + } + } + + @Override + public void filter(ClientRequestContext request) throws IOException { + if ("true".equals(request.getProperty(REQUEST_PROPERTY_FILTER_REUSED))) { + return; + } + + if (request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) { + return; + } + + Type operation = null; + if (mode == HttpAuthenticationFeature.Mode.BASIC_PREEMPTIVE) { + basicAuth.filterRequest(request); + operation = Type.BASIC; + } else if (mode == HttpAuthenticationFeature.Mode.BASIC_NON_PREEMPTIVE) { + // do nothing + } + + if (operation != null) { + request.setProperty(REQUEST_PROPERTY_OPERATION, operation); + } + } + + @Override + public void filter(ClientRequestContext request, ClientResponseContext response) throws IOException { + if ("true".equals(request.getProperty(REQUEST_PROPERTY_FILTER_REUSED))) { + return; + } + + Type result = null; // which authentication is requested: BASIC or DIGEST + boolean authenticate; + + if (response.getStatus() == Response.Status.UNAUTHORIZED.getStatusCode()) { + String authString = response.getHeaders().getFirst(HttpHeaders.WWW_AUTHENTICATE); + if (authString != null) { + final String upperCaseAuth = authString.trim().toUpperCase(); + if (upperCaseAuth.startsWith("BASIC")) { + result = Type.BASIC; + } else { + // unknown authentication -> this filter cannot authenticate with this method + return; + } + } + authenticate = true; + } else { + authenticate = false; + } + + if (mode == HttpAuthenticationFeature.Mode.BASIC_PREEMPTIVE) { + // do nothing -> 401 will be returned to the client + } else if (mode == HttpAuthenticationFeature.Mode.BASIC_NON_PREEMPTIVE) { + if (authenticate && result == Type.BASIC) { + basicAuth.filterResponseAndAuthenticate(request, response); + } + } else if (mode == HttpAuthenticationFeature.Mode.UNIVERSAL) { + if (authenticate) { + boolean success = false; + + // now we have the challenge response and we can authenticate + if (result == Type.BASIC) { + success = basicAuth.filterResponseAndAuthenticate(request, response); + } + } + } + } + + private String getCacheKey(ClientRequestContext request) { + return request.getUri().toString() + ":" + request.getMethod(); + } + + /** + * Repeat the {@code request} with provided {@code newAuthorizationHeader} + * and update the {@code response} with newest response data. + * + * @param request Request context. + * @param response Response context (will be updated with the new response data). + * @param newAuthorizationHeader {@code Authorization} header that should be added to the new request. + * @return {@code true} is the authentication was successful ({@code true} if 401 response code was not returned; + * {@code false} otherwise). + */ + static boolean repeatRequest(ClientRequestContext request, ClientResponseContext response, + String newAuthorizationHeader) { + Client client = ClientBuilder.newClient(request.getConfiguration()); + String method = request.getMethod(); + MediaType mediaType = request.getMediaType(); + URI lUri = request.getUri(); + + WebTarget resourceTarget = client.target(lUri); + + Invocation.Builder builder = resourceTarget.request(mediaType); + + MultivaluedMap newHeaders = new MultivaluedHashMap(); + + for (Map.Entry> entry : request.getHeaders().entrySet()) { + if (HttpHeaders.AUTHORIZATION.equals(entry.getKey())) { + continue; + } + newHeaders.put(entry.getKey(), entry.getValue()); + } + + newHeaders.add(HttpHeaders.AUTHORIZATION, newAuthorizationHeader); + builder.headers(newHeaders); + + builder.property(REQUEST_PROPERTY_FILTER_REUSED, "true"); + + Invocation invocation; + if (request.getEntity() == null) { + invocation = builder.build(method); + } else { + invocation = builder.build(method, Entity.entity(request.getEntity(), request.getMediaType())); + } + Response nextResponse = invocation.invoke(); + + if (nextResponse.hasEntity()) { + response.setEntityStream(nextResponse.readEntity(InputStream.class)); + } + MultivaluedMap headers = response.getHeaders(); + headers.clear(); + headers.putAll(nextResponse.getStringHeaders()); + response.setStatus(nextResponse.getStatus()); + + return response.getStatus() != Response.Status.UNAUTHORIZED.getStatusCode(); + } + + /** + * Credentials (username + password). + */ + static class Credentials { + + private final String username; + private final byte[] password; + + /** + * Create a new credentials from username and password as byte array. + * + * @param username Username. + * @param password Password as byte array. + */ + Credentials(String username, byte[] password) { + this.username = username; + this.password = password; + } + + /** + * Create a new credentials from username and password as {@link String}. + * + * @param username Username. + * @param password {@code String} password. + */ + Credentials(String username, String password) { + this.username = username; + this.password = password == null ? null : password.getBytes(CHARACTER_SET); + } + + /** + * Return username. + * + * @return username. + */ + String getUsername() { + return username; + } + + /** + * Return password as byte array. + * + * @return Password string in byte array representation. + */ + byte[] getPassword() { + return password; + } + } + + private static Credentials extractCredentials(ClientRequestContext request, Type type) { + String usernameKey = null; + String passwordKey = null; + if (type == null) { + usernameKey = HttpAuthenticationFeature.HTTP_AUTHENTICATION_USERNAME; + passwordKey = HttpAuthenticationFeature.HTTP_AUTHENTICATION_PASSWORD; + } else if (type == Type.BASIC) { + usernameKey = HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME; + passwordKey = HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD; + } + + String userName = (String) request.getProperty(usernameKey); + if (userName != null && !userName.equals("")) { + byte[] pwdBytes; + Object password = request.getProperty(passwordKey); + if (password instanceof byte[]) { + pwdBytes = ((byte[]) password); + } else if (password instanceof String) { + pwdBytes = ((String) password).getBytes(CHARACTER_SET); + } else { + throw new RequestAuthenticationException("Passwort invalid."); + } + return new Credentials(userName, pwdBytes); + } + return null; + } + + /** + * Get credentials actual for the current request. Priorities in credentials selection are the following: + *
    + *
  1. Basic/digest specific credentials defined in the request properties
  2. + *
  3. Common credentials defined in the request properties
  4. + *
  5. {@code defaultCredentials}
  6. + *
+ * + * @param request Request from which credentials should be extracted. + * @param defaultCredentials Default credentials (can be {@code null}). + * @param type Type of requested credentials. + * @return Credentials or {@code null} if no credentials are found and {@code defaultCredentials} are {@code null}. + * @throws RequestAuthenticationException in case the {@code username} or {@code password} is invalid. + */ + static Credentials getCredentials(ClientRequestContext request, Credentials defaultCredentials, Type type) { + Credentials commonCredentials = extractCredentials(request, type); + + if (commonCredentials != null) { + return commonCredentials; + } else { + Credentials specificCredentials = extractCredentials(request, null); + + return specificCredentials != null ? specificCredentials : defaultCredentials; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/RequestAuthenticationException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/RequestAuthenticationException.java new file mode 100644 index 0000000000000..adbb9bfbde868 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/RequestAuthenticationException.java @@ -0,0 +1,79 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package org.openhab.binding.lametrictime.api.authentication; + +import javax.ws.rs.ProcessingException; + +/** + * Exception thrown by security request authentication. + * + * @author Petr Bouda (petr.bouda at oracle.com) + */ +public class RequestAuthenticationException extends ProcessingException { + + /** + * Creates new instance of this exception with exception cause. + * + * @param cause Exception cause. + */ + public RequestAuthenticationException(Throwable cause) { + super(cause); + } + + /** + * Creates new instance of this exception with exception message. + * + * @param message Exception message. + */ + public RequestAuthenticationException(String message) { + super(message); + } + + /** + * Creates new instance of this exception with exception message and exception cause. + * + * @param message Exception message. + * @param cause Exception cause. + */ + public RequestAuthenticationException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/ResponseAuthenticationException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/ResponseAuthenticationException.java new file mode 100644 index 0000000000000..03fa4aa865de6 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/authentication/ResponseAuthenticationException.java @@ -0,0 +1,83 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package org.openhab.binding.lametrictime.api.authentication; + +import javax.ws.rs.client.ResponseProcessingException; +import javax.ws.rs.core.Response; + +/** + * Exception thrown by security response authentication. + * + * @author Petr Bouda (petr.bouda at oracle.com) + */ +public class ResponseAuthenticationException extends ResponseProcessingException { + + /** + * Creates new instance of this exception with exception cause. + * + * @param response the response instance for which the processing failed. + * @param cause Exception cause. + */ + public ResponseAuthenticationException(Response response, Throwable cause) { + super(response, cause); + } + + /** + * Creates new instance of this exception with exception message. + * + * @param response the response instance for which the processing failed. + * @param message Exception message. + */ + public ResponseAuthenticationException(Response response, String message) { + super(response, message); + } + + /** + * Creates new instance of this exception with exception message and exception cause. + * + * @param response the response instance for which the processing failed. + * @param message Exception message. + * @param cause Exception cause. + */ + public ResponseAuthenticationException(Response response, String message, Throwable cause) { + super(response, message, cause); + } + +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/CloudConfiguration.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/CloudConfiguration.java new file mode 100644 index 0000000000000..8f217a0e6cba0 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/CloudConfiguration.java @@ -0,0 +1,91 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud; + +import java.net.URI; + +public class CloudConfiguration +{ + private URI baseUri = URI.create("https://developer.lametric.com/api/v2"); + + private boolean logging = false; + private String logLevel = "INFO"; + private int logMax = 104857600; // 100kb + + public URI getBaseUri() + { + return baseUri; + } + + public void setBaseUri(URI baseUri) + { + this.baseUri = baseUri; + } + + public CloudConfiguration withBaseUri(URI baseUri) + { + this.baseUri = baseUri; + return this; + } + + public boolean isLogging() + { + return logging; + } + + public void setLogging(boolean logging) + { + this.logging = logging; + } + + public CloudConfiguration withLogging(boolean logging) + { + this.logging = logging; + return this; + } + + public String getLogLevel() + { + return logLevel; + } + + public void setLogLevel(String logLevel) + { + this.logLevel = logLevel; + } + + public CloudConfiguration withLogLevel(String logLevel) + { + this.logLevel = logLevel; + return this; + } + + public int getLogMax() + { + return logMax; + } + + public void setLogMax(int logMax) + { + this.logMax = logMax; + } + + public CloudConfiguration withLogMax(int logMax) + { + this.logMax = logMax; + return this; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/LaMetricTimeCloud.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/LaMetricTimeCloud.java new file mode 100644 index 0000000000000..06f06ad0aa265 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/LaMetricTimeCloud.java @@ -0,0 +1,39 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud; + +import javax.ws.rs.client.ClientBuilder; + +import org.openhab.binding.lametrictime.api.cloud.impl.LaMetricTimeCloudImpl; +import org.openhab.binding.lametrictime.api.cloud.model.IconFilter; +import org.openhab.binding.lametrictime.api.cloud.model.Icons; + +public interface LaMetricTimeCloud +{ + public Icons getIcons(); + + public Icons getIcons(IconFilter filter); + + public static LaMetricTimeCloud create(CloudConfiguration config) + { + return new LaMetricTimeCloudImpl(config); + } + + public static LaMetricTimeCloud create(CloudConfiguration config, ClientBuilder clientBuilder) + { + return new LaMetricTimeCloudImpl(config, clientBuilder); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/impl/LaMetricTimeCloudImpl.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/impl/LaMetricTimeCloudImpl.java new file mode 100644 index 0000000000000..11cdf97103f75 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/impl/LaMetricTimeCloudImpl.java @@ -0,0 +1,73 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.impl; + +import java.util.logging.Logger; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.MediaType; + +import org.openhab.binding.lametrictime.api.cloud.CloudConfiguration; +import org.openhab.binding.lametrictime.api.cloud.LaMetricTimeCloud; +import org.openhab.binding.lametrictime.api.cloud.model.IconFilter; +import org.openhab.binding.lametrictime.api.cloud.model.Icons; +import org.openhab.binding.lametrictime.api.common.impl.AbstractClient; +import org.openhab.binding.lametrictime.api.filter.LoggingFilter; +import org.openhab.binding.lametrictime.internal.GsonProvider; + +public class LaMetricTimeCloudImpl extends AbstractClient implements LaMetricTimeCloud { + private final CloudConfiguration config; + + public LaMetricTimeCloudImpl(CloudConfiguration config) { + this.config = config; + } + + public LaMetricTimeCloudImpl(CloudConfiguration config, ClientBuilder clientBuilder) { + super(clientBuilder); + this.config = config; + } + + @Override + public Icons getIcons() { + return getClient().target(config.getBaseUri()).path("/icons").request(MediaType.APPLICATION_JSON_TYPE) + .get(Icons.class); + } + + @Override + public Icons getIcons(IconFilter filter) { + return getClient().target(config.getBaseUri()).path("/icons").queryParam("page", filter.getPage()) + .queryParam("page_size", filter.getPageSize()).queryParam("fields", filter.getFieldsString()) + .queryParam("order", filter.getOrderString()).request(MediaType.APPLICATION_JSON_TYPE).get(Icons.class); + } + + @Override + protected Client createClient() { + ClientBuilder builder = getClientBuilder(); + + // setup Gson (de)serialization + GsonProvider gsonProvider = new GsonProvider<>(); + builder.register(gsonProvider); + + // turn on logging if requested + if (config.isLogging()) { + builder.register( + new LoggingFilter(Logger.getLogger(LaMetricTimeCloudImpl.class.getName()), config.getLogMax())); + } + + return builder.build(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Icon.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Icon.java new file mode 100644 index 0000000000000..99df9454f0e90 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Icon.java @@ -0,0 +1,139 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.model; + +public class Icon +{ + private Integer id; + private String title; + private String code; + private IconType type; + private String category; + private String url; + private Thumb thumb; + + public Integer getId() + { + return id; + } + + public void setId(Integer id) + { + this.id = id; + } + + public Icon withId(Integer id) + { + this.id = id; + return this; + } + + public String getTitle() + { + return title; + } + + public void setTitle(String title) + { + this.title = title; + } + + public Icon withTitle(String title) + { + this.title = title; + return this; + } + + public String getCode() + { + return code; + } + + public void setCode(String code) + { + this.code = code; + } + + public Icon withCode(String code) + { + this.code = code; + return this; + } + + public IconType getType() + { + return type; + } + + public void setType(IconType type) + { + this.type = type; + } + + public Icon withType(IconType type) + { + this.type = type; + return this; + } + + public String getCategory() + { + return category; + } + + public void setCategory(String category) + { + this.category = category; + } + + public Icon withCategory(String category) + { + this.category = category; + return this; + } + + public String getUrl() + { + return url; + } + + public void setUrl(String url) + { + this.url = url; + } + + public Icon withUrl(String url) + { + this.url = url; + return this; + } + + public Thumb getThumb() + { + return thumb; + } + + public void setThumb(Thumb thumb) + { + this.thumb = thumb; + } + + public Icon withThumb(Thumb thumb) + { + this.thumb = thumb; + return this; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconField.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconField.java new file mode 100644 index 0000000000000..4ea57dc075d26 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconField.java @@ -0,0 +1,34 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.model; + +import com.google.gson.annotations.SerializedName; + +public enum IconField +{ + @SerializedName("id") + ID, + @SerializedName("title") + TITLE, + @SerializedName("code") + CODE, + @SerializedName("type") + TYPE, + @SerializedName("url") + URL, + @SerializedName("thumb") + THUMB +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconFilter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconFilter.java new file mode 100644 index 0000000000000..2d2da0a45ff02 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconFilter.java @@ -0,0 +1,113 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.model; + +import java.util.List; + +public class IconFilter +{ + private Integer page; + private Integer pageSize; + private List fields; + private IconOrder order; + + public Integer getPage() + { + return page; + } + + public void setPage(Integer page) + { + this.page = page; + } + + public IconFilter withPage(Integer page) + { + this.page = page; + return this; + } + + public Integer getPageSize() + { + return pageSize; + } + + public void setPageSize(Integer pageSize) + { + this.pageSize = pageSize; + } + + public IconFilter withPageSize(Integer pageSize) + { + this.pageSize = pageSize; + return this; + } + + public List getFields() + { + return fields; + } + + public String getFieldsString() + { + if (fields == null || fields.isEmpty()) + { + return null; + } + + StringBuilder builder = new StringBuilder(); + builder.append(fields.get(0).name().toLowerCase()); + + for (int i = 1; i < fields.size(); i++) + { + builder.append(',').append(fields.get(i).name().toLowerCase()); + } + + return builder.toString(); + } + + public void setFields(List fields) + { + this.fields = fields; + } + + public IconFilter withFields(List fields) + { + this.fields = fields; + return this; + } + + public IconOrder getOrder() + { + return order; + } + + public String getOrderString() + { + return order == null ? null : order.name().toLowerCase(); + } + + public void setOrder(IconOrder order) + { + this.order = order; + } + + public IconFilter withOrder(IconOrder order) + { + this.order = order; + return this; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconOrder.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconOrder.java new file mode 100644 index 0000000000000..bad2ad35dc5c3 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconOrder.java @@ -0,0 +1,28 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.model; + +import com.google.gson.annotations.SerializedName; + +public enum IconOrder +{ + @SerializedName("popular") + POPULAR, + @SerializedName("newest") + NEWEST, + @SerializedName("title") + TITLE +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconType.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconType.java new file mode 100644 index 0000000000000..8c7290f9ce843 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconType.java @@ -0,0 +1,26 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.model; + +import com.google.gson.annotations.SerializedName; + +public enum IconType +{ + @SerializedName("picture") + PICTURE, + @SerializedName("movie") + MOVIE +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Icons.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Icons.java new file mode 100644 index 0000000000000..e38a5f62bfdd4 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Icons.java @@ -0,0 +1,57 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.model; + +import java.util.ArrayList; +import java.util.List; + +public class Icons +{ + private IconsMetadata meta; + private List data = new ArrayList(); + + public IconsMetadata getMeta() + { + return meta; + } + + public void setMeta(IconsMetadata meta) + { + this.meta = meta; + } + + public Icons withMeta(IconsMetadata meta) + { + this.meta = meta; + return this; + } + + public List getData() + { + return data; + } + + public void setData(List data) + { + this.data = data; + } + + public Icons withData(List data) + { + this.data = data; + return this; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconsMetadata.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconsMetadata.java new file mode 100644 index 0000000000000..2a7f6395f568f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/IconsMetadata.java @@ -0,0 +1,88 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.model; + +public class IconsMetadata +{ + private Integer totalIconCount; + private Integer page; + private Integer pageSize; + private Integer pageCount; + + public Integer getTotalIconCount() + { + return totalIconCount; + } + + public void setTotalIconCount(Integer totalIconCount) + { + this.totalIconCount = totalIconCount; + } + + public IconsMetadata withTotalIconCount(Integer totalIconCount) + { + this.totalIconCount = totalIconCount; + return this; + } + + public Integer getPage() + { + return page; + } + + public void setPage(Integer page) + { + this.page = page; + } + + public IconsMetadata withPage(Integer page) + { + this.page = page; + return this; + } + + public Integer getPageSize() + { + return pageSize; + } + + public void setPageSize(Integer pageSize) + { + this.pageSize = pageSize; + } + + public IconsMetadata withPageSize(Integer pageSize) + { + this.pageSize = pageSize; + return this; + } + + public Integer getPageCount() + { + return pageCount; + } + + public void setPageCount(Integer pageCount) + { + this.pageCount = pageCount; + } + + public IconsMetadata withPageCount(Integer pageCount) + { + this.pageCount = pageCount; + return this; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Thumb.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Thumb.java new file mode 100644 index 0000000000000..6a25dc9da41b1 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/cloud/model/Thumb.java @@ -0,0 +1,88 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.cloud.model; + +public class Thumb +{ + private String original; + private String small; + private String large; + private String xlarge; + + public String getOriginal() + { + return original; + } + + public void setOriginal(String original) + { + this.original = original; + } + + public Thumb withOriginal(String original) + { + this.original = original; + return this; + } + + public String getSmall() + { + return small; + } + + public void setSmall(String small) + { + this.small = small; + } + + public Thumb withSmall(String small) + { + this.small = small; + return this; + } + + public String getLarge() + { + return large; + } + + public void setLarge(String large) + { + this.large = large; + } + + public Thumb withLarge(String large) + { + this.large = large; + return this; + } + + public String getXlarge() + { + return xlarge; + } + + public void setXlarge(String xlarge) + { + this.xlarge = xlarge; + } + + public Thumb withXlarge(String xlarge) + { + this.xlarge = xlarge; + return this; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/AbstractClient.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/AbstractClient.java new file mode 100644 index 0000000000000..e557db8b24412 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/AbstractClient.java @@ -0,0 +1,83 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.common.impl; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; + +import com.google.gson.Gson; + +public abstract class AbstractClient +{ + private final ClientBuilder clientBuilder; + + private volatile Client client; + private volatile Gson gson; + + public AbstractClient() + { + this(ClientBuilder.newBuilder()); + } + + public AbstractClient(ClientBuilder clientBuilder) + { + this.clientBuilder = clientBuilder; + } + + protected Client getClient() + { + if (client == null) + { + synchronized (this) + { + if (client == null) + { + client = createClient(); + } + } + } + + return client; + } + + protected Gson getGson() + { + if (gson == null) + { + synchronized (this) + { + if (gson == null) + { + gson = createGson(); + } + } + } + + return gson; + } + + protected abstract Client createClient(); + + protected Gson createGson() + { + return GsonGenerator.create(); + } + + protected ClientBuilder getClientBuilder() + { + return clientBuilder; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/GsonGenerator.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/GsonGenerator.java new file mode 100644 index 0000000000000..b363ab82fdfa6 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/GsonGenerator.java @@ -0,0 +1,68 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.common.impl; + +import org.openhab.binding.lametrictime.api.common.impl.typeadapters.ActionTypeAdapterFactory; +import org.openhab.binding.lametrictime.api.common.impl.typeadapters.ApplicationTypeAdapterFactory; +import org.openhab.binding.lametrictime.api.common.impl.typeadapters.UpdateActionTypeAdapterFactory; +import org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported.JSR310TypeAdapters; +import org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported.RuntimeTypeAdapterFactory; +import org.openhab.binding.lametrictime.api.local.model.BooleanParameter; +import org.openhab.binding.lametrictime.api.local.model.IntegerParameter; +import org.openhab.binding.lametrictime.api.local.model.Parameter; +import org.openhab.binding.lametrictime.api.local.model.StringParameter; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class GsonGenerator +{ + public static Gson create() + { + return create(false); + } + + public static Gson create(boolean prettyPrint) + { + GsonBuilder builder = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .registerTypeAdapterFactory(new ApplicationTypeAdapterFactory()) + .registerTypeAdapterFactory(new ActionTypeAdapterFactory()) + .registerTypeAdapterFactory(new UpdateActionTypeAdapterFactory()) + .registerTypeAdapterFactory(RuntimeTypeAdapterFactory.of(Parameter.class, + "data_type") + .registerSubtype(BooleanParameter.class, + "bool") + .registerSubtype(StringParameter.class, + "string") + .registerSubtype(IntegerParameter.class, + "int")); + + // add Java 8 Time API support + JSR310TypeAdapters.registerJSR310TypeAdapters(builder); + + if (prettyPrint) + { + builder.setPrettyPrinting(); + } + + return builder.create(); + } + + // @formatter:off + private GsonGenerator() {} + // @formatter:on +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/ActionTypeAdapterFactory.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/ActionTypeAdapterFactory.java new file mode 100644 index 0000000000000..e519e8608e21d --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/ActionTypeAdapterFactory.java @@ -0,0 +1,110 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; + +import org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported.CustomizedTypeAdapterFactory; +import org.openhab.binding.lametrictime.api.local.model.Action; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class ActionTypeAdapterFactory extends CustomizedTypeAdapterFactory +{ + private static final String PROPERTY_ID = "id"; + private static final String PROPERTY_PARAMETERS = "params"; + + public ActionTypeAdapterFactory() + { + super(Action.class); + } + + @Override + protected void beforeWrite(Action source, JsonElement toSerialize) + { + if (toSerialize == null || toSerialize.isJsonNull()) + { + return; + } + + JsonObject actionObj = toSerialize.getAsJsonObject(); + if (actionObj == null || actionObj.isJsonNull()) + { + return; + } + + // rewrite parameters from a nested object (map) to properties on the action + JsonElement paramsElem = actionObj.get(PROPERTY_PARAMETERS); + if (paramsElem != null && !paramsElem.isJsonNull()) + { + JsonObject paramsObj = paramsElem.getAsJsonObject(); + actionObj.remove(PROPERTY_PARAMETERS); + + for (Entry entry : paramsObj.entrySet()) + { + actionObj.add(entry.getKey(), entry.getValue()); + } + } + } + + @Override + protected void afterRead(JsonElement deserialized) + { + if (deserialized == null || deserialized.isJsonNull()) + { + return; + } + + JsonObject actionObj = deserialized.getAsJsonObject(); + if (actionObj == null || actionObj.isJsonNull()) + { + return; + } + + if (actionObj.has(PROPERTY_PARAMETERS)) + { + throw new IllegalArgumentException("Attempting to deserialize Action that contains a colliding " + + PROPERTY_PARAMETERS + + " property"); + } + + // temporary list of field names + List fields = new ArrayList<>(); + + // rewrite parameters to a nested object (map) + JsonObject paramsObj = new JsonObject(); + for (Entry entry : actionObj.entrySet()) + { + // skip ID field + if (PROPERTY_ID.equals(entry.getKey())) + { + continue; + } + + String paramId = entry.getKey(); + fields.add(paramId); // to be removed later + + paramsObj.add(paramId, entry.getValue()); + } + actionObj.add(PROPERTY_PARAMETERS, paramsObj); + + // remove all fields other than the list + fields.forEach(field -> actionObj.remove(field)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/ApplicationTypeAdapterFactory.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/ApplicationTypeAdapterFactory.java new file mode 100644 index 0000000000000..fed1281598f11 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/ApplicationTypeAdapterFactory.java @@ -0,0 +1,126 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters; + +import java.util.Map.Entry; + +import org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported.CustomizedTypeAdapterFactory; +import org.openhab.binding.lametrictime.api.local.model.Application; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class ApplicationTypeAdapterFactory extends CustomizedTypeAdapterFactory +{ + private static final String PROPERTY_ID = "id"; + private static final String PROPERTY_WIDGETS = "widgets"; + private static final String PROPERTY_ACTIONS = "actions"; + + public ApplicationTypeAdapterFactory() + { + super(Application.class); + } + + @Override + protected void beforeWrite(Application source, JsonElement toSerialize) + { + if (toSerialize == null || toSerialize.isJsonNull()) + { + return; + } + + JsonObject appObj = toSerialize.getAsJsonObject(); + if (appObj == null || appObj.isJsonNull()) + { + return; + } + + // remove widget IDs + JsonElement widgetsElem = appObj.get(PROPERTY_WIDGETS); + if (widgetsElem != null && !widgetsElem.isJsonNull()) + { + for (Entry entry : widgetsElem.getAsJsonObject().entrySet()) + { + JsonElement widgetElem = entry.getValue(); + if (widgetElem == null || widgetElem.isJsonNull()) + { + continue; + } + widgetElem.getAsJsonObject().remove(PROPERTY_ID); + } + } + + // remove action IDs + JsonElement actionsElem = appObj.get(PROPERTY_ACTIONS); + if (actionsElem != null && !actionsElem.isJsonNull()) + { + for (Entry entry : actionsElem.getAsJsonObject().entrySet()) + { + JsonElement actionElem = entry.getValue(); + if (actionElem == null || actionElem.isJsonNull()) + { + continue; + } + actionElem.getAsJsonObject().remove(PROPERTY_ID); + } + } + } + + @Override + protected void afterRead(JsonElement deserialized) + { + if (deserialized == null || deserialized.isJsonNull()) + { + return; + } + + JsonObject appObj = deserialized.getAsJsonObject(); + if (appObj == null || appObj.isJsonNull()) + { + return; + } + + // inject widget IDs + JsonElement widgetsElem = appObj.get(PROPERTY_WIDGETS); + if (widgetsElem != null && !widgetsElem.isJsonNull()) + { + for (Entry entry : widgetsElem.getAsJsonObject().entrySet()) + { + JsonElement widgetElem = entry.getValue(); + if (widgetElem == null || widgetElem.isJsonNull()) + { + continue; + } + widgetElem.getAsJsonObject().addProperty(PROPERTY_ID, entry.getKey()); + } + } + + // inject action IDs + JsonElement actionsElem = appObj.get(PROPERTY_ACTIONS); + if (actionsElem != null && !actionsElem.isJsonNull()) + { + for (Entry entry : actionsElem.getAsJsonObject().entrySet()) + { + JsonElement actionElem = entry.getValue(); + if (actionElem == null || actionElem.isJsonNull()) + { + continue; + } + actionElem.getAsJsonObject().addProperty(PROPERTY_ID, entry.getKey()); + } + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/UpdateActionTypeAdapterFactory.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/UpdateActionTypeAdapterFactory.java new file mode 100644 index 0000000000000..a7ab0a3637a8e --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/UpdateActionTypeAdapterFactory.java @@ -0,0 +1,75 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters; + +import java.util.Map.Entry; + +import org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported.CustomizedTypeAdapterFactory; +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class UpdateActionTypeAdapterFactory extends CustomizedTypeAdapterFactory +{ + private static final String PROPERTY_PARAMETERS = "params"; + private static final String PROPERTY_VALUE = "value"; + + public UpdateActionTypeAdapterFactory() + { + super(UpdateAction.class); + } + + @Override + protected void beforeWrite(UpdateAction source, JsonElement toSerialize) + { + if (toSerialize == null || toSerialize.isJsonNull()) + { + return; + } + + JsonObject actionObj = toSerialize.getAsJsonObject(); + if (actionObj == null || actionObj.isJsonNull()) + { + return; + } + + // rewrite parameters map from {name => Parameter} to {name => value} + JsonElement paramsElem = actionObj.get(PROPERTY_PARAMETERS); + if (paramsElem != null && !paramsElem.isJsonNull()) + { + JsonObject paramsObj = paramsElem.getAsJsonObject(); + actionObj.remove(PROPERTY_PARAMETERS); + + JsonObject newParamsObj = new JsonObject(); + for (Entry entry : paramsObj.entrySet()) + { + newParamsObj.add(entry.getKey(), + entry.getValue() + .getAsJsonObject() + .getAsJsonPrimitive(PROPERTY_VALUE)); + } + actionObj.add(PROPERTY_PARAMETERS, newParamsObj); + } + } + + @Override + protected void afterRead(JsonElement deserialized) + { + throw new UnsupportedOperationException(UpdateAction.class.getName() + + " cannot be derialized"); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/CustomizedTypeAdapterFactory.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/CustomizedTypeAdapterFactory.java new file mode 100644 index 0000000000000..4bfdc9494cf15 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/CustomizedTypeAdapterFactory.java @@ -0,0 +1,74 @@ +/* + * Pulled from Stack Overflow answer located here: http://stackoverflow.com/a/11272452 + * and placed in an appropriate package within this library. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.io.IOException; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +public abstract class CustomizedTypeAdapterFactory implements TypeAdapterFactory +{ + private final Class customizedClass; + + public CustomizedTypeAdapterFactory(Class customizedClass) + { + this.customizedClass = customizedClass; + } + + @Override + @SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal + public final TypeAdapter create(Gson gson, TypeToken type) + { + return type.getRawType() == customizedClass + ? (TypeAdapter)customizeMyClassAdapter(gson, (TypeToken)type) + : null; + } + + private TypeAdapter customizeMyClassAdapter(Gson gson, TypeToken type) + { + final TypeAdapter delegate = gson.getDelegateAdapter(this, type); + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + return new TypeAdapter() + { + @Override + public void write(JsonWriter out, C value) throws IOException + { + JsonElement tree = delegate.toJsonTree(value); + beforeWrite(value, tree); + elementAdapter.write(out, tree); + } + + @Override + public C read(JsonReader in) throws IOException + { + JsonElement tree = elementAdapter.read(in); + afterRead(tree); + return delegate.fromJsonTree(tree); + } + }; + } + + /** + * Override this to muck with {@code toSerialize} before it is written to + * the outgoing JSON stream. + */ + protected void beforeWrite(C source, JsonElement toSerialize) + { + } + + /** + * Override this to muck with {@code deserialized} before it parsed into the + * application type. + */ + protected void afterRead(JsonElement deserialized) + { + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/DateTimeTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/DateTimeTypeAdapter.java new file mode 100644 index 0000000000000..16a4d144f9580 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/DateTimeTypeAdapter.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.util.function.Function; + +/** + * Abstract type adapter for jsr310 date-time types. + * + * @author Christophe Bornet + */ +abstract class DateTimeTypeAdapter extends TemporalTypeAdapter { + + DateTimeTypeAdapter(Function parseFunction) { + super(parseFunction); + } + + @Override + public String preProcess(String in) { + if (in.endsWith("+0000")) { + return in.substring(0, in.length()-5) + "Z"; + } + return in; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/DurationTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/DurationTypeAdapter.java new file mode 100644 index 0000000000000..bb5e7d010646d --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/DurationTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.Duration; + +/** + * Type adapter for jsr310 {@link Duration} class. + * + * @author Christophe Bornet + */ +public class DurationTypeAdapter extends TemporalTypeAdapter { + + public DurationTypeAdapter() { + super(Duration::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/InstantTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/InstantTypeAdapter.java new file mode 100644 index 0000000000000..6155e4fac446a --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/InstantTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.Instant; + +/** + * Type adapter for jsr310 {@link Instant} class. + * + * @author Christophe Bornet + */ +public class InstantTypeAdapter extends DateTimeTypeAdapter { + + public InstantTypeAdapter() { + super(Instant::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/JSR310TypeAdapters.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/JSR310TypeAdapters.java new file mode 100644 index 0000000000000..de58493bcdcff --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/JSR310TypeAdapters.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import com.google.gson.GsonBuilder; + +import java.time.*; + +/** + * Helper methods to register JSR310 type adapters. + * + * @author Christophe Bornet + */ +public class JSR310TypeAdapters { + + private JSR310TypeAdapters() { + } + + public static GsonBuilder registerDurationTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(Duration.class, new DurationTypeAdapter()); + } + + public static GsonBuilder registerInstantTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(Instant.class, new InstantTypeAdapter()); + } + + public static GsonBuilder registerLocalDateTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter()); + } + + public static GsonBuilder registerLocalDateTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()); + } + + public static GsonBuilder registerLocalTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(LocalTime.class, new LocalTimeTypeAdapter()); + } + + public static GsonBuilder registerMonthDayTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(MonthDay.class, new MonthDayTypeAdapter()); + } + + public static GsonBuilder registerOffsetDateTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()); + } + + public static GsonBuilder registerOffsetTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(OffsetTime.class, new OffsetTimeTypeAdapter()); + } + + public static GsonBuilder registerPeriodTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(Period.class, new PeriodTypeAdapter()); + } + + public static GsonBuilder registerYearMonthTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(YearMonth.class, new YearMonthTypeAdapter()); + } + + public static GsonBuilder registerYearTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(Year.class, new YearTypeAdapter()); + } + + public static GsonBuilder registerZonedDateTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeTypeAdapter()); + } + + + /** + * Helper method to register all the available JSR310 adapters at once. + * @param gsonBuilder the gsonBuilder on which all the JSR310 adapters must be registered. + * @return the gsonBuilder with the JSR310 adapters registered. + */ + public static GsonBuilder registerJSR310TypeAdapters(GsonBuilder gsonBuilder) { + registerDurationTypeAdapter(gsonBuilder); + registerInstantTypeAdapter(gsonBuilder); + registerLocalDateTimeTypeAdapter(gsonBuilder); + registerLocalDateTypeAdapter(gsonBuilder); + registerLocalTimeTypeAdapter(gsonBuilder); + registerMonthDayTypeAdapter(gsonBuilder); + registerOffsetDateTimeTypeAdapter(gsonBuilder); + registerOffsetTimeTypeAdapter(gsonBuilder); + registerPeriodTypeAdapter(gsonBuilder); + registerYearMonthTypeAdapter(gsonBuilder); + registerYearTypeAdapter(gsonBuilder); + registerZonedDateTimeTypeAdapter(gsonBuilder); + + return gsonBuilder; + } + + +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalDateTimeTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalDateTimeTypeAdapter.java new file mode 100644 index 0000000000000..2a97d1a51d207 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalDateTimeTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.LocalDateTime; + +/** + * Type adapter for jsr310 {@link LocalDateTime} class. + * + * @author Christophe Bornet + */ +public class LocalDateTimeTypeAdapter extends DateTimeTypeAdapter { + + public LocalDateTimeTypeAdapter() { + super(LocalDateTime::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalDateTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalDateTypeAdapter.java new file mode 100644 index 0000000000000..34c9978d02fc5 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalDateTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.LocalDate; + +/** + * Type adapter for jsr310 {@link LocalDate} class. + * + * @author Christophe Bornet + */ +public class LocalDateTypeAdapter extends TemporalTypeAdapter { + + public LocalDateTypeAdapter() { + super(LocalDate::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalTimeTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalTimeTypeAdapter.java new file mode 100644 index 0000000000000..9d71534b78bf5 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/LocalTimeTypeAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * Type adapter for jsr310 {@link LocalTime} class. + * + * @author Christophe Bornet + */ +public class LocalTimeTypeAdapter extends TemporalTypeAdapter { + + public LocalTimeTypeAdapter() { + super(LocalTime::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/MonthDayTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/MonthDayTypeAdapter.java new file mode 100644 index 0000000000000..e942a9b3e9283 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/MonthDayTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.MonthDay; + +/** + * Type adapter for jsr310 {@link MonthDay} class. + * + * @author Christophe Bornet + */ +public class MonthDayTypeAdapter extends TemporalTypeAdapter { + + public MonthDayTypeAdapter() { + super(MonthDay::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/OffsetDateTimeTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/OffsetDateTimeTypeAdapter.java new file mode 100644 index 0000000000000..68fda33ae85c4 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/OffsetDateTimeTypeAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Type adapter for jsr310 {@link OffsetDateTime} class. + * + * @author Christophe Bornet + */ +public class OffsetDateTimeTypeAdapter extends DateTimeTypeAdapter { + + public OffsetDateTimeTypeAdapter() { + super(OffsetDateTime::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/OffsetTimeTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/OffsetTimeTypeAdapter.java new file mode 100644 index 0000000000000..c72859c0dda66 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/OffsetTimeTypeAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.OffsetTime; +import java.time.format.DateTimeFormatter; + +/** + * Type adapter for jsr310 {@link OffsetTime} class. + * + * @author Christophe Bornet + */ +public class OffsetTimeTypeAdapter extends TemporalTypeAdapter { + + public OffsetTimeTypeAdapter() { + super(OffsetTime::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/PeriodTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/PeriodTypeAdapter.java new file mode 100644 index 0000000000000..e1a38fb451dd5 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/PeriodTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.Period; + +/** + * Type adapter for jsr310 {@link Period} class. + * + * @author Christophe Bornet + */ +public class PeriodTypeAdapter extends TemporalTypeAdapter { + + public PeriodTypeAdapter() { + super(Period::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/RuntimeTypeAdapterFactory.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/RuntimeTypeAdapterFactory.java new file mode 100644 index 0000000000000..ae1cb753e467c --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/RuntimeTypeAdapterFactory.java @@ -0,0 +1,420 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Copied from + * https://raw.githubusercontent.com/google/gson/master/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java + * and repackaged here with additional content from + * com.google.gson.internal.{Streams,TypeAdapters,LazilyParsedNumber} + * to avoid using the internal package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.io.EOFException; +import java.io.IOException; +import java.io.ObjectStreamException; +import java.math.BigDecimal; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonIOException; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSyntaxException; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import com.google.gson.stream.MalformedJsonException; + +/** + * Adapts values whose runtime type may differ from their declaration type. This + * is necessary when a field's type is not the same type that GSON should create + * when deserializing that field. For example, consider these types: + *
   {@code
+ *   abstract class Shape {
+ *     int x;
+ *     int y;
+ *   }
+ *   class Circle extends Shape {
+ *     int radius;
+ *   }
+ *   class Rectangle extends Shape {
+ *     int width;
+ *     int height;
+ *   }
+ *   class Diamond extends Shape {
+ *     int width;
+ *     int height;
+ *   }
+ *   class Drawing {
+ *     Shape bottomShape;
+ *     Shape topShape;
+ *   }
+ * }
+ *

Without additional type information, the serialized JSON is ambiguous. Is + * the bottom shape in this drawing a rectangle or a diamond?

   {@code
+ *   {
+ *     "bottomShape": {
+ *       "width": 10,
+ *       "height": 5,
+ *       "x": 0,
+ *       "y": 0
+ *     },
+ *     "topShape": {
+ *       "radius": 2,
+ *       "x": 4,
+ *       "y": 1
+ *     }
+ *   }}
+ * This class addresses this problem by adding type information to the + * serialized JSON and honoring that type information when the JSON is + * deserialized:
   {@code
+ *   {
+ *     "bottomShape": {
+ *       "type": "Diamond",
+ *       "width": 10,
+ *       "height": 5,
+ *       "x": 0,
+ *       "y": 0
+ *     },
+ *     "topShape": {
+ *       "type": "Circle",
+ *       "radius": 2,
+ *       "x": 4,
+ *       "y": 1
+ *     }
+ *   }}
+ * Both the type field name ({@code "type"}) and the type labels ({@code + * "Rectangle"}) are configurable. + * + *

Registering Types

+ * Create a {@code RuntimeTypeAdapterFactory} by passing the base type and type field + * name to the {@link #of} factory method. If you don't supply an explicit type + * field name, {@code "type"} will be used.
   {@code
+ *   RuntimeTypeAdapterFactory shapeAdapterFactory
+ *       = RuntimeTypeAdapterFactory.of(Shape.class, "type");
+ * }
+ * Next register all of your subtypes. Every subtype must be explicitly + * registered. This protects your application from injection attacks. If you + * don't supply an explicit type label, the type's simple name will be used. + *
   {@code
+ *   shapeAdapter.registerSubtype(Rectangle.class, "Rectangle");
+ *   shapeAdapter.registerSubtype(Circle.class, "Circle");
+ *   shapeAdapter.registerSubtype(Diamond.class, "Diamond");
+ * }
+ * Finally, register the type adapter factory in your application's GSON builder: + *
   {@code
+ *   Gson gson = new GsonBuilder()
+ *       .registerTypeAdapterFactory(shapeAdapterFactory)
+ *       .create();
+ * }
+ * Like {@code GsonBuilder}, this API supports chaining:
   {@code
+ *   RuntimeTypeAdapterFactory shapeAdapterFactory = RuntimeTypeAdapterFactory.of(Shape.class)
+ *       .registerSubtype(Rectangle.class)
+ *       .registerSubtype(Circle.class)
+ *       .registerSubtype(Diamond.class);
+ * }
+ */ +public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory { + private final Class baseType; + private final String typeFieldName; + private final Map> labelToSubtype = new LinkedHashMap>(); + private final Map, String> subtypeToLabel = new LinkedHashMap, String>(); + + private RuntimeTypeAdapterFactory(Class baseType, String typeFieldName) { + if (typeFieldName == null || baseType == null) { + throw new NullPointerException(); + } + this.baseType = baseType; + this.typeFieldName = typeFieldName; + } + + /** + * Creates a new runtime type adapter using for {@code baseType} using {@code + * typeFieldName} as the type field name. Type field names are case sensitive. + */ + public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName) { + return new RuntimeTypeAdapterFactory(baseType, typeFieldName); + } + + /** + * Creates a new runtime type adapter for {@code baseType} using {@code "type"} as + * the type field name. + */ + public static RuntimeTypeAdapterFactory of(Class baseType) { + return new RuntimeTypeAdapterFactory(baseType, "type"); + } + + /** + * Registers {@code type} identified by {@code label}. Labels are case + * sensitive. + * + * @throws IllegalArgumentException if either {@code type} or {@code label} + * have already been registered on this type adapter. + */ + public RuntimeTypeAdapterFactory registerSubtype(Class type, String label) { + if (type == null || label == null) { + throw new NullPointerException(); + } + if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) { + throw new IllegalArgumentException("types and labels must be unique"); + } + labelToSubtype.put(label, type); + subtypeToLabel.put(type, label); + return this; + } + + /** + * Registers {@code type} identified by its {@link Class#getSimpleName simple + * name}. Labels are case sensitive. + * + * @throws IllegalArgumentException if either {@code type} or its simple name + * have already been registered on this type adapter. + */ + public RuntimeTypeAdapterFactory registerSubtype(Class type) { + return registerSubtype(type, type.getSimpleName()); + } + + public TypeAdapter create(Gson gson, TypeToken type) { + if (type.getRawType() != baseType) { + return null; + } + + final Map> labelToDelegate + = new LinkedHashMap>(); + final Map, TypeAdapter> subtypeToDelegate + = new LinkedHashMap, TypeAdapter>(); + for (Map.Entry> entry : labelToSubtype.entrySet()) { + TypeAdapter delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue())); + labelToDelegate.put(entry.getKey(), delegate); + subtypeToDelegate.put(entry.getValue(), delegate); + } + + return new TypeAdapter() { + @Override public R read(JsonReader in) throws IOException { + JsonElement jsonElement = RuntimeTypeAdapterFactory.parse(in); + JsonElement labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName); + if (labelJsonElement == null) { + throw new JsonParseException("cannot deserialize " + baseType + + " because it does not define a field named " + typeFieldName); + } + String label = labelJsonElement.getAsString(); + @SuppressWarnings("unchecked") // registration requires that subtype extends T + TypeAdapter delegate = (TypeAdapter) labelToDelegate.get(label); + if (delegate == null) { + throw new JsonParseException("cannot deserialize " + baseType + " subtype named " + + label + "; did you forget to register a subtype?"); + } + return delegate.fromJsonTree(jsonElement); + } + + @Override public void write(JsonWriter out, R value) throws IOException { + Class srcType = value.getClass(); + String label = subtypeToLabel.get(srcType); + @SuppressWarnings("unchecked") // registration requires that subtype extends T + TypeAdapter delegate = (TypeAdapter) subtypeToDelegate.get(srcType); + if (delegate == null) { + throw new JsonParseException("cannot serialize " + srcType.getName() + + "; did you forget to register a subtype?"); + } + JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject(); + if (jsonObject.has(typeFieldName)) { + throw new JsonParseException("cannot serialize " + srcType.getName() + + " because it already defines a field named " + typeFieldName); + } + JsonObject clone = new JsonObject(); + clone.add(typeFieldName, new JsonPrimitive(label)); + for (Map.Entry e : jsonObject.entrySet()) { + clone.add(e.getKey(), e.getValue()); + } + RuntimeTypeAdapterFactory.write(clone, out); + } + }.nullSafe(); + } + + /** + * Takes a reader in any state and returns the next value as a JsonElement. + */ + private static JsonElement parse(JsonReader reader) throws JsonParseException { + boolean isEmpty = true; + try { + reader.peek(); + isEmpty = false; + return RuntimeTypeAdapterFactory.JSON_ELEMENT.read(reader); + } catch (EOFException e) { + /* + * For compatibility with JSON 1.5 and earlier, we return a JsonNull for + * empty documents instead of throwing. + */ + if (isEmpty) { + return JsonNull.INSTANCE; + } + // The stream ended prematurely so it is likely a syntax error. + throw new JsonSyntaxException(e); + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + + /** + * Writes the JSON element to the writer, recursively. + */ + private static void write(JsonElement element, JsonWriter writer) throws IOException { + RuntimeTypeAdapterFactory.JSON_ELEMENT.write(writer, element); + } + + private static final TypeAdapter JSON_ELEMENT = new TypeAdapter() { + @Override public JsonElement read(JsonReader in) throws IOException { + switch (in.peek()) { + case STRING: + return new JsonPrimitive(in.nextString()); + case NUMBER: + String number = in.nextString(); + return new JsonPrimitive(new LazilyParsedNumber(number)); + case BOOLEAN: + return new JsonPrimitive(in.nextBoolean()); + case NULL: + in.nextNull(); + return JsonNull.INSTANCE; + case BEGIN_ARRAY: + JsonArray array = new JsonArray(); + in.beginArray(); + while (in.hasNext()) { + array.add(read(in)); + } + in.endArray(); + return array; + case BEGIN_OBJECT: + JsonObject object = new JsonObject(); + in.beginObject(); + while (in.hasNext()) { + object.add(in.nextName(), read(in)); + } + in.endObject(); + return object; + case END_DOCUMENT: + case NAME: + case END_OBJECT: + case END_ARRAY: + default: + throw new IllegalArgumentException(); + } + } + + @Override public void write(JsonWriter out, JsonElement value) throws IOException { + if (value == null || value.isJsonNull()) { + out.nullValue(); + } else if (value.isJsonPrimitive()) { + JsonPrimitive primitive = value.getAsJsonPrimitive(); + if (primitive.isNumber()) { + out.value(primitive.getAsNumber()); + } else if (primitive.isBoolean()) { + out.value(primitive.getAsBoolean()); + } else { + out.value(primitive.getAsString()); + } + + } else if (value.isJsonArray()) { + out.beginArray(); + for (JsonElement e : value.getAsJsonArray()) { + write(out, e); + } + out.endArray(); + + } else if (value.isJsonObject()) { + out.beginObject(); + for (Map.Entry e : value.getAsJsonObject().entrySet()) { + out.name(e.getKey()); + write(out, e.getValue()); + } + out.endObject(); + + } else { + throw new IllegalArgumentException("Couldn't write " + value.getClass()); + } + } + }; + + /** + * This class holds a number value that is lazily converted to a specific number type + * + * @author Inderjeet Singh + */ + public static final class LazilyParsedNumber extends Number { + private final String value; + + public LazilyParsedNumber(String value) { + this.value = value; + } + + @Override + public int intValue() { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + try { + return (int) Long.parseLong(value); + } catch (NumberFormatException nfe) { + return new BigDecimal(value).intValue(); + } + } + } + + @Override + public long longValue() { + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + return new BigDecimal(value).longValue(); + } + } + + @Override + public float floatValue() { + return Float.parseFloat(value); + } + + @Override + public double doubleValue() { + return Double.parseDouble(value); + } + + @Override + public String toString() { + return value; + } + + /** + * If somebody is unlucky enough to have to serialize one of these, serialize + * it as a BigDecimal so that they won't need Gson on the other side to + * deserialize it. + */ + private Object writeReplace() throws ObjectStreamException { + return new BigDecimal(value); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/TemporalTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/TemporalTypeAdapter.java new file mode 100644 index 0000000000000..81dcddc40218e --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/TemporalTypeAdapter.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.time.temporal.TemporalAccessor; +import java.util.Objects; +import java.util.function.Function; + +/** + * Abstract type adapter for jsr310 date-time types. + * + * @author Christophe Bornet + */ +abstract class TemporalTypeAdapter extends TypeAdapter { + + Function parseFunction; + + TemporalTypeAdapter(Function parseFunction) { + Objects.requireNonNull(parseFunction); + this.parseFunction = parseFunction; + } + + @Override + public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(value.toString()); + } + } + + @Override + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + String temporalString = preProcess(in.nextString()); + return parseFunction.apply(temporalString); + } + + public String preProcess(String in) { + return in; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/YearMonthTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/YearMonthTypeAdapter.java new file mode 100644 index 0000000000000..f491e5ae24e86 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/YearMonthTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.YearMonth; + +/** + * Type adapter for jsr310 {@link YearMonth} class. + * + * @author Christophe Bornet + */ +public class YearMonthTypeAdapter extends TemporalTypeAdapter { + + public YearMonthTypeAdapter() { + super(YearMonth::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/YearTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/YearTypeAdapter.java new file mode 100644 index 0000000000000..db406821bf1e9 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/YearTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.Year; + +/** + * Type adapter for jsr310 {@link Year} class. + * + * @author Christophe Bornet + */ +public class YearTypeAdapter extends TemporalTypeAdapter { + + public YearTypeAdapter() { + super(Year::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/ZonedDateTimeTypeAdapter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/ZonedDateTimeTypeAdapter.java new file mode 100644 index 0000000000000..35fd20cf20eba --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/common/impl/typeadapters/imported/ZonedDateTimeTypeAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.lametrictime.api.common.impl.typeadapters.imported; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Type adapter for jsr310 {@link ZonedDateTime} class. + * + * @author Christophe Bornet + */ +public class ZonedDateTimeTypeAdapter extends DateTimeTypeAdapter { + + public ZonedDateTimeTypeAdapter() { + super(ZonedDateTime::parse); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/filter/LoggingFilter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/filter/LoggingFilter.java new file mode 100644 index 0000000000000..7b355cbd2f1d2 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/filter/LoggingFilter.java @@ -0,0 +1,355 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2011-2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package org.openhab.binding.lametrictime.api.filter; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Logger; + +import javax.annotation.Priority; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; + +/** + * Universal logging filter. + *

+ * Can be used on client or server side. Has the highest priority. + * + * @author Pavel Bucek (pavel.bucek at oracle.com) + * @author Martin Matula + */ +@PreMatching +@Priority(Integer.MIN_VALUE) +public final class LoggingFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, + ClientResponseFilter, WriterInterceptor { + + public static final Charset UTF8 = Charset.forName("UTF-8"); + + private static final Logger LOGGER = Logger.getLogger(LoggingFilter.class.getName()); + private static final String NOTIFICATION_PREFIX = "* "; + private static final String REQUEST_PREFIX = "> "; + private static final String RESPONSE_PREFIX = "< "; + private static final String ENTITY_LOGGER_PROPERTY = LoggingFilter.class.getName() + ".entityLogger"; + private static final String LOGGING_ID_PROPERTY = LoggingFilter.class.getName() + ".id"; + + private static final Comparator>> COMPARATOR = new Comparator>>() { + + @Override + public int compare(final Map.Entry> o1, final Map.Entry> o2) { + return o1.getKey().compareToIgnoreCase(o2.getKey()); + } + }; + + private static final int DEFAULT_MAX_ENTITY_SIZE = 8 * 1024; + + // + private final Logger logger; + private final AtomicLong _id = new AtomicLong(0); + private final boolean printEntity; + private final int maxEntitySize; + + /** + * Create a logging filter logging the request and response to a default JDK + * logger, named as the fully qualified class name of this class. Entity + * logging is turned off by default. + */ + public LoggingFilter() { + this(LOGGER, false); + } + + /** + * Create a logging filter with custom logger and custom settings of entity + * logging. + * + * @param logger the logger to log requests and responses. + * @param printEntity if true, entity will be logged as well up to the default maxEntitySize, which is 8KB + */ + public LoggingFilter(final Logger logger, final boolean printEntity) { + this.logger = logger; + this.printEntity = printEntity; + this.maxEntitySize = DEFAULT_MAX_ENTITY_SIZE; + } + + /** + * Creates a logging filter with custom logger and entity logging turned on, but potentially limiting the size + * of entity to be buffered and logged. + * + * @param logger the logger to log requests and responses. + * @param maxEntitySize maximum number of entity bytes to be logged (and buffered) - if the entity is larger, + * logging filter will print (and buffer in memory) only the specified number of bytes + * and print "...more..." string at the end. Negative values are interpreted as zero. + */ + public LoggingFilter(final Logger logger, final int maxEntitySize) { + this.logger = logger; + this.printEntity = true; + this.maxEntitySize = Math.max(0, maxEntitySize); + } + + private void log(final StringBuilder b) { + if (logger != null) { + logger.info(b.toString()); + } + } + + private StringBuilder prefixId(final StringBuilder b, final long id) { + b.append(Long.toString(id)).append(" "); + return b; + } + + private void printRequestLine(final StringBuilder b, final String note, final long id, final String method, + final URI uri) { + prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") + .append(Thread.currentThread().getName()).append("\n"); + prefixId(b, id).append(REQUEST_PREFIX).append(method).append(" ").append(uri.toASCIIString()).append("\n"); + } + + private void printResponseLine(final StringBuilder b, final String note, final long id, final int status) { + prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") + .append(Thread.currentThread().getName()).append("\n"); + prefixId(b, id).append(RESPONSE_PREFIX).append(Integer.toString(status)).append("\n"); + } + + private void printPrefixedHeaders(final StringBuilder b, final long id, final String prefix, + final MultivaluedMap headers) { + for (final Map.Entry> headerEntry : getSortedHeaders(headers.entrySet())) { + final List val = headerEntry.getValue(); + final String header = headerEntry.getKey(); + + if (val.size() == 1) { + prefixId(b, id).append(prefix).append(header).append(": ").append(val.get(0)).append("\n"); + } else { + final StringBuilder sb = new StringBuilder(); + boolean add = false; + for (final Object s : val) { + if (add) { + sb.append(','); + } + add = true; + sb.append(s); + } + prefixId(b, id).append(prefix).append(header).append(": ").append(sb.toString()).append("\n"); + } + } + } + + private Set>> getSortedHeaders(final Set>> headers) { + final TreeSet>> sortedHeaders = new TreeSet>>( + COMPARATOR); + sortedHeaders.addAll(headers); + return sortedHeaders; + } + + private InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) + throws IOException { + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + stream.mark(maxEntitySize + 1); + final byte[] entity = new byte[maxEntitySize + 1]; + final int entitySize = stream.read(entity); + b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); + if (entitySize > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + stream.reset(); + return stream; + } + + @Override + public void filter(final ClientRequestContext context) throws IOException { + final long id = _id.incrementAndGet(); + context.setProperty(LOGGING_ID_PROPERTY, id); + + final StringBuilder b = new StringBuilder(); + + printRequestLine(b, "Sending client request", id, context.getMethod(), context.getUri()); + printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getStringHeaders()); + + if (printEntity && context.hasEntity()) { + final OutputStream stream = new LoggingStream(b, context.getEntityStream()); + context.setEntityStream(stream); + context.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) + throws IOException { + final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); + final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); + + final StringBuilder b = new StringBuilder(); + + printResponseLine(b, "Client response received", id, responseContext.getStatus()); + printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getHeaders()); + + if (printEntity && responseContext.hasEntity()) { + responseContext.setEntityStream( + logInboundEntity(b, responseContext.getEntityStream(), getCharset(responseContext.getMediaType()))); + } + + log(b); + } + + @Override + public void filter(final ContainerRequestContext context) throws IOException { + final long id = _id.incrementAndGet(); + context.setProperty(LOGGING_ID_PROPERTY, id); + + final StringBuilder b = new StringBuilder(); + + printRequestLine(b, "Server has received a request", id, context.getMethod(), + context.getUriInfo().getRequestUri()); + printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getHeaders()); + + if (printEntity && context.hasEntity()) { + context.setEntityStream(logInboundEntity(b, context.getEntityStream(), getCharset(context.getMediaType()))); + } + + log(b); + } + + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) + throws IOException { + final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); + final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); + + final StringBuilder b = new StringBuilder(); + + printResponseLine(b, "Server responded with a response", id, responseContext.getStatus()); + printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getStringHeaders()); + + if (printEntity && responseContext.hasEntity()) { + final OutputStream stream = new LoggingStream(b, responseContext.getEntityStream()); + responseContext.setEntityStream(stream); + requestContext.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void aroundWriteTo(final WriterInterceptorContext writerInterceptorContext) + throws IOException, WebApplicationException { + final LoggingStream stream = (LoggingStream) writerInterceptorContext.getProperty(ENTITY_LOGGER_PROPERTY); + writerInterceptorContext.proceed(); + if (stream != null) { + log(stream.getStringBuilder(getCharset(writerInterceptorContext.getMediaType()))); + } + } + + private class LoggingStream extends FilterOutputStream { + + private final StringBuilder b; + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + LoggingStream(final StringBuilder b, final OutputStream inner) { + super(inner); + + this.b = b; + } + + StringBuilder getStringBuilder(final Charset charset) { + // write entity to the builder + final byte[] entity = baos.toByteArray(); + + b.append(new String(entity, 0, Math.min(entity.length, maxEntitySize), charset)); + if (entity.length > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + + return b; + } + + @Override + public void write(final int i) throws IOException { + if (baos.size() <= maxEntitySize) { + baos.write(i); + } + out.write(i); + } + } + + /** + * Get the character set from a media type. + *

+ * The character set is obtained from the media type parameter "charset". + * If the parameter is not present the {@link #UTF8} charset is utilized. + * + * @param m the media type. + * @return the character set. + */ + public static Charset getCharset(MediaType m) { + String name = (m == null) ? null : m.getParameters().get(MediaType.CHARSET_PARAMETER); + return (name == null) ? UTF8 : Charset.forName(name); + } + +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/AbstractDataIcon.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/AbstractDataIcon.java new file mode 100644 index 0000000000000..6658b53e7213d --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/AbstractDataIcon.java @@ -0,0 +1,76 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.impl; + +import java.util.Base64; + +import org.openhab.binding.lametrictime.api.model.Icon; + +public abstract class AbstractDataIcon implements Icon +{ + private volatile Object CONFIGURE_FLAG; + + private String type; + private byte[] data; + + protected void configure() + { + if (CONFIGURE_FLAG == null) + { + synchronized (this) + { + if (CONFIGURE_FLAG == null) + { + populateFields(); + } + } + } + } + + protected String getType() + { + configure(); + return type; + } + + protected void setType(String type) + { + this.type = type; + } + + protected byte[] getData() + { + configure(); + return data; + } + + protected void setData(byte[] data) + { + this.data = data; + } + + @Override + public String toRaw() + { + return new StringBuilder().append("data:") + .append(getType()) + .append(";base64,") + .append(Base64.getEncoder().encodeToString(getData())) + .toString(); + } + + protected abstract void populateFields(); +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/DataIcon.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/DataIcon.java new file mode 100644 index 0000000000000..cbb15daa3316b --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/DataIcon.java @@ -0,0 +1,37 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.impl; + +public class DataIcon extends AbstractDataIcon +{ + public DataIcon(String mimeType, byte[] data) + { + setType(mimeType); + setData(data); + } + + @Override + protected void configure() + { + // noop + } + + @Override + protected void populateFields() + { + // noop + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/FileIcon.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/FileIcon.java new file mode 100644 index 0000000000000..1b40eeafa9e9f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/FileIcon.java @@ -0,0 +1,55 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.impl; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import javax.activation.MimetypesFileTypeMap; + +public class FileIcon extends AbstractDataIcon +{ + private final MimetypesFileTypeMap mimeTypeMap = new MimetypesFileTypeMap(); + + private final Path path; + + public FileIcon(File file) + { + this(file.toPath()); + } + + public FileIcon(Path path) + { + this.path = path; + mimeTypeMap.addMimeTypes("image/png png PNG"); + } + + @Override + protected void populateFields() + { + setType(mimeTypeMap.getContentType(path.toFile())); + try + { + setData(Files.readAllBytes(path)); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/HTTPIcon.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/HTTPIcon.java new file mode 100644 index 0000000000000..5a89c4be64bf9 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/HTTPIcon.java @@ -0,0 +1,47 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.impl; + +import java.net.URI; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Response; + +public class HTTPIcon extends AbstractDataIcon +{ + private final URI uri; + + public HTTPIcon(String uri) + { + this(URI.create(uri)); + } + + public HTTPIcon(URI uri) + { + this.uri = uri; + } + + @Override + protected void populateFields() + { + Client client = ClientBuilder.newBuilder().build(); + Response response = client.target(uri).request().get(); + + setType(response.getMediaType().toString()); + setData(response.readEntity(byte[].class)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/KeyIcon.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/KeyIcon.java new file mode 100644 index 0000000000000..b711cac1ae461 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/KeyIcon.java @@ -0,0 +1,34 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.impl; + +import org.openhab.binding.lametrictime.api.model.Icon; + +public class KeyIcon implements Icon +{ + private final String key; + + public KeyIcon(String key) + { + this.key = key; + } + + @Override + public String toRaw() + { + return key; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/LaMetricTimeImpl.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/LaMetricTimeImpl.java new file mode 100644 index 0000000000000..cdf7f5ce7f33b --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/impl/LaMetricTimeImpl.java @@ -0,0 +1,334 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.impl; + +import static org.openhab.binding.lametrictime.api.model.ApiValue.raw; + +import java.util.Arrays; + +import javax.ws.rs.client.ClientBuilder; + +import org.openhab.binding.lametrictime.api.Configuration; +import org.openhab.binding.lametrictime.api.LaMetricTime; +import org.openhab.binding.lametrictime.api.cloud.CloudConfiguration; +import org.openhab.binding.lametrictime.api.cloud.LaMetricTimeCloud; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.local.ApplicationActivationException; +import org.openhab.binding.lametrictime.api.local.ApplicationNotFoundException; +import org.openhab.binding.lametrictime.api.local.LaMetricTimeLocal; +import org.openhab.binding.lametrictime.api.local.LocalConfiguration; +import org.openhab.binding.lametrictime.api.local.NotificationCreationException; +import org.openhab.binding.lametrictime.api.local.UpdateException; +import org.openhab.binding.lametrictime.api.local.model.Application; +import org.openhab.binding.lametrictime.api.local.model.Audio; +import org.openhab.binding.lametrictime.api.local.model.Bluetooth; +import org.openhab.binding.lametrictime.api.local.model.Display; +import org.openhab.binding.lametrictime.api.local.model.Frame; +import org.openhab.binding.lametrictime.api.local.model.Notification; +import org.openhab.binding.lametrictime.api.local.model.NotificationModel; +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; +import org.openhab.binding.lametrictime.api.local.model.Widget; +import org.openhab.binding.lametrictime.api.model.CoreAction; +import org.openhab.binding.lametrictime.api.model.CoreApplication; +import org.openhab.binding.lametrictime.api.model.CoreApps; +import org.openhab.binding.lametrictime.api.model.Icon; +import org.openhab.binding.lametrictime.api.model.Icons; +import org.openhab.binding.lametrictime.api.model.enums.BrightnessMode; +import org.openhab.binding.lametrictime.api.model.enums.Priority; +import org.openhab.binding.lametrictime.api.model.enums.Sound; + +public class LaMetricTimeImpl implements LaMetricTime +{ + private final LaMetricTimeLocal local; + private final LaMetricTimeCloud cloud; + + private final Object muteLock = new Object(); + private Integer volumeSaveState; + + public LaMetricTimeImpl(Configuration config) + { + this(config.getLocalConfig(), config.getCloudConfig()); + } + + public LaMetricTimeImpl(Configuration config, ClientBuilder clientBuilder) + { + this(config.getLocalConfig(), config.getCloudConfig(), clientBuilder); + } + + public LaMetricTimeImpl(LocalConfiguration localConfig, CloudConfiguration cloudConfig) + { + this.local = LaMetricTimeLocal.create(localConfig); + this.cloud = LaMetricTimeCloud.create(cloudConfig); + } + + public LaMetricTimeImpl(LocalConfiguration localConfig, + CloudConfiguration cloudConfig, + ClientBuilder clientBuilder) + { + this.local = LaMetricTimeLocal.create(localConfig, clientBuilder); + this.cloud = LaMetricTimeCloud.create(cloudConfig, clientBuilder); + } + + @Override + public String getVersion() + { + return local.getApi().getApiVersion(); + } + + @Override + public String notifyInfo(String message) throws NotificationCreationException + { + return notify(message, Priority.INFO, Icons.key("i1248"), Sound.NOTIFICATION, 1, 1); + } + + @Override + public String notifyWarning(String message) throws NotificationCreationException + { + return notify(message, Priority.WARNING, Icons.key("a2098"), Sound.NOTIFICATION2, 2, 2); + } + + @Override + public String notifyCritical(String message) throws NotificationCreationException + { + return notify(message, Priority.CRITICAL, Icons.key("a4787"), Sound.ALARM1, 0, 0); + } + + @Override + public String notify(String message, + Priority priority, + Icon icon, + Sound sound, + int messageRepeat, + int soundRepeat) throws NotificationCreationException + { + // @formatter:off + NotificationModel model = new NotificationModel() + .withCycles(messageRepeat) + .withFrames(Arrays.asList(new Frame().withText(message) + .withIcon(raw(icon)))); + if (sound != null) + { + model.setSound(new org.openhab.binding.lametrictime.api.local.model.Sound() + .withCategory(raw(sound.getCategory())) + .withId(raw(sound)) + .withRepeat(soundRepeat)); + } + // @formatter:on + + Notification notification = new Notification().withPriority(raw(priority)).withModel(model); + return local.createNotification(notification); + } + + @Override + public Application getClock() + { + return getApplication(CoreApps.clock()); + } + + @Override + public Application getCountdown() + { + return getApplication(CoreApps.countdown()); + } + + @Override + public Application getRadio() + { + return getApplication(CoreApps.radio()); + } + + @Override + public Application getStopwatch() + { + return getApplication(CoreApps.stopwatch()); + } + + @Override + public Application getWeather() + { + return getApplication(CoreApps.weather()); + } + + @Override + public Application getApplication(CoreApplication coreApp) + { + try + { + return getLocalApi().getApplication(coreApp.getPackageName()); + } + catch (ApplicationNotFoundException e) + { + // core apps should never throw errors + throw new RuntimeException("Failed to retrieve core application: " + + coreApp.getPackageName(), + e); + } + } + + @Override + public Application getApplication(String name) throws ApplicationNotFoundException + { + return getLocalApi().getApplication(name); + } + + @Override + public void activateApplication(CoreApplication coreApp) + { + try + { + activateApplication(getApplication(coreApp)); + } + catch (ApplicationActivationException e) + { + // core apps should never throw errors + throw new RuntimeException("Failed to activate core application: " + + coreApp.getPackageName(), + e); + } + } + + @Override + public void activateApplication(Application app) throws ApplicationActivationException + { + getLocalApi().activateApplication(app.getPackageName(), getFirstWidgetId(app)); + } + + @Override + public void activateWidget(Widget widget) throws ApplicationActivationException + { + getLocalApi().activateApplication(widget.getPackageName(), widget.getId()); + } + + @Override + public void doAction(CoreAction coreAction) + { + try + { + doAction(getApplication(coreAction.getApp()), coreAction.getAction()); + } + catch (ApplicationActionException e) + { + // core apps should never throw errors + throw new RuntimeException("Failed to execute weather forecast action", e); + } + } + + @Override + public void doAction(Application app, UpdateAction action) throws ApplicationActionException + { + getLocalApi().doAction(app.getPackageName(), getFirstWidgetId(app), action); + } + + @Override + public void doAction(Widget widget, CoreAction coreAction) throws ApplicationActionException + { + doAction(widget, coreAction.getAction()); + } + + @Override + public void doAction(Widget widget, UpdateAction action) throws ApplicationActionException + { + getLocalApi().doAction(widget.getPackageName(), widget.getId(), action); + } + + protected String getFirstWidgetId(Application app) + { + return app.getWidgets().firstKey(); + } + + @Override + public Display setBrightness(int brightness) throws UpdateException + { + return local.updateDisplay(new Display().withBrightness(brightness) + .withBrightnessMode(raw(BrightnessMode.MANUAL))); + } + + @Override + public Display setBrightnessMode(BrightnessMode mode) throws UpdateException + { + return local.updateDisplay(new Display().withBrightnessMode(raw(mode))); + } + + @Override + public Audio setVolume(int volume) throws UpdateException + { + return local.updateAudio(new Audio().withVolume(volume)); + } + + @Override + public Audio mute() throws UpdateException + { + synchronized (muteLock) + { + Audio audio = local.getAudio(); + if (audio.getVolume() == 0) + { + return audio; + } + + volumeSaveState = audio.getVolume(); + return setVolume(0); + } + } + + @Override + public Audio unmute() throws UpdateException + { + synchronized (muteLock) + { + if (volumeSaveState == null) + { + Audio audio = local.getAudio(); + if (audio.getVolume() == 0) + { + return setVolume(50); + } + else + { + return audio; + } + } + + Audio audio = setVolume(volumeSaveState); + volumeSaveState = null; + return audio; + } + } + + @Override + public Bluetooth setBluetoothActive(boolean active) throws UpdateException + { + return local.updateBluetooth(new Bluetooth().withActive(active)); + } + + @Override + public Bluetooth setBluetoothName(String name) throws UpdateException + { + return local.updateBluetooth(new Bluetooth().withName(name)); + } + + @Override + public LaMetricTimeLocal getLocalApi() + { + return local; + } + + @Override + public LaMetricTimeCloud getCloudApi() + { + return cloud; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationActionException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationActionException.java new file mode 100644 index 0000000000000..afdce96164c25 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationActionException.java @@ -0,0 +1,56 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import org.openhab.binding.lametrictime.api.local.model.Failure; + +public class ApplicationActionException extends LaMetricTimeException +{ + private static final long serialVersionUID = 1L; + + public ApplicationActionException() + { + super(); + } + + public ApplicationActionException(String message) + { + super(message); + } + + public ApplicationActionException(Throwable cause) + { + super(cause); + } + + public ApplicationActionException(String message, Throwable cause) + { + super(message, cause); + } + + public ApplicationActionException(String message, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public ApplicationActionException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationActivationException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationActivationException.java new file mode 100644 index 0000000000000..261a80f9894de --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationActivationException.java @@ -0,0 +1,56 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import org.openhab.binding.lametrictime.api.local.model.Failure; + +public class ApplicationActivationException extends LaMetricTimeException +{ + private static final long serialVersionUID = 1L; + + public ApplicationActivationException() + { + super(); + } + + public ApplicationActivationException(String message) + { + super(message); + } + + public ApplicationActivationException(Throwable cause) + { + super(cause); + } + + public ApplicationActivationException(String message, Throwable cause) + { + super(message, cause); + } + + public ApplicationActivationException(String message, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public ApplicationActivationException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationNotFoundException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationNotFoundException.java new file mode 100644 index 0000000000000..fa41f355e506f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/ApplicationNotFoundException.java @@ -0,0 +1,56 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import org.openhab.binding.lametrictime.api.local.model.Failure; + +public class ApplicationNotFoundException extends LaMetricTimeException +{ + private static final long serialVersionUID = 1L; + + public ApplicationNotFoundException() + { + super(); + } + + public ApplicationNotFoundException(String message) + { + super(message); + } + + public ApplicationNotFoundException(Throwable cause) + { + super(cause); + } + + public ApplicationNotFoundException(String message, Throwable cause) + { + super(message, cause); + } + + public ApplicationNotFoundException(String message, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public ApplicationNotFoundException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LaMetricTimeException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LaMetricTimeException.java new file mode 100644 index 0000000000000..30f4389217713 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LaMetricTimeException.java @@ -0,0 +1,77 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import java.util.List; + +import org.openhab.binding.lametrictime.api.local.model.Error; +import org.openhab.binding.lametrictime.api.local.model.Failure; + +public class LaMetricTimeException extends Exception +{ + private static final long serialVersionUID = 1L; + + public LaMetricTimeException() + { + super(); + } + + public LaMetricTimeException(String message) + { + super(message); + } + + public LaMetricTimeException(Throwable cause) + { + super(cause); + } + + public LaMetricTimeException(String message, Throwable cause) + { + super(message, cause); + } + + public LaMetricTimeException(String message, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public LaMetricTimeException(Failure failure) + { + super(buildMessage(failure)); + } + + private static String buildMessage(Failure failure) + { + StringBuilder builder = new StringBuilder(); + + List errors = failure.getErrors(); + if (!errors.isEmpty()) + { + builder.append(errors.get(0).getMessage()); + } + + for (int i = 1; i < errors.size(); i++) + { + builder.append("; ").append(errors.get(i).getMessage()); + } + + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LaMetricTimeLocal.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LaMetricTimeLocal.java new file mode 100644 index 0000000000000..91c7e898516bc --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LaMetricTimeLocal.java @@ -0,0 +1,93 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import java.util.List; +import java.util.SortedMap; + +import javax.ws.rs.client.ClientBuilder; + +import org.openhab.binding.lametrictime.api.local.impl.LaMetricTimeLocalImpl; +import org.openhab.binding.lametrictime.api.local.model.Api; +import org.openhab.binding.lametrictime.api.local.model.Application; +import org.openhab.binding.lametrictime.api.local.model.Audio; +import org.openhab.binding.lametrictime.api.local.model.Bluetooth; +import org.openhab.binding.lametrictime.api.local.model.Device; +import org.openhab.binding.lametrictime.api.local.model.Display; +import org.openhab.binding.lametrictime.api.local.model.Notification; +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; +import org.openhab.binding.lametrictime.api.local.model.WidgetUpdates; +import org.openhab.binding.lametrictime.api.local.model.Wifi; + +public interface LaMetricTimeLocal +{ + public Api getApi(); + + public Device getDevice(); + + public String createNotification(Notification notification) throws NotificationCreationException; + + public List getNotifications(); + + public Notification getCurrentNotification(); + + public Notification getNotification(String id) throws NotificationNotFoundException; + + public void deleteNotification(String id) throws NotificationNotFoundException; + + public Display getDisplay(); + + public Display updateDisplay(Display display) throws UpdateException; + + public Audio getAudio(); + + public Audio updateAudio(Audio audio) throws UpdateException; + + public Bluetooth getBluetooth(); + + public Bluetooth updateBluetooth(Bluetooth bluetooth) throws UpdateException; + + public Wifi getWifi(); + + public void updateApplication(String packageName, + String accessToken, + WidgetUpdates widgetUpdates) throws UpdateException; + + public SortedMap getApplications(); + + public Application getApplication(String packageName) throws ApplicationNotFoundException; + + public void activatePreviousApplication(); + + public void activateNextApplication(); + + public void activateApplication(String packageName, + String widgetId) throws ApplicationActivationException; + + public void doAction(String packageName, + String widgetId, + UpdateAction action) throws ApplicationActionException; + + public static LaMetricTimeLocal create(LocalConfiguration config) + { + return new LaMetricTimeLocalImpl(config); + } + + public static LaMetricTimeLocal create(LocalConfiguration config, ClientBuilder clientBuilder) + { + return new LaMetricTimeLocalImpl(config, clientBuilder); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LocalConfiguration.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LocalConfiguration.java new file mode 100644 index 0000000000000..128cea2cda42e --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/LocalConfiguration.java @@ -0,0 +1,281 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import java.net.URI; +import java.net.URISyntaxException; + +public class LocalConfiguration +{ + private String host; + private String apiKey; + + private boolean secure = true; + private boolean ignoreCertificateValidation = true; + private boolean ignoreHostnameValidation = true; + + private String insecureScheme = "http"; + private int insecurePort = 8080; + + private String secureScheme = "https"; + private int securePort = 4343; + + private String basePath = "/api/v2"; + + private String authUser = "dev"; + + private boolean logging = false; + private String logLevel = "INFO"; + private int logMax = 104857600; // 100kb + + public String getHost() + { + return host; + } + + public void setHost(String host) + { + this.host = host; + } + + public LocalConfiguration withHost(String host) + { + this.host = host; + return this; + } + + public String getApiKey() + { + return apiKey; + } + + public void setApiKey(String apiKey) + { + this.apiKey = apiKey; + } + + public LocalConfiguration withApiKey(String apiKey) + { + this.apiKey = apiKey; + return this; + } + + public boolean isSecure() + { + return secure; + } + + public void setSecure(boolean secure) + { + this.secure = secure; + } + + public LocalConfiguration withSecure(boolean secure) + { + this.secure = secure; + return this; + } + + public boolean isIgnoreCertificateValidation() + { + return ignoreCertificateValidation; + } + + public void setIgnoreCertificateValidation(boolean ignoreCertificateValidation) + { + this.ignoreCertificateValidation = ignoreCertificateValidation; + } + + public LocalConfiguration withIgnoreCertificateValidation(boolean ignoreCertificateValidation) + { + this.ignoreCertificateValidation = ignoreCertificateValidation; + return this; + } + + public boolean isIgnoreHostnameValidation() + { + return ignoreHostnameValidation; + } + + public void setIgnoreHostnameValidation(boolean ignoreHostnameValidation) + { + this.ignoreHostnameValidation = ignoreHostnameValidation; + } + + public LocalConfiguration withIgnoreHostnameValidation(boolean ignoreHostnameValidation) + { + this.ignoreHostnameValidation = ignoreHostnameValidation; + return this; + } + + public String getInsecureScheme() + { + return insecureScheme; + } + + public void setInsecureScheme(String insecureScheme) + { + this.insecureScheme = insecureScheme; + } + + public LocalConfiguration withInsecureScheme(String insecureScheme) + { + this.insecureScheme = insecureScheme; + return this; + } + + public int getInsecurePort() + { + return insecurePort; + } + + public void setInsecurePort(int insecurePort) + { + this.insecurePort = insecurePort; + } + + public LocalConfiguration withInsecurePort(int insecurePort) + { + this.insecurePort = insecurePort; + return this; + } + + public String getSecureScheme() + { + return secureScheme; + } + + public void setSecureScheme(String secureScheme) + { + this.secureScheme = secureScheme; + } + + public LocalConfiguration withSecureScheme(String secureScheme) + { + this.secureScheme = secureScheme; + return this; + } + + public int getSecurePort() + { + return securePort; + } + + public void setSecurePort(int securePort) + { + this.securePort = securePort; + } + + public LocalConfiguration withSecurePort(int securePort) + { + this.securePort = securePort; + return this; + } + + public String getBasePath() + { + return basePath; + } + + public void setBasePath(String basePath) + { + this.basePath = basePath; + } + + public LocalConfiguration withBasePath(String basePath) + { + this.basePath = basePath; + return this; + } + + public String getAuthUser() + { + return authUser; + } + + public void setAuthUser(String authUser) + { + this.authUser = authUser; + } + + public LocalConfiguration withAuthUser(String authUser) + { + this.authUser = authUser; + return this; + } + + public boolean isLogging() + { + return logging; + } + + public void setLogging(boolean logging) + { + this.logging = logging; + } + + public LocalConfiguration withLogging(boolean logging) + { + this.logging = logging; + return this; + } + + public String getLogLevel() + { + return logLevel; + } + + public void setLogLevel(String logLevel) + { + this.logLevel = logLevel; + } + + public LocalConfiguration withLogLevel(String logLevel) + { + this.logLevel = logLevel; + return this; + } + + public int getLogMax() + { + return logMax; + } + + public void setLogMax(int logMax) + { + this.logMax = logMax; + } + + public LocalConfiguration withLogMax(int logMax) + { + this.logMax = logMax; + return this; + } + + public URI getBaseUri() + { + String scheme = secure ? secureScheme : insecureScheme; + int port = secure ? securePort : insecurePort; + try + { + return new URI(scheme, null, host, port, basePath, null, null); + } + catch (URISyntaxException e) + { + throw new RuntimeException("Invalid configuration", e); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/NotificationCreationException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/NotificationCreationException.java new file mode 100644 index 0000000000000..c07dc39fcb404 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/NotificationCreationException.java @@ -0,0 +1,56 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import org.openhab.binding.lametrictime.api.local.model.Failure; + +public class NotificationCreationException extends LaMetricTimeException +{ + private static final long serialVersionUID = 1L; + + public NotificationCreationException() + { + super(); + } + + public NotificationCreationException(String message) + { + super(message); + } + + public NotificationCreationException(Throwable cause) + { + super(cause); + } + + public NotificationCreationException(String message, Throwable cause) + { + super(message, cause); + } + + public NotificationCreationException(String message, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public NotificationCreationException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/NotificationNotFoundException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/NotificationNotFoundException.java new file mode 100644 index 0000000000000..d34085fc94eab --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/NotificationNotFoundException.java @@ -0,0 +1,56 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import org.openhab.binding.lametrictime.api.local.model.Failure; + +public class NotificationNotFoundException extends LaMetricTimeException +{ + private static final long serialVersionUID = 1L; + + public NotificationNotFoundException() + { + super(); + } + + public NotificationNotFoundException(String message, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public NotificationNotFoundException(String message, Throwable cause) + { + super(message, cause); + } + + public NotificationNotFoundException(String message) + { + super(message); + } + + public NotificationNotFoundException(Throwable cause) + { + super(cause); + } + + public NotificationNotFoundException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/UpdateException.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/UpdateException.java new file mode 100644 index 0000000000000..553e0a1d5917e --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/UpdateException.java @@ -0,0 +1,56 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local; + +import org.openhab.binding.lametrictime.api.local.model.Failure; + +public class UpdateException extends LaMetricTimeException +{ + private static final long serialVersionUID = 1L; + + public UpdateException() + { + super(); + } + + public UpdateException(String message) + { + super(message); + } + + public UpdateException(Throwable cause) + { + super(cause); + } + + public UpdateException(String message, Throwable cause) + { + super(message, cause); + } + + public UpdateException(String message, + Throwable cause, + boolean enableSuppression, + boolean writableStackTrace) + { + super(message, cause, enableSuppression, writableStackTrace); + } + + public UpdateException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/impl/LaMetricTimeLocalImpl.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/impl/LaMetricTimeLocalImpl.java new file mode 100644 index 0000000000000..60b05182140e7 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/impl/LaMetricTimeLocalImpl.java @@ -0,0 +1,382 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.impl; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.List; +import java.util.SortedMap; +import java.util.logging.Logger; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.openhab.binding.lametrictime.api.authentication.HttpAuthenticationFeature; +import org.openhab.binding.lametrictime.api.cloud.impl.LaMetricTimeCloudImpl; +import org.openhab.binding.lametrictime.api.common.impl.AbstractClient; +import org.openhab.binding.lametrictime.api.filter.LoggingFilter; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.local.ApplicationActivationException; +import org.openhab.binding.lametrictime.api.local.ApplicationNotFoundException; +import org.openhab.binding.lametrictime.api.local.LaMetricTimeLocal; +import org.openhab.binding.lametrictime.api.local.LocalConfiguration; +import org.openhab.binding.lametrictime.api.local.NotificationCreationException; +import org.openhab.binding.lametrictime.api.local.NotificationNotFoundException; +import org.openhab.binding.lametrictime.api.local.UpdateException; +import org.openhab.binding.lametrictime.api.local.model.Api; +import org.openhab.binding.lametrictime.api.local.model.Application; +import org.openhab.binding.lametrictime.api.local.model.Audio; +import org.openhab.binding.lametrictime.api.local.model.AudioUpdateResult; +import org.openhab.binding.lametrictime.api.local.model.Bluetooth; +import org.openhab.binding.lametrictime.api.local.model.BluetoothUpdateResult; +import org.openhab.binding.lametrictime.api.local.model.Device; +import org.openhab.binding.lametrictime.api.local.model.Display; +import org.openhab.binding.lametrictime.api.local.model.DisplayUpdateResult; +import org.openhab.binding.lametrictime.api.local.model.Failure; +import org.openhab.binding.lametrictime.api.local.model.Notification; +import org.openhab.binding.lametrictime.api.local.model.NotificationResult; +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; +import org.openhab.binding.lametrictime.api.local.model.WidgetUpdates; +import org.openhab.binding.lametrictime.api.local.model.Wifi; +import org.openhab.binding.lametrictime.internal.GsonProvider; + +import com.google.gson.reflect.TypeToken; + +public class LaMetricTimeLocalImpl extends AbstractClient implements LaMetricTimeLocal { + private static final String HEADER_ACCESS_TOKEN = "X-Access-Token"; + + private final LocalConfiguration config; + + private volatile Api api; + + public LaMetricTimeLocalImpl(LocalConfiguration config) { + this.config = config; + } + + public LaMetricTimeLocalImpl(LocalConfiguration config, ClientBuilder clientBuilder) { + super(clientBuilder); + this.config = config; + } + + @Override + public Api getApi() { + if (api == null) { + synchronized (this) { + if (api == null) { + api = getClient().target(config.getBaseUri()).request(MediaType.APPLICATION_JSON_TYPE) + .get(Api.class); + } + } + } + + // remove support for v2.0.0 which has several errors in returned endpoints + if ("2.0.0".equals(api.getApiVersion())) { + throw new IllegalStateException( + "API version 2.0.0 detected, but 2.1.0 or greater is required. Please upgrade LaMetric Time firmware to version 1.7.7 or later. See http://lametric.com/firmware for more information."); + } + + return api; + } + + @Override + public Device getDevice() { + return getClient().target(getApi().getEndpoints().getDeviceUrl()).request(MediaType.APPLICATION_JSON_TYPE) + .get(Device.class); + } + + @Override + public String createNotification(Notification notification) throws NotificationCreationException { + Response response = getClient().target(getApi().getEndpoints().getNotificationsUrl()) + .request(MediaType.APPLICATION_JSON_TYPE).post(Entity.json(notification)); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new NotificationCreationException(response.readEntity(Failure.class)); + } + + try { + return response.readEntity(NotificationResult.class).getSuccess().getId(); + } catch (Exception e) { + throw new NotificationCreationException("Invalid JSON returned from service", e); + } + } + + @Override + public List getNotifications() { + Response response = getClient().target(getApi().getEndpoints().getNotificationsUrl()) + .request(MediaType.APPLICATION_JSON_TYPE).get(); + + // @formatter:off + return getGson().fromJson(response.readEntity(String.class), + new TypeToken>(){}.getType()); + // @formatter:on + } + + @Override + public Notification getCurrentNotification() { + Notification notification = getClient().target(getApi().getEndpoints().getCurrentNotificationUrl()) + .request(MediaType.APPLICATION_JSON_TYPE).get(Notification.class); + + // when there is no current notification, return null + if (notification.getId() == null) { + return null; + } + + return notification; + } + + @Override + public Notification getNotification(String id) throws NotificationNotFoundException { + Response response = getClient() + .target(getApi().getEndpoints().getConcreteNotificationUrl().replace("{:id}", id)) + .request(MediaType.APPLICATION_JSON_TYPE).get(); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new NotificationNotFoundException(response.readEntity(Failure.class)); + } + + return response.readEntity(Notification.class); + } + + @Override + public void deleteNotification(String id) throws NotificationNotFoundException { + Response response = getClient() + .target(getApi().getEndpoints().getConcreteNotificationUrl().replace("{:id}", id)) + .request(MediaType.APPLICATION_JSON_TYPE).delete(); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new NotificationNotFoundException(response.readEntity(Failure.class)); + } + + response.close(); + } + + @Override + public Display getDisplay() { + return getClient().target(getApi().getEndpoints().getDisplayUrl()).request(MediaType.APPLICATION_JSON_TYPE) + .get(Display.class); + } + + @Override + public Display updateDisplay(Display display) throws UpdateException { + Response response = getClient().target(getApi().getEndpoints().getDisplayUrl()) + .request(MediaType.APPLICATION_JSON_TYPE).put(Entity.json(display)); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new UpdateException(response.readEntity(Failure.class)); + } + + return response.readEntity(DisplayUpdateResult.class).getSuccess().getData(); + } + + @Override + public Audio getAudio() { + return getClient().target(getApi().getEndpoints().getAudioUrl()).request(MediaType.APPLICATION_JSON_TYPE) + .get(Audio.class); + } + + @Override + public Audio updateAudio(Audio audio) throws UpdateException { + Response response = getClient().target(getApi().getEndpoints().getAudioUrl()) + .request(MediaType.APPLICATION_JSON_TYPE).put(Entity.json(audio)); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new UpdateException(response.readEntity(Failure.class)); + } + + return response.readEntity(AudioUpdateResult.class).getSuccess().getData(); + } + + @Override + public Bluetooth getBluetooth() { + return getClient().target(getApi().getEndpoints().getBluetoothUrl()).request(MediaType.APPLICATION_JSON_TYPE) + .get(Bluetooth.class); + } + + @Override + public Bluetooth updateBluetooth(Bluetooth bluetooth) throws UpdateException { + Response response = getClient().target(getApi().getEndpoints().getBluetoothUrl()) + .request(MediaType.APPLICATION_JSON_TYPE).put(Entity.json(bluetooth)); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new UpdateException(response.readEntity(Failure.class)); + } + + return response.readEntity(BluetoothUpdateResult.class).getSuccess().getData(); + } + + @Override + public Wifi getWifi() { + return getClient().target(getApi().getEndpoints().getWifiUrl()).request(MediaType.APPLICATION_JSON_TYPE) + .get(Wifi.class); + } + + @Override + public void updateApplication(String packageName, String accessToken, WidgetUpdates widgetUpdates) + throws UpdateException { + Response response = getClient() + .target(getApi().getEndpoints().getWidgetUpdateUrl().replace("{:id}", packageName)) + .request(MediaType.APPLICATION_JSON_TYPE).header(HEADER_ACCESS_TOKEN, accessToken) + .post(Entity.json(widgetUpdates)); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new UpdateException(response.readEntity(Failure.class)); + } + + response.close(); + } + + @Override + public SortedMap getApplications() { + Response response = getClient().target(getApi().getEndpoints().getAppsListUrl()) + .request(MediaType.APPLICATION_JSON_TYPE).get(); + + // @formatter:off + return getGson().fromJson(response.readEntity(String.class), + new TypeToken>(){}.getType()); + // @formatter:on + } + + @Override + public Application getApplication(String packageName) throws ApplicationNotFoundException { + Response response = getClient().target(getApi().getEndpoints().getAppsGetUrl().replace("{:id}", packageName)) + .request(MediaType.APPLICATION_JSON_TYPE).get(); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new ApplicationNotFoundException(response.readEntity(Failure.class)); + } + + return response.readEntity(Application.class); + } + + @Override + public void activatePreviousApplication() { + getClient().target(getApi().getEndpoints().getAppsSwitchPrevUrl()).request(MediaType.APPLICATION_JSON_TYPE) + .put(Entity.json(new Object())); + } + + @Override + public void activateNextApplication() { + getClient().target(getApi().getEndpoints().getAppsSwitchNextUrl()).request(MediaType.APPLICATION_JSON_TYPE) + .put(Entity.json(new Object())); + } + + @Override + public void activateApplication(String packageName, String widgetId) throws ApplicationActivationException { + Response response = getClient().target(getApi().getEndpoints().getAppsSwitchUrl().replace("{:id}", packageName) + .replace("{:widget_id}", widgetId)).request(MediaType.APPLICATION_JSON_TYPE) + .put(Entity.json(new Object())); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new ApplicationActivationException(response.readEntity(Failure.class)); + } + + response.close(); + } + + @Override + public void doAction(String packageName, String widgetId, UpdateAction action) throws ApplicationActionException { + Response response = getClient().target(getApi().getEndpoints().getAppsActionUrl().replace("{:id}", packageName) + .replace("{:widget_id}", widgetId)).request(MediaType.APPLICATION_JSON_TYPE).post(Entity.json(action)); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { + throw new ApplicationActionException(response.readEntity(Failure.class)); + } + + response.close(); + } + + @Override + protected Client createClient() { + ClientBuilder builder = ClientBuilder.newBuilder(); + + // setup Gson (de)serialization + GsonProvider gsonProvider = new GsonProvider<>(); + builder.register(gsonProvider); + + if (config.isSecure()) { + /* + * The certificate presented by LaMetric time is self-signed. + * Therefore, unless the user takes action by adding the certificate + * chain to the Java keystore, HTTPS will fail. + * + * By setting the ignoreCertificateValidation configuration option + * to true (default), HTTPS will be used and the connection will be + * encrypted, but the validity of the certificate is not confirmed. + */ + if (config.isIgnoreCertificateValidation()) { + try { + SSLContext sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(null, new TrustManager[] { new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + // noop + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) + throws CertificateException { + // noop + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + } }, new java.security.SecureRandom()); + builder.sslContext(sslcontext); + } catch (KeyManagementException | NoSuchAlgorithmException e) { + throw new RuntimeException("Failed to setup secure communication", e); + } + } + + /* + * The self-signed certificate used by LaMetric time does not match + * the host when configured on a network. This makes the HTTPS + * handshake fail. + * + * By setting the ignoreHostnameValidation configuration option to + * true (default), HTTPS will be used and the connection will be + * encrypted, but the validity of the hostname in the certificate is + * not confirmed. + */ + if (config.isIgnoreHostnameValidation()) { + builder.hostnameVerifier((host, session) -> true); + } + } + + // turn on logging if requested + if (config.isLogging()) { + builder.register( + new LoggingFilter(Logger.getLogger(LaMetricTimeCloudImpl.class.getName()), config.getLogMax())); + } + + // setup basic auth + builder.register(HttpAuthenticationFeature.basic(config.getAuthUser(), config.getApiKey())); + + return builder.build(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Action.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Action.java new file mode 100644 index 0000000000000..d0fbe544f0c9a --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Action.java @@ -0,0 +1,122 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.util.SortedMap; + +import com.google.gson.annotations.SerializedName; + +public class Action +{ + private String id; + @SerializedName("params") + private SortedMap parameters; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Action withId(String id) + { + setId(id); + return this; + } + + public SortedMap getParameters() + { + return parameters; + } + + public void setParameters(SortedMap parameters) + { + this.parameters = parameters; + } + + public Action withParameters(SortedMap parameters) + { + setParameters(parameters); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((parameters == null) ? 0 : parameters.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + Action other = (Action)obj; + if (id == null) + { + if (other.id != null) + { + return false; + } + } + else if (!id.equals(other.id)) + { + return false; + } + if (parameters == null) + { + if (other.parameters != null) + { + return false; + } + } + else if (!parameters.equals(other.parameters)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Action [id="); + builder.append(id); + builder.append(", parameters="); + builder.append(parameters); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Api.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Api.java new file mode 100644 index 0000000000000..83ba2c17eac9d --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Api.java @@ -0,0 +1,66 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Api +{ + private String apiVersion; + private Endpoints endpoints; + + public String getApiVersion() + { + return apiVersion; + } + + public void setApiVersion(String apiVersion) + { + this.apiVersion = apiVersion; + } + + public Api withApiVersion(String apiVersion) + { + this.apiVersion = apiVersion; + return this; + } + + public Endpoints getEndpoints() + { + return endpoints; + } + + public void setEndpoints(Endpoints endpoints) + { + this.endpoints = endpoints; + } + + public Api withEndpoints(Endpoints endpoints) + { + this.endpoints = endpoints; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Api [apiVersion="); + builder.append(apiVersion); + builder.append(", endpoints="); + builder.append(endpoints); + builder.append("]"); + return builder.toString(); + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Application.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Application.java new file mode 100644 index 0000000000000..487a9ff6158a4 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Application.java @@ -0,0 +1,198 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.util.SortedMap; + +import com.google.gson.annotations.SerializedName; + +public class Application +{ + private SortedMap actions; + @SerializedName("package") + private String packageName; + private String vendor; + private String version; + private String versionCode; + private SortedMap widgets; + + public SortedMap getActions() + { + return actions; + } + + public void setActions(SortedMap actions) + { + this.actions = actions; + } + + public Application withActions(SortedMap actions) + { + setActions(actions); + return this; + } + + public String getPackageName() + { + return packageName; + } + + public void setPackageName(String packageName) + { + this.packageName = packageName; + } + + public Application withPackageName(String packageName) + { + setPackageName(packageName); + return this; + } + + public String getVendor() + { + return vendor; + } + + public void setVendor(String vendor) + { + this.vendor = vendor; + } + + public Application withVendor(String vendor) + { + setVendor(vendor); + return this; + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public Application withVersion(String version) + { + setVersion(version); + return this; + } + + public String getVersionCode() + { + return versionCode; + } + + public void setVersionCode(String versionCode) + { + this.versionCode = versionCode; + } + + public Application withVersionCode(String versionCode) + { + setVersionCode(versionCode); + return this; + } + + public SortedMap getWidgets() + { + return widgets; + } + + public void setWidgets(SortedMap widgets) + { + this.widgets = widgets; + } + + public Application withWidgets(SortedMap widgets) + { + setWidgets(widgets); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((packageName == null) ? 0 : packageName.hashCode()); + result = prime * result + ((versionCode == null) ? 0 : versionCode.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + Application other = (Application)obj; + if (packageName == null) + { + if (other.packageName != null) + { + return false; + } + } + else if (!packageName.equals(other.packageName)) + { + return false; + } + if (versionCode == null) + { + if (other.versionCode != null) + { + return false; + } + } + else if (!versionCode.equals(other.versionCode)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Application [actions="); + builder.append(actions); + builder.append(", packageName="); + builder.append(packageName); + builder.append(", vendor="); + builder.append(vendor); + builder.append(", version="); + builder.append(version); + builder.append(", versionCode="); + builder.append(versionCode); + builder.append(", widgets="); + builder.append(widgets); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Audio.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Audio.java new file mode 100644 index 0000000000000..1282ad9fc5401 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Audio.java @@ -0,0 +1,47 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Audio +{ + private Integer volume; + + public Integer getVolume() + { + return volume; + } + + public void setVolume(Integer volume) + { + this.volume = volume; + } + + public Audio withVolume(Integer volume) + { + this.volume = volume; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Audio [volume="); + builder.append(volume); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/AudioUpdateResult.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/AudioUpdateResult.java new file mode 100644 index 0000000000000..d5a5ddfbf6884 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/AudioUpdateResult.java @@ -0,0 +1,58 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class AudioUpdateResult +{ + private Success success; + + public Success getSuccess() + { + return success; + } + + public void setSuccess(Success success) + { + this.success = success; + } + + public AudioUpdateResult withSuccess(Success success) + { + this.success = success; + return this; + } + + public static class Success + { + private Audio data; + + public Audio getData() + { + return data; + } + + public void setData(Audio data) + { + this.data = data; + } + + public Success withData(Audio data) + { + this.data = data; + return this; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Bluetooth.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Bluetooth.java new file mode 100644 index 0000000000000..83f1f16d2c3ad --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Bluetooth.java @@ -0,0 +1,153 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Bluetooth +{ + private Boolean active; + + /* + * API sometimes calls this field 'mac' and other times calls it 'address'. + * Additionally, Gson uses fields only (not methods). Therefore, if use the + * same instance of this class to read one value and then try to write the + * other without calling the setter, it won't work (the other value will be + * null). + */ + private String mac; + private String address; + + private Boolean available; + private Boolean discoverable; + private String name; + private Boolean pairable; + + public Boolean isActive() + { + return active; + } + + public void setActive(Boolean active) + { + this.active = active; + } + + public Bluetooth withActive(Boolean active) + { + this.active = active; + return this; + } + + public String getMac() + { + return mac == null ? address : mac; + } + + public void setMac(String mac) + { + this.mac = mac; + this.address = mac; + } + + public Bluetooth withMac(String mac) + { + setMac(mac); + return this; + } + + public Boolean isAvailable() + { + return available; + } + + public void setAvailable(Boolean available) + { + this.available = available; + } + + public Bluetooth withAvailable(Boolean available) + { + this.available = available; + return this; + } + + public Boolean isDiscoverable() + { + return discoverable; + } + + public void setDiscoverable(Boolean discoverable) + { + this.discoverable = discoverable; + } + + public Bluetooth withDiscoverable(Boolean discoverable) + { + this.discoverable = discoverable; + return this; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public Bluetooth withName(String name) + { + this.name = name; + return this; + } + + public Boolean isPairable() + { + return pairable; + } + + public void setPairable(Boolean pairable) + { + this.pairable = pairable; + } + + public Bluetooth withPairable(Boolean pairable) + { + this.pairable = pairable; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Bluetooth [active="); + builder.append(active); + builder.append(", mac="); + builder.append(getMac()); + builder.append(", available="); + builder.append(available); + builder.append(", discoverable="); + builder.append(discoverable); + builder.append(", name="); + builder.append(name); + builder.append(", pairable="); + builder.append(pairable); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/BluetoothUpdateResult.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/BluetoothUpdateResult.java new file mode 100644 index 0000000000000..a28b78781506f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/BluetoothUpdateResult.java @@ -0,0 +1,58 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class BluetoothUpdateResult +{ + private Success success; + + public Success getSuccess() + { + return success; + } + + public void setSuccess(Success success) + { + this.success = success; + } + + public BluetoothUpdateResult withSuccess(Success success) + { + this.success = success; + return this; + } + + public static class Success + { + private Bluetooth data; + + public Bluetooth getData() + { + return data; + } + + public void setData(Bluetooth data) + { + this.data = data; + } + + public Success withData(Bluetooth data) + { + this.data = data; + return this; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/BooleanParameter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/BooleanParameter.java new file mode 100644 index 0000000000000..cb3c3f2b411f0 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/BooleanParameter.java @@ -0,0 +1,65 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class BooleanParameter extends Parameter +{ + private Boolean value; + + @Override + public BooleanParameter withName(String name) + { + super.withName(name); + return this; + } + + @Override + public BooleanParameter withRequired(Boolean required) + { + super.withRequired(required); + return this; + } + + public Boolean getValue() + { + return value; + } + + public void setValue(Boolean value) + { + this.value = value; + } + + public BooleanParameter withValue(Boolean value) + { + setValue(value); + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BooleanParameter [value="); + builder.append(value); + builder.append(", getName()="); + builder.append(getName()); + builder.append(", getRequired()="); + builder.append(getRequired()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Device.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Device.java new file mode 100644 index 0000000000000..61ca40a44f9e0 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Device.java @@ -0,0 +1,218 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Device +{ + private Audio audio; + private Bluetooth bluetooth; + private Display display; + private String id; + private String mode; + private String model; + private String name; + private String osVersion; + private String serialNumber; + private Wifi wifi; + + public Audio getAudio() + { + return audio; + } + + public void setAudio(Audio audio) + { + this.audio = audio; + } + + public Device withAudio(Audio audio) + { + this.audio = audio; + return this; + } + + public Bluetooth getBluetooth() + { + return bluetooth; + } + + public void setBluetooth(Bluetooth bluetooth) + { + this.bluetooth = bluetooth; + } + + public Device withBluetooth(Bluetooth bluetooth) + { + this.bluetooth = bluetooth; + return this; + } + + public Display getDisplay() + { + return display; + } + + public void setDisplay(Display display) + { + this.display = display; + } + + public Device withDisplay(Display display) + { + this.display = display; + return this; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Device withId(String id) + { + this.id = id; + return this; + } + + public String getMode() + { + return mode; + } + + public void setMode(String mode) + { + this.mode = mode; + } + + public Device withMode(String mode) + { + this.mode = mode; + return this; + } + + public String getModel() + { + return model; + } + + public void setModel(String model) + { + this.model = model; + } + + public Device withModel(String model) + { + this.model = model; + return this; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public Device withName(String name) + { + this.name = name; + return this; + } + + public String getOsVersion() + { + return osVersion; + } + + public void setOsVersion(String osVersion) + { + this.osVersion = osVersion; + } + + public Device withOsVersion(String osVersion) + { + this.osVersion = osVersion; + return this; + } + + public String getSerialNumber() + { + return serialNumber; + } + + public void setSerialNumber(String serialNumber) + { + this.serialNumber = serialNumber; + } + + public Device withSerialNumber(String serialNumber) + { + this.serialNumber = serialNumber; + return this; + } + + public Wifi getWifi() + { + return wifi; + } + + public void setWifi(Wifi wifi) + { + this.wifi = wifi; + } + + public Device withWifi(Wifi wifi) + { + this.wifi = wifi; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Device [audio="); + builder.append(audio); + builder.append(", bluetooth="); + builder.append(bluetooth); + builder.append(", display="); + builder.append(display); + builder.append(", id="); + builder.append(id); + builder.append(", mode="); + builder.append(mode); + builder.append(", model="); + builder.append(model); + builder.append(", name="); + builder.append(name); + builder.append(", osVersion="); + builder.append(osVersion); + builder.append(", serialNumber="); + builder.append(serialNumber); + builder.append(", wifi="); + builder.append(wifi); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Display.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Display.java new file mode 100644 index 0000000000000..057812a32407e --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Display.java @@ -0,0 +1,142 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Display +{ + private Integer brightness; + private String brightnessMode; + private Integer height; + private Screensaver screensaver; + private String type; + private Integer width; + + public Integer getBrightness() + { + return brightness; + } + + public void setBrightness(Integer brightness) + { + this.brightness = brightness; + } + + public Display withBrightness(Integer brightness) + { + this.brightness = brightness; + return this; + } + + public String getBrightnessMode() + { + return brightnessMode; + } + + public void setBrightnessMode(String brightnessMode) + { + this.brightnessMode = brightnessMode; + } + + public Display withBrightnessMode(String brightnessMode) + { + this.brightnessMode = brightnessMode; + return this; + } + + public Integer getHeight() + { + return height; + } + + public void setHeight(Integer height) + { + this.height = height; + } + + public Display withHeight(Integer height) + { + this.height = height; + return this; + } + + public Screensaver getScreensaver() + { + return screensaver; + } + + public void setScreensaver(Screensaver screensaver) + { + this.screensaver = screensaver; + } + + public Display withScreensaver(Screensaver screensaver) + { + this.screensaver = screensaver; + return this; + } + + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } + + public Display withType(String type) + { + this.type = type; + return this; + } + + public Integer getWidth() + { + return width; + } + + public void setWidth(Integer width) + { + this.width = width; + } + + public Display withWidth(Integer width) + { + this.width = width; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Display [brightness="); + builder.append(brightness); + builder.append(", brightnessMode="); + builder.append(brightnessMode); + builder.append(", height="); + builder.append(height); + builder.append(", screensaver="); + builder.append(screensaver); + builder.append(", type="); + builder.append(type); + builder.append(", width="); + builder.append(width); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/DisplayUpdateResult.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/DisplayUpdateResult.java new file mode 100644 index 0000000000000..948ade75b7076 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/DisplayUpdateResult.java @@ -0,0 +1,58 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class DisplayUpdateResult +{ + private Success success; + + public Success getSuccess() + { + return success; + } + + public void setSuccess(Success success) + { + this.success = success; + } + + public DisplayUpdateResult withSuccess(Success success) + { + this.success = success; + return this; + } + + public static class Success + { + private Display data; + + public Display getData() + { + return data; + } + + public void setData(Display data) + { + this.data = data; + } + + public Success withData(Display data) + { + this.data = data; + return this; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Endpoints.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Endpoints.java new file mode 100644 index 0000000000000..827feb4c7f086 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Endpoints.java @@ -0,0 +1,313 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Endpoints +{ + private String appsActionUrl; + private String appsGetUrl; + private String appsListUrl; + private String appsSwitchNextUrl; + private String appsSwitchPrevUrl; + private String appsSwitchUrl; + private String audioUrl; + private String bluetoothUrl; + private String concreteNotificationUrl; + private String currentNotificationUrl; + private String deviceUrl; + private String displayUrl; + private String notificationsUrl; + private String widgetUpdateUrl; + private String wifiUrl; + + public String getAppsActionUrl() + { + return appsActionUrl; + } + + public void setAppsActionUrl(String appsActionUrl) + { + this.appsActionUrl = appsActionUrl; + } + + public Endpoints withAppsActionUrl(String appsActionUrl) + { + this.appsActionUrl = appsActionUrl; + return this; + } + + public String getAppsGetUrl() + { + return appsGetUrl; + } + + public void setAppsGetUrl(String appsGetUrl) + { + this.appsGetUrl = appsGetUrl; + } + + public Endpoints withAppsGetUrl(String appsGetUrl) + { + this.appsGetUrl = appsGetUrl; + return this; + } + + public String getAppsListUrl() + { + return appsListUrl; + } + + public void setAppsListUrl(String appsListUrl) + { + this.appsListUrl = appsListUrl; + } + + public Endpoints withAppsListUrl(String appsListUrl) + { + this.appsListUrl = appsListUrl; + return this; + } + + public String getAppsSwitchNextUrl() + { + return appsSwitchNextUrl; + } + + public void setAppsSwitchNextUrl(String appsSwitchNextUrl) + { + this.appsSwitchNextUrl = appsSwitchNextUrl; + } + + public Endpoints withAppsSwitchNextUrl(String appsSwitchNextUrl) + { + this.appsSwitchNextUrl = appsSwitchNextUrl; + return this; + } + + public String getAppsSwitchPrevUrl() + { + return appsSwitchPrevUrl; + } + + public void setAppsSwitchPrevUrl(String appsSwitchPrevUrl) + { + this.appsSwitchPrevUrl = appsSwitchPrevUrl; + } + + public Endpoints withAppsSwitchPrevUrl(String appsSwitchPrevUrl) + { + this.appsSwitchPrevUrl = appsSwitchPrevUrl; + return this; + } + + public String getAppsSwitchUrl() + { + return appsSwitchUrl; + } + + public void setAppsSwitchUrl(String appsSwitchUrl) + { + this.appsSwitchUrl = appsSwitchUrl; + } + + public Endpoints withAppsSwitchUrl(String appsSwitchUrl) + { + this.appsSwitchUrl = appsSwitchUrl; + return this; + } + + public String getAudioUrl() + { + return audioUrl; + } + + public void setAudioUrl(String audioUrl) + { + this.audioUrl = audioUrl; + } + + public Endpoints withAudioUrl(String audioUrl) + { + this.audioUrl = audioUrl; + return this; + } + + public String getBluetoothUrl() + { + return bluetoothUrl; + } + + public void setBluetoothUrl(String bluetoothUrl) + { + this.bluetoothUrl = bluetoothUrl; + } + + public Endpoints withBluetoothUrl(String bluetoothUrl) + { + this.bluetoothUrl = bluetoothUrl; + return this; + } + + public String getConcreteNotificationUrl() + { + return concreteNotificationUrl; + } + + public void setConcreteNotificationUrl(String concreteNotificationUrl) + { + this.concreteNotificationUrl = concreteNotificationUrl; + } + + public Endpoints withConcreteNotificationUrl(String concreteNotificationUrl) + { + this.concreteNotificationUrl = concreteNotificationUrl; + return this; + } + + public String getCurrentNotificationUrl() + { + return currentNotificationUrl; + } + + public void setCurrentNotificationUrl(String currentNotificationUrl) + { + this.currentNotificationUrl = currentNotificationUrl; + } + + public Endpoints withCurrentNotificationUrl(String currentNotificationUrl) + { + this.currentNotificationUrl = currentNotificationUrl; + return this; + } + + public String getDeviceUrl() + { + return deviceUrl; + } + + public void setDeviceUrl(String deviceUrl) + { + this.deviceUrl = deviceUrl; + } + + public Endpoints withDeviceUrl(String deviceUrl) + { + this.deviceUrl = deviceUrl; + return this; + } + + public String getDisplayUrl() + { + return displayUrl; + } + + public void setDisplayUrl(String displayUrl) + { + this.displayUrl = displayUrl; + } + + public Endpoints withDisplayUrl(String displayUrl) + { + this.displayUrl = displayUrl; + return this; + } + + public String getNotificationsUrl() + { + return notificationsUrl; + } + + public void setNotificationsUrl(String notificationsUrl) + { + this.notificationsUrl = notificationsUrl; + } + + public Endpoints withNotificationsUrl(String notificationsUrl) + { + this.notificationsUrl = notificationsUrl; + return this; + } + + public String getWidgetUpdateUrl() + { + return widgetUpdateUrl; + } + + public void setWidgetUpdateUrl(String widgetUpdateUrl) + { + this.widgetUpdateUrl = widgetUpdateUrl; + } + + public Endpoints withWidgetUpdateUrl(String widgetUpdateUrl) + { + this.widgetUpdateUrl = widgetUpdateUrl; + return this; + } + + public String getWifiUrl() + { + return wifiUrl; + } + + public void setWifiUrl(String wifiUrl) + { + this.wifiUrl = wifiUrl; + } + + public Endpoints withWifiUrl(String wifiUrl) + { + this.wifiUrl = wifiUrl; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Endpoints [appsActionUrl="); + builder.append(appsActionUrl); + builder.append(", appsGetUrl="); + builder.append(appsGetUrl); + builder.append(", appsListUrl="); + builder.append(appsListUrl); + builder.append(", appsSwitchNextUrl="); + builder.append(appsSwitchNextUrl); + builder.append(", appsSwitchPrevUrl="); + builder.append(appsSwitchPrevUrl); + builder.append(", appsSwitchUrl="); + builder.append(appsSwitchUrl); + builder.append(", audioUrl="); + builder.append(audioUrl); + builder.append(", bluetoothUrl="); + builder.append(bluetoothUrl); + builder.append(", concreteNotificationUrl="); + builder.append(concreteNotificationUrl); + builder.append(", currentNotificationUrl="); + builder.append(currentNotificationUrl); + builder.append(", deviceUrl="); + builder.append(deviceUrl); + builder.append(", displayUrl="); + builder.append(displayUrl); + builder.append(", notificationsUrl="); + builder.append(notificationsUrl); + builder.append(", widgetUpdateUrl="); + builder.append(widgetUpdateUrl); + builder.append(", wifiUrl="); + builder.append(wifiUrl); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Error.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Error.java new file mode 100644 index 0000000000000..d37b7b5bd3870 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Error.java @@ -0,0 +1,47 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Error +{ + private String message; + + public String getMessage() + { + return message; + } + + public void setMessage(String message) + { + this.message = message; + } + + public Error withMessage(String message) + { + this.message = message; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Error [message="); + builder.append(message); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Failure.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Failure.java new file mode 100644 index 0000000000000..32b5b3d3f0556 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Failure.java @@ -0,0 +1,50 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.util.ArrayList; +import java.util.List; + +public class Failure +{ + private List errors = new ArrayList(); + + public List getErrors() + { + return errors; + } + + public void setErrors(List errors) + { + this.errors = errors; + } + + public Failure withErrors(List errors) + { + this.errors = errors; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Failure [errors="); + builder.append(errors); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Frame.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Frame.java new file mode 100644 index 0000000000000..4e490830e293c --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Frame.java @@ -0,0 +1,129 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +public class Frame +{ + private String icon; + private String text; + @SerializedName("goalData") + private GoalData goalData; + @SerializedName("chartData") + private List chartData; + private Integer index; + + public String getIcon() + { + return icon; + } + + public void setIcon(String icon) + { + this.icon = icon; + } + + public Frame withIcon(String icon) + { + this.icon = icon; + return this; + } + + public String getText() + { + return text; + } + + public void setText(String text) + { + this.text = text; + } + + public Frame withText(String text) + { + this.text = text; + return this; + } + + public GoalData getGoalData() + { + return goalData; + } + + public void setGoalData(GoalData goalData) + { + this.goalData = goalData; + } + + public Frame withGoalData(GoalData goalData) + { + this.goalData = goalData; + return this; + } + + public List getChartData() + { + return chartData; + } + + public void setChartData(List chartData) + { + this.chartData = chartData; + } + + public Frame withChartData(List chartData) + { + this.chartData = chartData; + return this; + } + + public Integer getIndex() + { + return index; + } + + public void setIndex(Integer index) + { + this.index = index; + } + + public Frame withIndex(Integer index) + { + this.index = index; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Frame [icon="); + builder.append(icon); + builder.append(", text="); + builder.append(text); + builder.append(", goalData="); + builder.append(goalData); + builder.append(", chartData="); + builder.append(chartData); + builder.append(", index="); + builder.append(index); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/GoalData.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/GoalData.java new file mode 100644 index 0000000000000..6a9d04b748f6d --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/GoalData.java @@ -0,0 +1,179 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class GoalData +{ + private Integer start; + private Integer current; + private Integer end; + private String unit; + + public Integer getStart() + { + return start; + } + + public void setStart(Integer start) + { + this.start = start; + } + + public GoalData withStart(Integer start) + { + this.start = start; + return this; + } + + public Integer getCurrent() + { + return current; + } + + public void setCurrent(Integer current) + { + this.current = current; + } + + public GoalData withCurrent(Integer current) + { + this.current = current; + return this; + } + + public Integer getEnd() + { + return end; + } + + public void setEnd(Integer end) + { + this.end = end; + } + + public GoalData withEnd(Integer end) + { + this.end = end; + return this; + } + + public String getUnit() + { + return unit; + } + + public void setUnit(String unit) + { + this.unit = unit; + } + + public GoalData withUnit(String unit) + { + this.unit = unit; + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((current == null) ? 0 : current.hashCode()); + result = prime * result + ((end == null) ? 0 : end.hashCode()); + result = prime * result + ((start == null) ? 0 : start.hashCode()); + result = prime * result + ((unit == null) ? 0 : unit.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + GoalData other = (GoalData)obj; + if (current == null) + { + if (other.current != null) + { + return false; + } + } + else if (!current.equals(other.current)) + { + return false; + } + if (end == null) + { + if (other.end != null) + { + return false; + } + } + else if (!end.equals(other.end)) + { + return false; + } + if (start == null) + { + if (other.start != null) + { + return false; + } + } + else if (!start.equals(other.start)) + { + return false; + } + if (unit == null) + { + if (other.unit != null) + { + return false; + } + } + else if (!unit.equals(other.unit)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("GoalData [start="); + builder.append(start); + builder.append(", current="); + builder.append(current); + builder.append(", end="); + builder.append(end); + builder.append(", unit="); + builder.append(unit); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/IntegerParameter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/IntegerParameter.java new file mode 100644 index 0000000000000..6f351829fdb67 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/IntegerParameter.java @@ -0,0 +1,65 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class IntegerParameter extends Parameter +{ + private Integer value; + + @Override + public IntegerParameter withName(String name) + { + super.withName(name); + return this; + } + + @Override + public IntegerParameter withRequired(Boolean required) + { + super.withRequired(required); + return this; + } + + public Integer getValue() + { + return value; + } + + public void setValue(Integer value) + { + this.value = value; + } + + public IntegerParameter withValue(Integer value) + { + setValue(value); + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("IntegerParameter [value="); + builder.append(value); + builder.append(", getName()="); + builder.append(getName()); + builder.append(", getRequired()="); + builder.append(getRequired()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Modes.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Modes.java new file mode 100644 index 0000000000000..eb73595d04e15 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Modes.java @@ -0,0 +1,66 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Modes +{ + private TimeBased timeBased; + private WhenDark whenDark; + + public TimeBased getTimeBased() + { + return timeBased; + } + + public void setTimeBased(TimeBased timeBased) + { + this.timeBased = timeBased; + } + + public Modes withTimeBased(TimeBased timeBased) + { + this.timeBased = timeBased; + return this; + } + + public WhenDark getWhenDark() + { + return whenDark; + } + + public void setWhenDark(WhenDark whenDark) + { + this.whenDark = whenDark; + } + + public Modes withWhenDark(WhenDark whenDark) + { + this.whenDark = whenDark; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Modes [timeBased="); + builder.append(timeBased); + builder.append(", whenDark="); + builder.append(whenDark); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Notification.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Notification.java new file mode 100644 index 0000000000000..f0a57e097d1fe --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Notification.java @@ -0,0 +1,182 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.time.LocalDateTime; + +public class Notification +{ + private String id; + private String type; + private LocalDateTime created; + private LocalDateTime expirationDate; + private String priority; + private String iconType; + private Integer lifetime; + private NotificationModel model; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Notification withId(String id) + { + this.id = id; + return this; + } + + public String getType() + { + return type; + } + + public void setType(String type) + { + this.type = type; + } + + public Notification withType(String type) + { + this.type = type; + return this; + } + + public LocalDateTime getCreated() + { + return created; + } + + public void setCreated(LocalDateTime created) + { + this.created = created; + } + + public Notification withCreated(LocalDateTime created) + { + this.created = created; + return this; + } + + public LocalDateTime getExpirationDate() + { + return expirationDate; + } + + public void setExpirationDate(LocalDateTime expirationDate) + { + this.expirationDate = expirationDate; + } + + public Notification withExpirationDate(LocalDateTime expirationDate) + { + this.expirationDate = expirationDate; + return this; + } + + public String getPriority() + { + return priority; + } + + public void setPriority(String priority) + { + this.priority = priority; + } + + public Notification withPriority(String priority) + { + this.priority = priority; + return this; + } + + public String getIconType() + { + return iconType; + } + + public void setIconType(String iconType) + { + this.iconType = iconType; + } + + public Notification withIconType(String iconType) + { + this.iconType = iconType; + return this; + } + + public Integer getLifetime() + { + return lifetime; + } + + public void setLifetime(Integer lifetime) + { + this.lifetime = lifetime; + } + + public Notification withLifetime(Integer lifetime) + { + this.lifetime = lifetime; + return this; + } + + public NotificationModel getModel() + { + return model; + } + + public void setModel(NotificationModel model) + { + this.model = model; + } + + public Notification withModel(NotificationModel model) + { + this.model = model; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Notification [id="); + builder.append(id); + builder.append(", type="); + builder.append(type); + builder.append(", created="); + builder.append(created); + builder.append(", expirationDate="); + builder.append(expirationDate); + builder.append(", priority="); + builder.append(priority); + builder.append(", iconType="); + builder.append(iconType); + builder.append(", lifetime="); + builder.append(lifetime); + builder.append(", model="); + builder.append(model); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/NotificationModel.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/NotificationModel.java new file mode 100644 index 0000000000000..48d5936a238f3 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/NotificationModel.java @@ -0,0 +1,87 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.util.List; + +public class NotificationModel +{ + private Integer cycles; + private List frames; + private Sound sound; + + public Integer getCycles() + { + return cycles; + } + + public void setCycles(Integer cycles) + { + this.cycles = cycles; + } + + public NotificationModel withCycles(Integer cycles) + { + this.cycles = cycles; + return this; + } + + public List getFrames() + { + return frames; + } + + public void setFrames(List frames) + { + this.frames = frames; + } + + public NotificationModel withFrames(List frames) + { + this.frames = frames; + return this; + } + + public Sound getSound() + { + return sound; + } + + public void setSound(Sound sound) + { + this.sound = sound; + } + + public NotificationModel withSound(Sound sound) + { + this.sound = sound; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("NotificationModel [cycles="); + builder.append(cycles); + builder.append(", frames="); + builder.append(frames); + builder.append(", sound="); + builder.append(sound); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/NotificationResult.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/NotificationResult.java new file mode 100644 index 0000000000000..6e1ecc6bd799e --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/NotificationResult.java @@ -0,0 +1,58 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class NotificationResult +{ + private Success success; + + public Success getSuccess() + { + return success; + } + + public void setSuccess(Success success) + { + this.success = success; + } + + public NotificationResult withSuccess(Success success) + { + this.success = success; + return this; + } + + public static class Success + { + private String id; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Success withId(String id) + { + this.id = id; + return this; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Parameter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Parameter.java new file mode 100644 index 0000000000000..38afe7fee93c3 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Parameter.java @@ -0,0 +1,54 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public abstract class Parameter +{ + private String name; + private Boolean required; + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public Parameter withName(String name) + { + setName(name); + return this; + } + + public Boolean getRequired() + { + return required; + } + + public void setRequired(Boolean required) + { + this.required = required; + } + + public Parameter withRequired(Boolean required) + { + setRequired(required); + return this; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Screensaver.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Screensaver.java new file mode 100644 index 0000000000000..923cb2205cd4b --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Screensaver.java @@ -0,0 +1,85 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Screensaver +{ + private Boolean enabled; + private Modes modes; + private String widget; + + public Boolean isEnabled() + { + return enabled; + } + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public Screensaver withEnabled(Boolean enabled) + { + this.enabled = enabled; + return this; + } + + public Modes getModes() + { + return modes; + } + + public void setModes(Modes modes) + { + this.modes = modes; + } + + public Screensaver withModes(Modes modes) + { + this.modes = modes; + return this; + } + + public String getWidget() + { + return widget; + } + + public void setWidget(String widget) + { + this.widget = widget; + } + + public Screensaver withWidget(String widget) + { + this.widget = widget; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Screensaver [enabled="); + builder.append(enabled); + builder.append(", modes="); + builder.append(modes); + builder.append(", widget="); + builder.append(widget); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Sound.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Sound.java new file mode 100644 index 0000000000000..e0fe6343e7926 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Sound.java @@ -0,0 +1,85 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Sound +{ + private String category; + private String id; + private Integer repeat; + + public String getCategory() + { + return category; + } + + public void setCategory(String category) + { + this.category = category; + } + + public Sound withCategory(String category) + { + this.category = category; + return this; + } + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Sound withId(String id) + { + this.id = id; + return this; + } + + public Integer getRepeat() + { + return repeat; + } + + public void setRepeat(Integer repeat) + { + this.repeat = repeat; + } + + public Sound withRepeat(Integer repeat) + { + this.repeat = repeat; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Sound [category="); + builder.append(category); + builder.append(", id="); + builder.append(id); + builder.append(", repeat="); + builder.append(repeat); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/StringParameter.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/StringParameter.java new file mode 100644 index 0000000000000..502914938f42b --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/StringParameter.java @@ -0,0 +1,84 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class StringParameter extends Parameter +{ + private String format; + private String value; + + @Override + public StringParameter withName(String name) + { + super.withName(name); + return this; + } + + @Override + public StringParameter withRequired(Boolean required) + { + super.withRequired(required); + return this; + } + + public String getFormat() + { + return format; + } + + public void setFormat(String format) + { + this.format = format; + } + + public StringParameter withFormat(String format) + { + setFormat(format); + return this; + } + + public String getValue() + { + return value; + } + + public void setValue(String value) + { + this.value = value; + } + + public StringParameter withValue(String value) + { + setValue(value); + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("StringParameter [format="); + builder.append(format); + builder.append(", value="); + builder.append(value); + builder.append(", getName()="); + builder.append(getName()); + builder.append(", getRequired()="); + builder.append(getRequired()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/TimeBased.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/TimeBased.java new file mode 100644 index 0000000000000..59e8ca1345347 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/TimeBased.java @@ -0,0 +1,47 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class TimeBased +{ + private Boolean enabled; + + public Boolean isEnabled() + { + return enabled; + } + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public TimeBased withEnabled(Boolean enabled) + { + this.enabled = enabled; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("TimeBased [enabled="); + builder.append(enabled); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/UpdateAction.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/UpdateAction.java new file mode 100644 index 0000000000000..c7428a6d1a7b9 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/UpdateAction.java @@ -0,0 +1,35 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.util.SortedMap; + +public class UpdateAction extends Action +{ + @Override + public UpdateAction withId(String id) + { + super.setId(id); + return this; + } + + @Override + public UpdateAction withParameters(SortedMap parameters) + { + super.setParameters(parameters); + return this; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/WhenDark.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/WhenDark.java new file mode 100644 index 0000000000000..b3c87dadca6b1 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/WhenDark.java @@ -0,0 +1,47 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class WhenDark +{ + private Boolean enabled; + + public Boolean isEnabled() + { + return enabled; + } + + public void setEnabled(Boolean enabled) + { + this.enabled = enabled; + } + + public WhenDark withEnabled(Boolean enabled) + { + this.enabled = enabled; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("WhenDark [enabled="); + builder.append(enabled); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Widget.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Widget.java new file mode 100644 index 0000000000000..41ae5190af9d7 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Widget.java @@ -0,0 +1,185 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.util.Map; + +import com.google.gson.JsonPrimitive; +import com.google.gson.annotations.SerializedName; + +public class Widget +{ + private String id; + @SerializedName("package") + private String packageName; + private Integer index; + private Map settings; + + public String getId() + { + return id; + } + + public void setId(String id) + { + this.id = id; + } + + public Widget withId(String id) + { + setId(id); + return this; + } + + public String getPackageName() + { + return packageName; + } + + public void setPackageName(String packageName) + { + this.packageName = packageName; + } + + public Widget withPackageName(String packageName) + { + setPackageName(packageName); + return this; + } + + public Integer getIndex() + { + return index; + } + + public void setIndex(Integer index) + { + this.index = index; + } + + public Widget withIndex(Integer index) + { + setIndex(index); + return this; + } + + public Map getSettings() + { + return settings; + } + + public void setSettings(Map settings) + { + this.settings = settings; + } + + public Widget withSettings(Map settings) + { + setSettings(settings); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + result = prime * result + ((index == null) ? 0 : index.hashCode()); + result = prime * result + ((packageName == null) ? 0 : packageName.hashCode()); + result = prime * result + ((settings == null) ? 0 : settings.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (getClass() != obj.getClass()) + { + return false; + } + Widget other = (Widget)obj; + if (id == null) + { + if (other.id != null) + { + return false; + } + } + else if (!id.equals(other.id)) + { + return false; + } + if (index == null) + { + if (other.index != null) + { + return false; + } + } + else if (!index.equals(other.index)) + { + return false; + } + if (packageName == null) + { + if (other.packageName != null) + { + return false; + } + } + else if (!packageName.equals(other.packageName)) + { + return false; + } + if (settings == null) + { + if (other.settings != null) + { + return false; + } + } + else if (!settings.equals(other.settings)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Widget [id="); + builder.append(id); + builder.append(", packageName="); + builder.append(packageName); + builder.append(", index="); + builder.append(index); + builder.append(", settings="); + builder.append(settings); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/WidgetUpdates.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/WidgetUpdates.java new file mode 100644 index 0000000000000..a3c9fd10be1fe --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/WidgetUpdates.java @@ -0,0 +1,49 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import java.util.List; + +public class WidgetUpdates +{ + private List frames; + + public List getFrames() + { + return frames; + } + + public void setFrames(List frames) + { + this.frames = frames; + } + + public WidgetUpdates withFrames(List frames) + { + this.frames = frames; + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("WidgetUpdates [frames="); + builder.append(frames); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Wifi.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Wifi.java new file mode 100644 index 0000000000000..542f603b23e18 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/local/model/Wifi.java @@ -0,0 +1,241 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +public class Wifi +{ + private Boolean active; + + /* + * API sometimes calls this field 'mac' and other times calls it 'address'. + * Additionally, Gson uses fields only (not methods). Therefore, if use the + * same instance of this class to read one value and then try to write the + * other without calling the setter, it won't work (the other value will be + * null). + */ + private String mac; + private String address; + + private Boolean available; + private String encryption; + + /* + * API sometimes calls this field 'ssid' and other times calls it 'essid'. + * Additionally, Gson uses fields only (not methods). Therefore, if use the + * same instance of this class to read one value and then try to write the + * other without calling the setter, it won't work (the other value will be + * null). + */ + private String ssid; + private String essid; + + /* + * API sometimes calls this field 'ip' and other times calls it 'ipv4'. + * Additionally, Gson uses fields only (not methods). Therefore, if use the + * same instance of this class to read one value and then try to write the + * other without calling the setter, it won't work (the other value will be + * null). + */ + private String ip; + private String ipv4; + + private String mode; + private String netmask; + + /* + * API sometimes calls this field 'signal_strength' and other times calls it + * 'strength'. Additionally, Gson uses fields only (not methods). Therefore, + * if use the same instance of this class to read one value and then try to + * write the other without calling the setter, it won't work (the other + * value will be null). + */ + private Integer signalStrength; + private Integer strength; + + public Boolean isActive() + { + return active; + } + + public void setActive(Boolean active) + { + this.active = active; + } + + public Wifi withActive(Boolean active) + { + this.active = active; + return this; + } + + public String getMac() + { + return mac == null ? address : mac; + } + + public void setMac(String mac) + { + this.mac = mac; + this.address = mac; + } + + public Wifi withMac(String mac) + { + setMac(mac); + return this; + } + + public Boolean isAvailable() + { + return available; + } + + public void setAvailable(Boolean available) + { + this.available = available; + } + + public Wifi withAvailable(Boolean available) + { + this.available = available; + return this; + } + + public String getEncryption() + { + return encryption; + } + + public void setEncryption(String encryption) + { + this.encryption = encryption; + } + + public Wifi withEncryption(String encryption) + { + this.encryption = encryption; + return this; + } + + public String getSsid() + { + return ssid == null ? essid : ssid; + } + + public void setSsid(String ssid) + { + this.ssid = ssid; + this.essid = ssid; + } + + public Wifi withSsid(String ssid) + { + setSsid(ssid); + return this; + } + + public String getIp() + { + return ip == null ? ipv4 : ip; + } + + public void setIp(String ip) + { + this.ip = ip; + this.ipv4 = ip; + } + + public Wifi withIp(String ip) + { + setIp(ip); + return this; + } + + public String getMode() + { + return mode; + } + + public void setMode(String mode) + { + this.mode = mode; + } + + public Wifi withMode(String mode) + { + this.mode = mode; + return this; + } + + public String getNetmask() + { + return netmask; + } + + public void setNetmask(String netmask) + { + this.netmask = netmask; + } + + public Wifi withNetmask(String netmask) + { + this.netmask = netmask; + return this; + } + + public Integer getSignalStrength() + { + return signalStrength == null ? strength : signalStrength; + } + + public void setSignalStrength(Integer signalStrength) + { + this.signalStrength = signalStrength; + this.strength = signalStrength; + } + + public Wifi withSignalStrength(Integer signalStrength) + { + setSignalStrength(signalStrength); + return this; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Wifi [active="); + builder.append(active); + builder.append(", mac="); + builder.append(getMac()); + builder.append(", available="); + builder.append(available); + builder.append(", encryption="); + builder.append(encryption); + builder.append(", ssid="); + builder.append(getSsid()); + builder.append(", ip="); + builder.append(getIp()); + builder.append(", mode="); + builder.append(mode); + builder.append(", netmask="); + builder.append(netmask); + builder.append(", signalStrength="); + builder.append(getSignalStrength()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/ApiValue.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/ApiValue.java new file mode 100644 index 0000000000000..30df5532f35b1 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/ApiValue.java @@ -0,0 +1,31 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +public interface ApiValue +{ + public String toRaw(); + + public static String raw(ApiValue value) + { + if (value == null) + { + return null; + } + + return value.toRaw(); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/ClockApp.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/ClockApp.java new file mode 100644 index 0000000000000..2483e00ad50ff --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/ClockApp.java @@ -0,0 +1,78 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.openhab.binding.lametrictime.api.local.model.BooleanParameter; +import org.openhab.binding.lametrictime.api.local.model.Parameter; +import org.openhab.binding.lametrictime.api.local.model.StringParameter; +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; + +public class ClockApp extends CoreApplication +{ + private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss"); + + private static final String NAME = "com.lametric.clock"; + + private static final String ACTION_ALARM = "clock.alarm"; + + private static final String PARAMETER_ENABLED = "enabled"; + private static final String PARAMETER_TIME = "time"; + private static final String PARAMETER_WAKE_WITH_RADIO = "wake_with_radio"; + + public ClockApp() + { + super(NAME); + } + + public CoreAction setAlarm(Boolean enabled, LocalTime time, Boolean wakeWithRadio) + { + SortedMap parameters = new TreeMap<>(); + + if (enabled != null) + { + parameters.put(PARAMETER_ENABLED, new BooleanParameter().withValue(enabled)); + } + + if (time != null) + { + parameters.put(PARAMETER_TIME, + new StringParameter().withValue(time.format(TIME_FORMATTER))); + } + + if (wakeWithRadio != null) + { + parameters.put(PARAMETER_WAKE_WITH_RADIO, + new BooleanParameter().withValue(wakeWithRadio)); + } + + return new CoreAction(this, + new UpdateAction().withId(ACTION_ALARM).withParameters(parameters)); + } + + public CoreAction stopAlarm() + { + SortedMap parameters = new TreeMap<>(); + parameters.put(PARAMETER_ENABLED, new BooleanParameter().withValue(false)); + + return new CoreAction(this, + new UpdateAction().withId(ACTION_ALARM).withParameters(parameters)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreAction.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreAction.java new file mode 100644 index 0000000000000..d183cadb8ef2f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreAction.java @@ -0,0 +1,40 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; + +public class CoreAction +{ + private final CoreApplication app; + private final UpdateAction action; + + protected CoreAction(CoreApplication app, UpdateAction action) + { + this.app = app; + this.action = action; + } + + public CoreApplication getApp() + { + return app; + } + + public UpdateAction getAction() + { + return action; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreApplication.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreApplication.java new file mode 100644 index 0000000000000..c01f809519acd --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreApplication.java @@ -0,0 +1,31 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +public abstract class CoreApplication +{ + private final String packageName; + + public CoreApplication(String packageName) + { + this.packageName = packageName; + } + + public String getPackageName() + { + return packageName; + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreApps.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreApps.java new file mode 100644 index 0000000000000..1f38542da3cb8 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CoreApps.java @@ -0,0 +1,54 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +public class CoreApps +{ + private static final ClockApp CLOCK = new ClockApp(); + private static final CountdownApp COUNTDOWN = new CountdownApp(); + private static final RadioApp RADIO = new RadioApp(); + private static final StopwatchApp STOPWATCH = new StopwatchApp(); + private static final WeatherApp WEATHER = new WeatherApp(); + + public static ClockApp clock() + { + return CLOCK; + } + + public static CountdownApp countdown() + { + return COUNTDOWN; + } + + public static RadioApp radio() + { + return RADIO; + } + + public static StopwatchApp stopwatch() + { + return STOPWATCH; + } + + public static WeatherApp weather() + { + return WEATHER; + } + + // @formatter:off + private CoreApps() {} + // @formatter:on +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CountdownApp.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CountdownApp.java new file mode 100644 index 0000000000000..972df76d66766 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/CountdownApp.java @@ -0,0 +1,68 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +import java.util.SortedMap; +import java.util.TreeMap; + +import org.openhab.binding.lametrictime.api.local.model.BooleanParameter; +import org.openhab.binding.lametrictime.api.local.model.IntegerParameter; +import org.openhab.binding.lametrictime.api.local.model.Parameter; +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; + +public class CountdownApp extends CoreApplication +{ + private static final String NAME = "com.lametric.countdown"; + + private static final String ACTION_CONFIGURE = "countdown.configure"; + private static final String ACTION_PAUSE = "countdown.pause"; + private static final String ACTION_RESET = "countdown.reset"; + private static final String ACTION_START = "countdown.start"; + + private static final String PARAMETER_DURATION = "duration"; + private static final String PARAMETER_START_NOW = "start_now"; + + public CountdownApp() + { + super(NAME); + } + + public CoreAction configure(int duration, boolean startNow) + { + SortedMap parameters = new TreeMap<>(); + parameters.put(PARAMETER_DURATION, new IntegerParameter().withValue(duration)); + parameters.put(PARAMETER_START_NOW, new BooleanParameter().withValue(startNow)); + + return new CoreAction(this, + new UpdateAction().withId(ACTION_CONFIGURE) + .withParameters(parameters)); + } + + public CoreAction pause() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_PAUSE)); + } + + public CoreAction reset() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_RESET)); + } + + public CoreAction start() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_START)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/Icon.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/Icon.java new file mode 100644 index 0000000000000..c25f3f37c7e5b --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/Icon.java @@ -0,0 +1,21 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +public interface Icon extends ApiValue +{ + // marker interface +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/Icons.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/Icons.java new file mode 100644 index 0000000000000..df09f78fb79c7 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/Icons.java @@ -0,0 +1,90 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +import java.io.File; +import java.net.URI; +import java.nio.file.Path; + +import org.openhab.binding.lametrictime.api.impl.DataIcon; +import org.openhab.binding.lametrictime.api.impl.FileIcon; +import org.openhab.binding.lametrictime.api.impl.HTTPIcon; +import org.openhab.binding.lametrictime.api.impl.KeyIcon; + +public class Icons +{ + public static Icon key(String key) + { + return new KeyIcon(key); + } + + public static Icon http(String uri) + { + return http(URI.create(uri)); + } + + public static Icon http(URI uri) + { + return new HTTPIcon(uri); + } + + public static Icon path(Path path) + { + return new FileIcon(path); + } + + public static Icon file(File file) + { + return new FileIcon(file); + } + + public static Icon data(String mimeType, byte[] data) + { + return new DataIcon(mimeType, data); + } + + // @formatter:off + public static Icon dollar() { return key("i34"); } + public static Icon gmail() { return key("i43"); } + public static Icon confirm() { return key("i59"); } + public static Icon goOut() { return key("a68"); } + public static Icon dog() { return key("a76"); } + public static Icon clock() { return key("a82"); } + public static Icon smile() { return key("a87"); } + public static Icon lightning() { return key("i95"); } + public static Icon facebook() { return key("a128"); } + public static Icon home() { return key("i96"); } + public static Icon girl() { return key("a178"); } + public static Icon stop() { return key("i184"); } + public static Icon heart() { return key("a230"); } + public static Icon fade() { return key("a273"); } + public static Icon terminal() { return key("a315"); } + public static Icon usa() { return key("a413"); } + public static Icon switzerland() { return key("i469"); } + public static Icon attention() { return key("i555"); } + public static Icon theMatrix() { return key("a653"); } + public static Icon pizza() { return key("i1324"); } + public static Icon christmasTree() { return key("a1782"); } + public static Icon night() { return key("a2285"); } + public static Icon fireworks() { return key("a2867"); } + public static Icon beer() { return key("i3253"); } + public static Icon tetris() { return key("a3793"); } + public static Icon halloween() { return key("a4033"); } + public static Icon pacman() { return key("a4584"); } + + private Icons() {} + // @formatter:on +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/RadioApp.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/RadioApp.java new file mode 100644 index 0000000000000..41cac54803bfe --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/RadioApp.java @@ -0,0 +1,53 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; + +public class RadioApp extends CoreApplication +{ + private static final String NAME = "com.lametric.radio"; + + private static final String ACTION_NEXT = "radio.next"; + private static final String ACTION_PLAY = "radio.play"; + private static final String ACTION_PREV = "radio.prev"; + private static final String ACTION_STOP = "radio.stop"; + + public RadioApp() + { + super(NAME); + } + + public CoreAction next() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_NEXT)); + } + + public CoreAction play() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_PLAY)); + } + + public CoreAction previous() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_PREV)); + } + + public CoreAction stop() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_STOP)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/StopwatchApp.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/StopwatchApp.java new file mode 100644 index 0000000000000..2af8f4873046d --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/StopwatchApp.java @@ -0,0 +1,47 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; + +public class StopwatchApp extends CoreApplication +{ + private static final String NAME = "com.lametric.stopwatch"; + + private static final String ACTION_PAUSE = "stopwatch.pause"; + private static final String ACTION_RESET = "stopwatch.reset"; + private static final String ACTION_START = "stopwatch.start"; + + public StopwatchApp() + { + super(NAME); + } + + public CoreAction pause() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_PAUSE)); + } + + public CoreAction reset() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_RESET)); + } + + public CoreAction start() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_START)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/WeatherApp.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/WeatherApp.java new file mode 100644 index 0000000000000..8db4088fa8991 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/WeatherApp.java @@ -0,0 +1,35 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model; + +import org.openhab.binding.lametrictime.api.local.model.UpdateAction; + +public class WeatherApp extends CoreApplication +{ + private static final String NAME = "com.lametric.weather"; + + private static final String ACTION_FORECAST = "weather.forecast"; + + public WeatherApp() + { + super(NAME); + } + + public CoreAction forecast() + { + return new CoreAction(this, new UpdateAction().withId(ACTION_FORECAST)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/BrightnessMode.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/BrightnessMode.java new file mode 100644 index 0000000000000..be764da192339 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/BrightnessMode.java @@ -0,0 +1,48 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import org.openhab.binding.lametrictime.api.model.ApiValue; + +public enum BrightnessMode implements ApiValue +{ + AUTO, + MANUAL; + + @Override + public String toRaw() + { + return name().toLowerCase(); + } + + public static BrightnessMode toEnum(String raw) + { + if (raw == null) + { + return null; + } + + try + { + return valueOf(raw.toUpperCase()); + } + catch (IllegalArgumentException e) + { + // not a valid raw string + return null; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/DisplayType.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/DisplayType.java new file mode 100644 index 0000000000000..ada22e4ede4d3 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/DisplayType.java @@ -0,0 +1,50 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import org.openhab.binding.lametrictime.api.model.ApiValue; + +public enum DisplayType implements ApiValue +{ + MONOCHROME, + GRAYSCALE, + COLOR, + MIXED; + + @Override + public String toRaw() + { + return name().toLowerCase(); + } + + public static DisplayType toEnum(String raw) + { + if (raw == null) + { + return null; + } + + try + { + return valueOf(raw.toUpperCase()); + } + catch (IllegalArgumentException e) + { + // not a valid raw string + return null; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/IconType.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/IconType.java new file mode 100644 index 0000000000000..13f43accf1674 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/IconType.java @@ -0,0 +1,49 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import org.openhab.binding.lametrictime.api.model.ApiValue; + +public enum IconType implements ApiValue +{ + NONE, + INFO, + ALERT; + + @Override + public String toRaw() + { + return name().toLowerCase(); + } + + public static IconType toEnum(String raw) + { + if (raw == null) + { + return null; + } + + try + { + return valueOf(raw.toUpperCase()); + } + catch (IllegalArgumentException e) + { + // not a valid raw string + return null; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/IpMode.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/IpMode.java new file mode 100644 index 0000000000000..bdc3630f90df8 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/IpMode.java @@ -0,0 +1,48 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import org.openhab.binding.lametrictime.api.model.ApiValue; + +public enum IpMode implements ApiValue +{ + STATIC, + DHCP; + + @Override + public String toRaw() + { + return name().toLowerCase(); + } + + public static IpMode toEnum(String raw) + { + if (raw == null) + { + return null; + } + + try + { + return valueOf(raw.toUpperCase()); + } + catch (IllegalArgumentException e) + { + // not a valid raw string + return null; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/Priority.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/Priority.java new file mode 100644 index 0000000000000..bb9cfebbf62af --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/Priority.java @@ -0,0 +1,49 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import org.openhab.binding.lametrictime.api.model.ApiValue; + +public enum Priority implements ApiValue +{ + INFO, + WARNING, + CRITICAL; + + @Override + public String toRaw() + { + return name().toLowerCase(); + } + + public static Priority toEnum(String raw) + { + if (raw == null) + { + return null; + } + + try + { + return valueOf(raw.toUpperCase()); + } + catch (IllegalArgumentException e) + { + // not a valid raw string + return null; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/Sound.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/Sound.java new file mode 100644 index 0000000000000..a9c3ea1b52b60 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/Sound.java @@ -0,0 +1,119 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import org.openhab.binding.lametrictime.api.model.ApiValue; + +public enum Sound implements ApiValue +{ + BICYCLE(SoundCategory.NOTIFICATIONS), + CAR(SoundCategory.NOTIFICATIONS), + CASH(SoundCategory.NOTIFICATIONS), + CAT(SoundCategory.NOTIFICATIONS), + DOG(SoundCategory.NOTIFICATIONS), + DOG2(SoundCategory.NOTIFICATIONS), + ENERGY(SoundCategory.NOTIFICATIONS), + KNOCK_KNOCK(SoundCategory.NOTIFICATIONS, "knock-knock"), + LETTER_EMAIL(SoundCategory.NOTIFICATIONS), + LOSE1(SoundCategory.NOTIFICATIONS), + LOSE2(SoundCategory.NOTIFICATIONS), + NEGATIVE1(SoundCategory.NOTIFICATIONS), + NEGATIVE2(SoundCategory.NOTIFICATIONS), + NEGATIVE3(SoundCategory.NOTIFICATIONS), + NEGATIVE4(SoundCategory.NOTIFICATIONS), + NEGATIVE5(SoundCategory.NOTIFICATIONS), + NOTIFICATION(SoundCategory.NOTIFICATIONS), + NOTIFICATION2(SoundCategory.NOTIFICATIONS), + NOTIFICATION3(SoundCategory.NOTIFICATIONS), + NOTIFICATION4(SoundCategory.NOTIFICATIONS), + OPEN_DOOR(SoundCategory.NOTIFICATIONS), + POSITIVE1(SoundCategory.NOTIFICATIONS), + POSITIVE2(SoundCategory.NOTIFICATIONS), + POSITIVE3(SoundCategory.NOTIFICATIONS), + POSITIVE4(SoundCategory.NOTIFICATIONS), + POSITIVE5(SoundCategory.NOTIFICATIONS), + POSITIVE6(SoundCategory.NOTIFICATIONS), + STATISTIC(SoundCategory.NOTIFICATIONS), + THUNDER(SoundCategory.NOTIFICATIONS), + WATER1(SoundCategory.NOTIFICATIONS), + WATER2(SoundCategory.NOTIFICATIONS), + WIN(SoundCategory.NOTIFICATIONS), + WIN2(SoundCategory.NOTIFICATIONS), + WIND(SoundCategory.NOTIFICATIONS), + WIND_SHORT(SoundCategory.NOTIFICATIONS), + + ALARM1(SoundCategory.ALARMS), + ALARM2(SoundCategory.ALARMS), + ALARM3(SoundCategory.ALARMS), + ALARM4(SoundCategory.ALARMS), + ALARM5(SoundCategory.ALARMS), + ALARM6(SoundCategory.ALARMS), + ALARM7(SoundCategory.ALARMS), + ALARM8(SoundCategory.ALARMS), + ALARM9(SoundCategory.ALARMS), + ALARM10(SoundCategory.ALARMS), + ALARM11(SoundCategory.ALARMS), + ALARM12(SoundCategory.ALARMS), + ALARM13(SoundCategory.ALARMS); + + private final SoundCategory category; + private final String rawValue; + + private Sound(SoundCategory category) + { + this(category, null); + } + + private Sound(SoundCategory category, String rawValue) + { + this.category = category; + this.rawValue = rawValue; + } + + public SoundCategory getCategory() + { + return category; + } + + @Override + public String toRaw() + { + return rawValue != null ? rawValue : name().toLowerCase(); + } + + public static Sound toEnum(String raw) + { + if (raw == null) + { + return null; + } + + if (KNOCK_KNOCK.rawValue.equals(raw)) + { + return KNOCK_KNOCK; + } + + try + { + return valueOf(raw.toUpperCase()); + } + catch (IllegalArgumentException e) + { + // not a valid raw string + return null; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/SoundCategory.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/SoundCategory.java new file mode 100644 index 0000000000000..d1684ed419bad --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/SoundCategory.java @@ -0,0 +1,48 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import org.openhab.binding.lametrictime.api.model.ApiValue; + +public enum SoundCategory implements ApiValue +{ + NOTIFICATIONS, + ALARMS; + + @Override + public String toRaw() + { + return name().toLowerCase(); + } + + public static SoundCategory toEnum(String raw) + { + if (raw == null) + { + return null; + } + + try + { + return valueOf(raw.toUpperCase()); + } + catch (IllegalArgumentException e) + { + // not a valid raw string + return null; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/WifiEncryption.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/WifiEncryption.java new file mode 100644 index 0000000000000..e28a6763fde20 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/java/org/openhab/binding/lametrictime/api/model/enums/WifiEncryption.java @@ -0,0 +1,50 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import org.openhab.binding.lametrictime.api.model.ApiValue; + +public enum WifiEncryption implements ApiValue +{ + OPEN, + WEP, + WPA, + WPA2; + + @Override + public String toRaw() + { + return name(); + } + + public static WifiEncryption toEnum(String raw) + { + if (raw == null) + { + return null; + } + + try + { + return valueOf(raw); + } + catch (IllegalArgumentException e) + { + // not a valid raw string + return null; + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/AllIntegrationTestsSuite.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/AllIntegrationTestsSuite.java new file mode 100644 index 0000000000000..6c5ae8e7ce01a --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/AllIntegrationTestsSuite.java @@ -0,0 +1,28 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api; + +import org.junit.runner.RunWith; + +import com.googlecode.junittoolbox.SuiteClasses; +import com.googlecode.junittoolbox.WildcardPatternSuite; + +@RunWith(WildcardPatternSuite.class) +@SuiteClasses({ "**/*IT.class" }) +public class AllIntegrationTestsSuite +{ + // Execute all integration tests +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/AllUnitTestsSuite.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/AllUnitTestsSuite.java new file mode 100644 index 0000000000000..d85021cbf5716 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/AllUnitTestsSuite.java @@ -0,0 +1,27 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api; + +import org.junit.runner.RunWith; + +import com.googlecode.junittoolbox.ParallelSuite; +import com.googlecode.junittoolbox.SuiteClasses; + +@RunWith(ParallelSuite.class) +@SuiteClasses({ "**/*Test.class" }) +public class AllUnitTestsSuite { + // Execute all unit tests +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/impl/FileIconTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/impl/FileIconTest.java new file mode 100644 index 0000000000000..652ab975522e6 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/impl/FileIconTest.java @@ -0,0 +1,56 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.impl; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +public class FileIconTest extends AbstractTest +{ + @Test + public void testLocalPathGif() + { + FileIcon icon = new FileIcon(getTestDataPath("smile.gif")); + assertEquals("data:image/gif;base64,R0lGODlhCAAIAPEAAPz+BPz+/AAAAAAAACH5BAkKAAIAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAACAAIAAACEZSAYJfIElREIdaGs3PPNFMAACH5BAkKAAIALAAAAAAIAAgAAAIRlIBgl8gSVEQh1oazU4szJxQAIfkECTIAAgAsAAAAAAgACAAAAhKUgGCXyBJURCHWhlU7fCmzCQUAIfkECRQAAgAsAAAAAAgACAAAAhGUgGCXyBIaClFa1Y5eymRRAAAh+QQJMgACACwAAAAACAAIAAACEpSAYJfIElREIdaGVTt8KbMJBQA7", + icon.toRaw()); + } + + @Test + public void testLocalPathPng() + { + FileIcon icon = new FileIcon(getTestDataPath("info.png")); + assertEquals("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAL0lEQVQYlWN0NPv3nwEPYIEx9p1kRJFwMofoY0IXQGczMRAAVFSA7EhkNiMhbwIAA/sN+bH1CpgAAAAASUVORK5CYII=", + icon.toRaw()); + } + + @Test + public void testLocalFileGif() + { + FileIcon icon = new FileIcon(getTestDataFile("smile.gif")); + assertEquals("data:image/gif;base64,R0lGODlhCAAIAPEAAPz+BPz+/AAAAAAAACH5BAkKAAIAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAACAAIAAACEZSAYJfIElREIdaGs3PPNFMAACH5BAkKAAIALAAAAAAIAAgAAAIRlIBgl8gSVEQh1oazU4szJxQAIfkECTIAAgAsAAAAAAgACAAAAhKUgGCXyBJURCHWhlU7fCmzCQUAIfkECRQAAgAsAAAAAAgACAAAAhGUgGCXyBIaClFa1Y5eymRRAAAh+QQJMgACACwAAAAACAAIAAACEpSAYJfIElREIdaGVTt8KbMJBQA7", + icon.toRaw()); + } + + @Test + public void testLocalFilePng() + { + FileIcon icon = new FileIcon(getTestDataFile("info.png")); + assertEquals("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAL0lEQVQYlWN0NPv3nwEPYIEx9p1kRJFwMofoY0IXQGczMRAAVFSA7EhkNiMhbwIAA/sN+bH1CpgAAAAASUVORK5CYII=", + icon.toRaw()); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/impl/LaMetricTimeLocalImplIT.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/impl/LaMetricTimeLocalImplIT.java new file mode 100644 index 0000000000000..5fb6b5acf5e3d --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/impl/LaMetricTimeLocalImplIT.java @@ -0,0 +1,264 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.impl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Properties; + +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.local.ApplicationActivationException; +import org.openhab.binding.lametrictime.api.local.ApplicationNotFoundException; +import org.openhab.binding.lametrictime.api.local.LocalConfiguration; +import org.openhab.binding.lametrictime.api.local.NotificationCreationException; +import org.openhab.binding.lametrictime.api.local.NotificationNotFoundException; +import org.openhab.binding.lametrictime.api.local.UpdateException; +import org.openhab.binding.lametrictime.api.local.model.Audio; +import org.openhab.binding.lametrictime.api.local.model.Bluetooth; +import org.openhab.binding.lametrictime.api.local.model.Display; +import org.openhab.binding.lametrictime.api.local.model.Frame; +import org.openhab.binding.lametrictime.api.local.model.GoalData; +import org.openhab.binding.lametrictime.api.local.model.Notification; +import org.openhab.binding.lametrictime.api.local.model.NotificationModel; +import org.openhab.binding.lametrictime.api.local.model.Sound; +import org.openhab.binding.lametrictime.api.model.CoreApps; +import org.openhab.binding.lametrictime.api.model.enums.BrightnessMode; +import org.openhab.binding.lametrictime.api.model.enums.Priority; +import org.openhab.binding.lametrictime.api.model.enums.SoundCategory; +import org.openhab.binding.lametrictime.api.test.TestUtil; + +/** + *

+ * This test is excluded from the normal battery of tests because it is not a + * unit test, but rather a live test against an actual device. The purpose of + * this test is to make sure that after a firmware upgrade, the device still + * responds in a backwards compatible way. + *

+ *
+ *

+ * To run this test, first create a file called 'device.properties' in the + * matching package as this class under 'src/test/resources' with two + * properties: 'host' and 'apiKey'. After putting the configuration in place, + * either execute the test via your IDE or run 'mvn -DskipITs=false + * integration-test'. + *

+ */ +@Ignore +public class LaMetricTimeLocalImplIT { + private static final String PROP_HOST = "host"; + private static final String PROP_API_KEY = "apiKey"; + + private static LaMetricTimeLocalImpl local; + + @BeforeClass + public static void setup() throws IOException { + File file = TestUtil.getTestDataPath(LaMetricTimeLocalImplIT.class, "device.properties").toFile(); + if (!file.exists()) { + throw new IllegalStateException("Device configuration properties missing at " + file.getAbsolutePath()); + } + + try (InputStream in = new FileInputStream(file)) { + Properties properties = new Properties(); + properties.load(in); + + if (!properties.containsKey(PROP_HOST)) { + throw new IllegalStateException("Device configuration property " + PROP_HOST + " was not found"); + } + + if (!properties.containsKey(PROP_API_KEY)) { + throw new IllegalStateException("Device configuration property " + PROP_API_KEY + " was not found"); + } + + LocalConfiguration config = new LocalConfiguration().withHost(properties.getProperty(PROP_HOST)) + .withApiKey(properties.getProperty(PROP_API_KEY)).withLogging(true); + local = new LaMetricTimeLocalImpl(config); + } + } + + @Test + public void testGetApi() { + local.getApi(); + } + + @Test + public void testGetDevice() { + local.getDevice(); + } + + @Test + public void testCreateAndGetNotification() throws NotificationCreationException, NotificationNotFoundException { + String id = local.createNotification(buildSimpleNotification(1)); + local.getCurrentNotification(); + local.getNotification(id); + } + + @Test + public void testCreateGoalNotification() throws NotificationCreationException, NotificationNotFoundException { + local.createNotification(buildGoalNotification(1)); + } + + @Test + public void testCreateChartNotification() throws NotificationCreationException, NotificationNotFoundException { + local.createNotification(buildChartNotification(1)); + } + + @Test + public void testGetNotifications() { + local.getNotifications(); + } + + @Test(expected = NotificationNotFoundException.class) + public void testGetInvalidNotification() throws NotificationNotFoundException { + local.getNotification("invalid"); + } + + @Test + public void testCreateAndDeleteNotification() throws NotificationCreationException, NotificationNotFoundException { + String id = local.createNotification(buildSimpleNotification(0)); + local.deleteNotification(id); + } + + @Test + public void testGetDisplay() { + local.getDisplay(); + } + + @Test + public void testUpdateDisplay() throws UpdateException { + local.updateDisplay(new Display().withBrightnessMode(BrightnessMode.AUTO.toRaw())); + } + + @Test + public void testGetAudio() { + local.getAudio(); + } + + @Test + public void testUpdateAudio() throws UpdateException { + local.updateAudio(new Audio().withVolume(25)); + } + + @Test + public void testGetBluetooth() { + local.getBluetooth(); + } + + @Test + public void testUpdateBluetooth() throws UpdateException { + local.updateBluetooth(new Bluetooth().withActive(false)); + } + + @Test + public void testGetWifi() { + local.getWifi(); + } + + @Test + public void testGetApplications() { + local.getApplications(); + } + + @Test + public void testGetClockApplication() throws ApplicationNotFoundException { + local.getApplication(CoreApps.clock().getPackageName()); + } + + @Test + public void testGetCountdownApplication() throws ApplicationNotFoundException { + local.getApplication(CoreApps.countdown().getPackageName()); + } + + @Test + public void testGetRadioApplication() throws ApplicationNotFoundException { + local.getApplication(CoreApps.radio().getPackageName()); + } + + @Test + public void testGetStopwatchApplication() throws ApplicationNotFoundException { + local.getApplication(CoreApps.stopwatch().getPackageName()); + } + + @Test + public void testGetWeatherApplication() throws ApplicationNotFoundException { + local.getApplication(CoreApps.weather().getPackageName()); + } + + @Test(expected = ApplicationNotFoundException.class) + public void testGetInvalidApplication() throws ApplicationNotFoundException { + local.getApplication("invalid"); + } + + @Test + public void testActivatePreviousApplication() { + local.activatePreviousApplication(); + } + + @Test + public void testActivateNextApplication() { + local.activateNextApplication(); + } + + @Test + public void testActivateApplication() throws ApplicationActivationException, ApplicationNotFoundException { + // delete any notifications on the device or else the activate fails + local.getNotifications().stream().forEach(n -> { + try { + local.deleteNotification(n.getId()); + } catch (Exception e) { + e.printStackTrace(); + } + }); + + local.activateApplication(CoreApps.clock().getPackageName(), + local.getApplication(CoreApps.clock().getPackageName()).getWidgets().firstKey()); + } + + @Test + public void testDoAction() throws ApplicationActionException, ApplicationNotFoundException { + local.doAction(CoreApps.weather().getPackageName(), + local.getApplication(CoreApps.weather().getPackageName()).getWidgets().firstKey(), + CoreApps.weather().forecast().getAction()); + } + + private Notification buildSimpleNotification(int cycles) { + return new Notification().withPriority(Priority.CRITICAL.toRaw()).withModel(new NotificationModel() + .withCycles(cycles) + .withSound(new Sound().withCategory(SoundCategory.NOTIFICATIONS.toRaw()) + .withId(org.openhab.binding.lametrictime.api.model.enums.Sound.CAT.toRaw())) + .withFrames(Arrays.asList(new Frame().withText("CAT!").withIcon( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAUklEQVQYlWNUVFBgYGBgYBC98uE/AxJ4rSPAyMDAwMCETRJZjAnGgOlAZote+fCfCV0nOmA0+yKAYTwygJuAzQoGBgYGRkUFBQZ0dyDzGQl5EwCTESNpFb6zEwAAAABJRU5ErkJggg==")))); + } + + private Notification buildGoalNotification(int cycles) { + return new Notification().withPriority(Priority.CRITICAL.toRaw()) + .withModel(new NotificationModel().withCycles(cycles).withFrames(Arrays.asList(new Frame() + .withGoalData(new GoalData().withStart(0).withCurrent(50).withEnd(100).withUnit("%")).withIcon( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAUklEQVQYlWNUVFBgYGBgYBC98uE/AxJ4rSPAyMDAwMCETRJZjAnGgOlAZote+fCfCV0nOmA0+yKAYTwygJuAzQoGBgYGRkUFBQZ0dyDzGQl5EwCTESNpFb6zEwAAAABJRU5ErkJggg==")))); + } + + private Notification buildChartNotification(int cycles) { + return new Notification().withPriority(Priority.CRITICAL.toRaw()).withModel(new NotificationModel() + .withCycles(cycles) + .withFrames(Arrays.asList(new Frame().withChartData(Arrays.asList(1, 2, 3, 4, 5, 6, 7)).withIcon( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAUklEQVQYlWNUVFBgYGBgYBC98uE/AxJ4rSPAyMDAwMCETRJZjAnGgOlAZote+fCfCV0nOmA0+yKAYTwygJuAzQoGBgYGRkUFBQZ0dyDzGQl5EwCTESNpFb6zEwAAAABJRU5ErkJggg==")))); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/ActionTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/ActionTest.java new file mode 100644 index 0000000000000..aed37d22fc5d1 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/ActionTest.java @@ -0,0 +1,68 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.*; + +import java.io.FileReader; +import java.util.Iterator; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class ActionTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + @SuppressWarnings("serial") + public void testSerialize() throws Exception + { + // @formatter:off + Action action = new Action().withParameters(new TreeMap(){{put("enabled", new BooleanParameter()); + put("time", new StringParameter());}}); + // @formatter:on + assertEquals(readJson("action.json"), gson.toJson(action)); + } + + @Test + public void testDeserialize() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("action.json"))) + { + Action action = gson.fromJson(reader, Action.class); + SortedMap parameters = action.getParameters(); + assertNotNull(parameters); + assertEquals(2, parameters.size()); + + Iterator parametersIter = parameters.keySet().iterator(); + assertEquals("enabled", parametersIter.next()); + assertEquals("time", parametersIter.next()); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/ApplicationTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/ApplicationTest.java new file mode 100644 index 0000000000000..f208c962fbde1 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/ApplicationTest.java @@ -0,0 +1,112 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.*; + +import java.io.FileReader; +import java.util.Iterator; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class ApplicationTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + @SuppressWarnings("serial") + public void testSerializeAllFields() throws Exception + { + Application app = new Application().withPackageName("com.lametric.radio") + .withVendor("LaMetric") + .withVersion("1.0.10") + .withVersionCode("22") + // @formatter:off + .withWidgets(new TreeMap(){{put("589ed1b3fcdaa5180bf4848e55ba8061", new Widget());}}) + .withActions(new TreeMap(){{put("radio.next", new Action()); + put("radio.play", new Action()); + put("radio.prev", new Action()); + put("radio.stop", new Action());}}); + // @formatter:on + assertEquals(readJson("application-all.json"), gson.toJson(app)); + } + + @Test + public void testSerializeNullLists() throws Exception + { + Application app = new Application().withPackageName("com.lametric.radio") + .withVendor("LaMetric") + .withVersion("1.0.10") + .withVersionCode("22"); + assertEquals(readJson("application-null-maps.json"), gson.toJson(app)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("application-all.json"))) + { + Application app = gson.fromJson(reader, Application.class); + assertEquals("com.lametric.radio", app.getPackageName()); + assertEquals("LaMetric", app.getVendor()); + assertEquals("1.0.10", app.getVersion()); + assertEquals("22", app.getVersionCode()); + + SortedMap widgets = app.getWidgets(); + assertNotNull(widgets); + assertEquals(1, widgets.size()); + assertEquals("589ed1b3fcdaa5180bf4848e55ba8061", widgets.keySet().iterator().next()); + + SortedMap actions = app.getActions(); + assertNotNull(actions); + assertEquals(4, actions.size()); + + Iterator actionsIter = actions.keySet().iterator(); + assertEquals("radio.next", actionsIter.next()); + assertEquals("radio.play", actionsIter.next()); + assertEquals("radio.prev", actionsIter.next()); + assertEquals("radio.stop", actionsIter.next()); + } + } + + @Test + public void testDeserializeNullLists() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("application-null-maps.json"))) + { + Application app = gson.fromJson(reader, Application.class); + assertEquals("com.lametric.radio", app.getPackageName()); + assertEquals("LaMetric", app.getVendor()); + assertEquals("1.0.10", app.getVersion()); + assertEquals("22", app.getVersionCode()); + assertNull(app.getWidgets()); + assertNull(app.getActions()); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/AudioTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/AudioTest.java new file mode 100644 index 0000000000000..f0ed9eebe444a --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/AudioTest.java @@ -0,0 +1,55 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class AudioTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + Audio audio = new Audio().withVolume(42); + assertEquals(readJson("audio.json"), gson.toJson(audio)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("audio.json"))) + { + Audio audio = gson.fromJson(reader, Audio.class); + assertEquals(Integer.valueOf(42), audio.getVolume()); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/BluetoothTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/BluetoothTest.java new file mode 100644 index 0000000000000..37d9997d9b38b --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/BluetoothTest.java @@ -0,0 +1,80 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class BluetoothTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + Bluetooth bluetooth = new Bluetooth().withActive(false) + .withAvailable(true) + .withDiscoverable(false) + .withMac("AA:AA:AA:AA:AA:AA") + .withName("LM9999") + .withPairable(true); + assertEquals(readJson("bluetooth-mac-address.json"), gson.toJson(bluetooth)); + } + + @Test + public void testDeserializeMac() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("bluetooth-mac.json"))) + { + Bluetooth bluetooth = gson.fromJson(reader, Bluetooth.class); + assertEquals(false, bluetooth.isActive()); + assertEquals(true, bluetooth.isAvailable()); + assertEquals(false, bluetooth.isDiscoverable()); + assertEquals("AA:AA:AA:AA:AA:AA", bluetooth.getMac()); + assertEquals("LM9999", bluetooth.getName()); + assertEquals(true, bluetooth.isPairable()); + } + } + + @Test + public void testDeserializeAddress() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("bluetooth-address.json"))) + { + Bluetooth bluetooth = gson.fromJson(reader, Bluetooth.class); + assertEquals(false, bluetooth.isActive()); + assertEquals(true, bluetooth.isAvailable()); + assertEquals(false, bluetooth.isDiscoverable()); + assertEquals("AA:AA:AA:AA:AA:AA", bluetooth.getMac()); + assertEquals("LM9999", bluetooth.getName()); + assertEquals(true, bluetooth.isPairable()); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/FrameTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/FrameTest.java new file mode 100644 index 0000000000000..8e983a9192bcf --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/FrameTest.java @@ -0,0 +1,94 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; +import java.util.Arrays; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class FrameTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeSimple() throws Exception + { + Frame frame = new Frame().withIcon("i87").withText("Hello world!"); + assertEquals(readJson("frame-simple.json"), gson.toJson(frame)); + } + + @Test + public void testSerializeGoal() throws Exception + { + Frame frame = new Frame().withIcon("i120").withGoalData(new GoalData()); + assertEquals(readJson("frame-goal.json"), gson.toJson(frame)); + } + + @Test + public void testSerializeChart() throws Exception + { + Frame frame = new Frame().withChartData(Arrays.asList(1, 2, 3, 4, 5, 6, 7)); + assertEquals(readJson("frame-chart.json"), gson.toJson(frame)); + } + + @Test + public void testDeserializeSimple() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("frame-simple.json"))) + { + Frame frame = gson.fromJson(reader, Frame.class); + assertEquals("i87", frame.getIcon()); + assertEquals("Hello world!", frame.getText()); + assertEquals(null, frame.getGoalData()); + assertEquals(null, frame.getChartData()); + } + } + + @Test + public void testDeserializeGoal() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("frame-goal.json"))) + { + Frame frame = gson.fromJson(reader, Frame.class); + assertEquals("i120", frame.getIcon()); + assertEquals(new GoalData(), frame.getGoalData()); + } + } + + @Test + public void testDeserializeChart() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("frame-chart.json"))) + { + Frame frame = gson.fromJson(reader, Frame.class); + assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6, 7), frame.getChartData()); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/GoalDataTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/GoalDataTest.java new file mode 100644 index 0000000000000..7c179b21364d6 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/GoalDataTest.java @@ -0,0 +1,58 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class GoalDataTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeSimple() throws Exception + { + GoalData goalData = new GoalData().withStart(0).withEnd(100).withCurrent(50).withUnit("%"); + assertEquals(readJson("goal-data.json"), gson.toJson(goalData)); + } + + @Test + public void testDeserializeSimple() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("goal-data.json"))) + { + GoalData goalData = gson.fromJson(reader, GoalData.class); + assertEquals(Integer.valueOf(0), goalData.getStart()); + assertEquals(Integer.valueOf(100), goalData.getEnd()); + assertEquals(Integer.valueOf(50), goalData.getCurrent()); + assertEquals("%", goalData.getUnit()); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/UpdateActionTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/UpdateActionTest.java new file mode 100644 index 0000000000000..ae9997257bd0f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/UpdateActionTest.java @@ -0,0 +1,59 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; +import java.util.TreeMap; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class UpdateActionTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + @SuppressWarnings("serial") + public void testSerialize() throws Exception + { + UpdateAction action = new UpdateAction().withId("countdown.configure") + // @formatter:off + .withParameters(new TreeMap(){{put("duration", new IntegerParameter().withValue(30));}}); + // @formatter:on + assertEquals(readJson("update-action.json"), gson.toJson(action)); + } + + @Test(expected = UnsupportedOperationException.class) + public void testDeserialize() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("update-action.json"))) + { + gson.fromJson(reader, UpdateAction.class); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/WidgetTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/WidgetTest.java new file mode 100644 index 0000000000000..b6ff3b03e85f8 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/WidgetTest.java @@ -0,0 +1,73 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; +import java.util.HashMap; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; +import com.google.gson.JsonPrimitive; + +public class WidgetTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + @SuppressWarnings("serial") + public void testSerialize() throws Exception + { + Widget widget = new Widget().withPackageName("com.lametric.radio") + .withIndex(Integer.valueOf(-1)) + .withSettings(new HashMap() + { + { + put("_title", new JsonPrimitive("Radio")); + } + }); + assertEquals(readJson("widget.json"), gson.toJson(widget)); + } + + @Test + @SuppressWarnings("serial") + public void testDeserialize() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("widget.json"))) + { + Widget widget = gson.fromJson(reader, Widget.class); + assertEquals("com.lametric.radio", widget.getPackageName()); + assertEquals(Integer.valueOf(-1), widget.getIndex()); + assertEquals(new HashMap() + { + { + put("_title", new JsonPrimitive("Radio")); + } + }, widget.getSettings()); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/WidgetUpdatesTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/WidgetUpdatesTest.java new file mode 100644 index 0000000000000..ad43020e7a7b5 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/local/model/WidgetUpdatesTest.java @@ -0,0 +1,62 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.local.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; +import java.util.Arrays; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.openhab.binding.lametrictime.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class WidgetUpdatesTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerialize() throws Exception + { + WidgetUpdates widgetUpdates = new WidgetUpdates().withFrames(Arrays.asList(new Frame().withIcon("i120") + .withText("12°") + .withIndex(0))); + + assertEquals(readJson("widget-updates.json"), gson.toJson(widgetUpdates)); + } + + @Test + public void testDeserialize() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("widget-updates.json"))) + { + WidgetUpdates widgetUpdates = gson.fromJson(reader, WidgetUpdates.class); + assertEquals("i120", widgetUpdates.getFrames().get(0).getIcon()); + assertEquals("12°", widgetUpdates.getFrames().get(0).getText()); + assertEquals(null, widgetUpdates.getFrames().get(0).getGoalData()); + assertEquals(null, widgetUpdates.getFrames().get(0).getChartData()); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/BrightnessModeTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/BrightnessModeTest.java new file mode 100644 index 0000000000000..b5144e2e563fa --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/BrightnessModeTest.java @@ -0,0 +1,46 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.openhab.binding.lametrictime.api.model.enums.BrightnessMode; + +public class BrightnessModeTest +{ + @Test + public void testConversion() + { + for (BrightnessMode value : BrightnessMode.values()) + { + assertEquals(value, BrightnessMode.toEnum(value.toRaw())); + } + } + + @Test + public void testInvalidRawValue() + { + assertNull(BrightnessMode.toEnum("invalid raw value")); + } + + @Test + public void testNullRawValue() + { + assertNull(BrightnessMode.toEnum(null)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/DisplayTypeTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/DisplayTypeTest.java new file mode 100644 index 0000000000000..60c5acb797e97 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/DisplayTypeTest.java @@ -0,0 +1,46 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.openhab.binding.lametrictime.api.model.enums.DisplayType; + +public class DisplayTypeTest +{ + @Test + public void testConversion() + { + for (DisplayType value : DisplayType.values()) + { + assertEquals(value, DisplayType.toEnum(value.toRaw())); + } + } + + @Test + public void testInvalidRawValue() + { + assertNull(DisplayType.toEnum("invalid raw value")); + } + + @Test + public void testNullRawValue() + { + assertNull(DisplayType.toEnum(null)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/IconTypeTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/IconTypeTest.java new file mode 100644 index 0000000000000..64673e10de55a --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/IconTypeTest.java @@ -0,0 +1,46 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.openhab.binding.lametrictime.api.model.enums.IconType; + +public class IconTypeTest +{ + @Test + public void testConversion() + { + for (IconType value : IconType.values()) + { + assertEquals(value, IconType.toEnum(value.toRaw())); + } + } + + @Test + public void testInvalidRawValue() + { + assertNull(IconType.toEnum("invalid raw value")); + } + + @Test + public void testNullRawValue() + { + assertNull(IconType.toEnum(null)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/IpModeTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/IpModeTest.java new file mode 100644 index 0000000000000..0eb47d886b630 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/IpModeTest.java @@ -0,0 +1,45 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +public class IpModeTest +{ + @Test + public void testConversion() + { + for (IpMode value : IpMode.values()) + { + assertEquals(value, IpMode.toEnum(value.toRaw())); + } + } + + @Test + public void testInvalidRawValue() + { + assertNull(IpMode.toEnum("invalid raw value")); + } + + @Test + public void testNullRawValue() + { + assertNull(IpMode.toEnum(null)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/PriorityTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/PriorityTest.java new file mode 100644 index 0000000000000..23cea5d79bd98 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/PriorityTest.java @@ -0,0 +1,46 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.openhab.binding.lametrictime.api.model.enums.Priority; + +public class PriorityTest +{ + @Test + public void testConversion() + { + for (Priority value : Priority.values()) + { + assertEquals(value, Priority.toEnum(value.toRaw())); + } + } + + @Test + public void testInvalidRawValue() + { + assertNull(Priority.toEnum("invalid raw value")); + } + + @Test + public void testNullRawValue() + { + assertNull(Priority.toEnum(null)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/SoundCategoryTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/SoundCategoryTest.java new file mode 100644 index 0000000000000..6e0eb919776ff --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/SoundCategoryTest.java @@ -0,0 +1,46 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.openhab.binding.lametrictime.api.model.enums.SoundCategory; + +public class SoundCategoryTest +{ + @Test + public void testConversion() + { + for (SoundCategory value : SoundCategory.values()) + { + assertEquals(value, SoundCategory.toEnum(value.toRaw())); + } + } + + @Test + public void testInvalidRawValue() + { + assertNull(SoundCategory.toEnum("invalid raw value")); + } + + @Test + public void testNullRawValue() + { + assertNull(SoundCategory.toEnum(null)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/SoundTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/SoundTest.java new file mode 100644 index 0000000000000..35ae61c1ff0cc --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/SoundTest.java @@ -0,0 +1,46 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.openhab.binding.lametrictime.api.model.enums.Sound; + +public class SoundTest +{ + @Test + public void testConversion() + { + for (Sound value : Sound.values()) + { + assertEquals(value, Sound.toEnum(value.toRaw())); + } + } + + @Test + public void testInvalidRawValue() + { + assertNull(Sound.toEnum("invalid raw value")); + } + + @Test + public void testNullRawValue() + { + assertNull(Sound.toEnum(null)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/WifiEncryptionTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/WifiEncryptionTest.java new file mode 100644 index 0000000000000..4ead807b2b8c0 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/model/enums/WifiEncryptionTest.java @@ -0,0 +1,45 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.model.enums; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +public class WifiEncryptionTest +{ + @Test + public void testConversion() + { + for (WifiEncryption value : WifiEncryption.values()) + { + assertEquals(value, WifiEncryption.toEnum(value.toRaw())); + } + } + + @Test + public void testInvalidRawValue() + { + assertNull(WifiEncryption.toEnum("invalid raw value")); + } + + @Test + public void testNullRawValue() + { + assertNull(WifiEncryption.toEnum(null)); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/test/AbstractTest.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/test/AbstractTest.java new file mode 100644 index 0000000000000..cbb516b38f576 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/test/AbstractTest.java @@ -0,0 +1,39 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public abstract class AbstractTest +{ + protected File getTestDataFile(String name) + { + return getTestDataPath(name).toFile(); + } + + protected Path getTestDataPath(String name) + { + return TestUtil.getTestDataPath(this.getClass(), name); + } + + protected String readJson(String jsonFileName) throws IOException + { + return new String(Files.readAllBytes(getTestDataPath(jsonFileName))); + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/test/TestUtil.java b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/test/TestUtil.java new file mode 100644 index 0000000000000..1862e62a577ee --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/3rdparty/test/org/openhab/binding/lametrictime/api/test/TestUtil.java @@ -0,0 +1,42 @@ +/** + * Copyright 2017-2018 Gregory Moyer and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.lametrictime.api.test; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class TestUtil +{ + private static final String RESOURCES_PATH = "src/test/resources/"; + + public static Path getTestDataPath(Class clazz, String name) + { + String packageName = clazz.getPackage().getName(); + + List paths = new ArrayList<>(); + paths.addAll(Arrays.asList(packageName.split("\\."))); + paths.add(name); + + return Paths.get(RESOURCES_PATH, paths.toArray(new String[paths.size()])); + } + + // @formatter:off + private TestUtil() {} + // @formatter:on +} diff --git a/bundles/org.openhab.binding.lametrictime/src/main/feature/feature.xml b/bundles/org.openhab.binding.lametrictime/src/main/feature/feature.xml index d6f4b6aa4f2aa..7489e8731120c 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.lametrictime/src/main/feature/feature.xml @@ -1,11 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:com.eclipsesource.jaxrs/provider-gson/2.3 - mvn:org.openhab.addons.bundles/org.openhab.binding.lametrictime/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.lametrictime/${project.version} + diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/GsonProvider.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/GsonProvider.java new file mode 100644 index 0000000000000..1196adfc0c8b5 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/GsonProvider.java @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.lametrictime.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; + +import org.openhab.binding.lametrictime.api.common.impl.GsonGenerator; +import org.osgi.service.component.annotations.Component; + +import com.google.gson.Gson; + +/** + * JSON reader/writer for Jersey using GSON. + * + * @author Simon Kaufmann - Initial contribution + * + * @param + */ +@Provider +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +@Component(immediate = true) +public class GsonProvider implements MessageBodyReader, MessageBodyWriter { + + private final Gson gson; + + public GsonProvider() { + gson = GsonGenerator.create(); + } + + @Override + public long getSize(T t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return -1; + } + + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return true; + } + + @Override + public void writeTo(T object, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { + try (OutputStream stream = entityStream) { + entityStream.write(gson.toJson(object).getBytes(StandardCharsets.UTF_8)); + entityStream.flush(); + } + } + + @Override + public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return true; + } + + @Override + public T readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, InputStream entityStream) + throws IOException, WebApplicationException { + try (InputStreamReader reader = new InputStreamReader(entityStream, StandardCharsets.UTF_8)) { + return gson.fromJson(reader, type); + } + } +} diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/LaMetricTimeHandlerFactory.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/LaMetricTimeHandlerFactory.java index d704fe0cce370..06c1467db7dc1 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/LaMetricTimeHandlerFactory.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/LaMetricTimeHandlerFactory.java @@ -22,6 +22,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.ws.rs.client.ClientBuilder; + import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; @@ -40,6 +42,7 @@ import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,10 +59,26 @@ public class LaMetricTimeHandlerFactory extends BaseThingHandlerFactory { Stream.of(THING_TYPE_DEVICE, THING_TYPE_CLOCK_APP, THING_TYPE_COUNTDOWN_APP, THING_TYPE_RADIO_APP, THING_TYPE_STOPWATCH_APP, THING_TYPE_WEATHER_APP).collect(Collectors.toSet())); + // TODO: Those constants are Jersey specific - once we move away from Jersey, + // this can be removed and the client builder creation simplified. + public static final String READ_TIMEOUT_JERSEY = "jersey.config.client.readTimeout"; + public static final String CONNECT_TIMEOUT_JERSEY = "jersey.config.client.connectTimeout"; + + public static final String READ_TIMEOUT = "http.receive.timeout"; + public static final String CONNECT_TIMEOUT = "http.connection.timeout"; + + private static final int EVENT_STREAM_CONNECT_TIMEOUT = 10000; + private static final int EVENT_STREAM_READ_TIMEOUT = 10000; + private final Logger logger = LoggerFactory.getLogger(LaMetricTimeHandlerFactory.class); private final Map> discoveryServiceReg = new HashMap<>(); + @Reference(cardinality = ReferenceCardinality.OPTIONAL) + private ClientBuilder injectedClientBuilder; + + private ClientBuilder clientBuilder; + private StateDescriptionOptionsProvider stateDescriptionProvider; @Override @@ -74,7 +93,8 @@ protected ThingHandler createHandler(Thing thing) { if (THING_TYPE_DEVICE.equals(thingTypeUID)) { logger.debug("Creating handler for LaMetric Time device {}", thing); - LaMetricTimeHandler deviceHandler = new LaMetricTimeHandler((Bridge) thing, stateDescriptionProvider); + LaMetricTimeHandler deviceHandler = new LaMetricTimeHandler((Bridge) thing, stateDescriptionProvider, + getClientBuilder()); registerAppDiscoveryService(deviceHandler); return deviceHandler; @@ -141,4 +161,25 @@ protected void setDynamicStateDescriptionProvider(StateDescriptionOptionsProvide protected void unsetDynamicStateDescriptionProvider(StateDescriptionOptionsProvider provider) { this.stateDescriptionProvider = null; } + + private synchronized ClientBuilder getClientBuilder() { + if (clientBuilder == null) { + try { + clientBuilder = ClientBuilder.newBuilder(); + clientBuilder.property(CONNECT_TIMEOUT_JERSEY, EVENT_STREAM_CONNECT_TIMEOUT); + clientBuilder.property(READ_TIMEOUT_JERSEY, EVENT_STREAM_READ_TIMEOUT); + } catch (Exception e) { + // we seem to have no Jersey, so let's hope for an injected builder by CXF + if (this.injectedClientBuilder != null) { + clientBuilder = injectedClientBuilder; + clientBuilder.property(CONNECT_TIMEOUT, EVENT_STREAM_CONNECT_TIMEOUT); + clientBuilder.property(READ_TIMEOUT, EVENT_STREAM_READ_TIMEOUT); + } else { + throw new IllegalStateException("No JAX RS Client Builder available."); + } + } + } + return clientBuilder; + } + } diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/LaMetricTimeUtil.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/LaMetricTimeUtil.java index 0c06fcb02502c..da1b50f9f61d8 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/LaMetricTimeUtil.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/LaMetricTimeUtil.java @@ -15,9 +15,9 @@ import java.util.HashMap; import java.util.Map; -import org.syphr.lametrictime.api.local.model.Application; -import org.syphr.lametrictime.api.local.model.Widget; -import org.syphr.lametrictime.api.model.CoreApps; +import org.openhab.binding.lametrictime.api.local.model.Application; +import org.openhab.binding.lametrictime.api.local.model.Widget; +import org.openhab.binding.lametrictime.api.model.CoreApps; import com.google.gson.JsonPrimitive; diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/discovery/LaMetricTimeAppDiscoveryService.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/discovery/LaMetricTimeAppDiscoveryService.java index ef0c74b44e2c1..acad6aaaf1668 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/discovery/LaMetricTimeAppDiscoveryService.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/discovery/LaMetricTimeAppDiscoveryService.java @@ -24,6 +24,9 @@ import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.openhab.binding.lametrictime.api.local.model.Application; +import org.openhab.binding.lametrictime.api.local.model.Widget; +import org.openhab.binding.lametrictime.api.model.CoreApps; import org.openhab.binding.lametrictime.internal.LaMetricTimeBindingConstants; import org.openhab.binding.lametrictime.internal.LaMetricTimeUtil; import org.openhab.binding.lametrictime.internal.config.LaMetricTimeAppConfiguration; @@ -31,9 +34,6 @@ import org.openhab.binding.lametrictime.internal.handler.LaMetricTimeHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.lametrictime.api.local.model.Application; -import org.syphr.lametrictime.api.local.model.Widget; -import org.syphr.lametrictime.api.model.CoreApps; import com.google.gson.JsonPrimitive; diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/AbstractLaMetricTimeAppHandler.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/AbstractLaMetricTimeAppHandler.java index caa0670b2bb34..324e439ffdcd5 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/AbstractLaMetricTimeAppHandler.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/AbstractLaMetricTimeAppHandler.java @@ -24,14 +24,14 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.lametrictime.api.LaMetricTime; +import org.openhab.binding.lametrictime.api.local.ApplicationNotFoundException; +import org.openhab.binding.lametrictime.api.local.model.Application; +import org.openhab.binding.lametrictime.api.local.model.Widget; import org.openhab.binding.lametrictime.internal.WidgetRef; import org.openhab.binding.lametrictime.internal.config.LaMetricTimeAppConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.lametrictime.api.LaMetricTime; -import org.syphr.lametrictime.api.local.ApplicationNotFoundException; -import org.syphr.lametrictime.api.local.model.Application; -import org.syphr.lametrictime.api.local.model.Widget; /** * The {@link AbstractLaMetricTimeAppHandler} is the parent of all app handlers for diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/ClockAppHandler.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/ClockAppHandler.java index bef143bfa56e3..9039c9aa5af7b 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/ClockAppHandler.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/ClockAppHandler.java @@ -25,11 +25,11 @@ import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.model.CoreApps; import org.openhab.binding.lametrictime.internal.config.LaMetricTimeAppConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.lametrictime.api.local.ApplicationActionException; -import org.syphr.lametrictime.api.model.CoreApps; /** * The {@link ClockAppHandler} represents an instance of the built-in clock app. diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/CountdownAppHandler.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/CountdownAppHandler.java index fd47e0b0e9f58..92fd1ab020810 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/CountdownAppHandler.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/CountdownAppHandler.java @@ -20,11 +20,11 @@ import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.model.CoreApps; import org.openhab.binding.lametrictime.internal.config.LaMetricTimeAppConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.lametrictime.api.local.ApplicationActionException; -import org.syphr.lametrictime.api.model.CoreApps; /** * The {@link CountdownAppHandler} represents an instance of the built-in countdown app. diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/LaMetricTimeAppHandler.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/LaMetricTimeAppHandler.java index eb9a9b5e3069f..23ff90a9147c5 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/LaMetricTimeAppHandler.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/LaMetricTimeAppHandler.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.lametrictime.internal.handler; -import org.syphr.lametrictime.api.local.model.Widget; +import org.openhab.binding.lametrictime.api.local.model.Widget; /** * The {@link LaMetricTimeAppHandler} provides a common contract for all app handlers available for the device. diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/LaMetricTimeHandler.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/LaMetricTimeHandler.java index 4a027d3d6e1b2..fcf009611241c 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/LaMetricTimeHandler.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/LaMetricTimeHandler.java @@ -40,7 +40,19 @@ import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.StateOption; -import org.glassfish.jersey.client.ClientProperties; +import org.openhab.binding.lametrictime.api.Configuration; +import org.openhab.binding.lametrictime.api.LaMetricTime; +import org.openhab.binding.lametrictime.api.local.ApplicationActivationException; +import org.openhab.binding.lametrictime.api.local.LaMetricTimeLocal; +import org.openhab.binding.lametrictime.api.local.NotificationCreationException; +import org.openhab.binding.lametrictime.api.local.UpdateException; +import org.openhab.binding.lametrictime.api.local.model.Application; +import org.openhab.binding.lametrictime.api.local.model.Audio; +import org.openhab.binding.lametrictime.api.local.model.Bluetooth; +import org.openhab.binding.lametrictime.api.local.model.Device; +import org.openhab.binding.lametrictime.api.local.model.Display; +import org.openhab.binding.lametrictime.api.local.model.Widget; +import org.openhab.binding.lametrictime.api.model.enums.BrightnessMode; import org.openhab.binding.lametrictime.internal.LaMetricTimeBindingConstants; import org.openhab.binding.lametrictime.internal.LaMetricTimeConfigStatusMessage; import org.openhab.binding.lametrictime.internal.LaMetricTimeUtil; @@ -49,19 +61,6 @@ import org.openhab.binding.lametrictime.internal.config.LaMetricTimeConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.lametrictime.api.Configuration; -import org.syphr.lametrictime.api.LaMetricTime; -import org.syphr.lametrictime.api.local.ApplicationActivationException; -import org.syphr.lametrictime.api.local.LaMetricTimeLocal; -import org.syphr.lametrictime.api.local.NotificationCreationException; -import org.syphr.lametrictime.api.local.UpdateException; -import org.syphr.lametrictime.api.local.model.Application; -import org.syphr.lametrictime.api.local.model.Audio; -import org.syphr.lametrictime.api.local.model.Bluetooth; -import org.syphr.lametrictime.api.local.model.Device; -import org.syphr.lametrictime.api.local.model.Display; -import org.syphr.lametrictime.api.local.model.Widget; -import org.syphr.lametrictime.api.model.enums.BrightnessMode; /** * The {@link LaMetricTimeHandler} is responsible for handling commands, which are @@ -78,12 +77,16 @@ public class LaMetricTimeHandler extends ConfigStatusBridgeHandler { private final StateDescriptionOptionsProvider stateDescriptionProvider; + private final ClientBuilder clientBuilder; + private LaMetricTime clock; private ScheduledFuture connectionJob; - public LaMetricTimeHandler(Bridge bridge, StateDescriptionOptionsProvider stateDescriptionProvider) { + public LaMetricTimeHandler(Bridge bridge, StateDescriptionOptionsProvider stateDescriptionProvider, + ClientBuilder clientBuilder) { super(bridge); + this.clientBuilder = clientBuilder; this.stateDescriptionProvider = stateDescriptionProvider; if (stateDescriptionProvider == null) { @@ -99,8 +102,6 @@ public void initialize() { logger.debug("Creating LaMetric Time client"); Configuration clockConfig = new Configuration().withDeviceHost(bindingConfig.host) .withDeviceApiKey(bindingConfig.apiKey).withLogging(logger.isDebugEnabled()); - ClientBuilder clientBuilder = ClientBuilder.newBuilder().property(ClientProperties.CONNECT_TIMEOUT, 10000) - .property(ClientProperties.READ_TIMEOUT, 10000); clock = LaMetricTime.create(clockConfig, clientBuilder); connectionJob = scheduler.scheduleWithFixedDelay(() -> { diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/RadioAppHandler.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/RadioAppHandler.java index 2d8e9913a307c..e85d84d699f47 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/RadioAppHandler.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/RadioAppHandler.java @@ -21,11 +21,11 @@ import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.model.CoreApps; import org.openhab.binding.lametrictime.internal.config.LaMetricTimeAppConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.lametrictime.api.local.ApplicationActionException; -import org.syphr.lametrictime.api.model.CoreApps; /** * The {@link RadioAppHandler} represents an instance of the built-in radio app. diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/StopwatchAppHandler.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/StopwatchAppHandler.java index 14ad85240a8f1..90921bee1b137 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/StopwatchAppHandler.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/StopwatchAppHandler.java @@ -20,11 +20,11 @@ import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.model.CoreApps; import org.openhab.binding.lametrictime.internal.config.LaMetricTimeAppConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.lametrictime.api.local.ApplicationActionException; -import org.syphr.lametrictime.api.model.CoreApps; /** * The {@link StopwatchAppHandler} represents an instance of the built-in stopwatch app. diff --git a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/WeatherAppHandler.java b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/WeatherAppHandler.java index b8b9127c5d0f2..7ae94b160a8e6 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/WeatherAppHandler.java +++ b/bundles/org.openhab.binding.lametrictime/src/main/java/org/openhab/binding/lametrictime/internal/handler/WeatherAppHandler.java @@ -20,11 +20,11 @@ import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.lametrictime.api.local.ApplicationActionException; +import org.openhab.binding.lametrictime.api.model.CoreApps; import org.openhab.binding.lametrictime.internal.config.LaMetricTimeAppConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.lametrictime.api.local.ApplicationActionException; -import org.syphr.lametrictime.api.model.CoreApps; /** * The {@link WeatherAppHandler} represents an instance of the built-in weather app. diff --git a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/binding/binding.xml index 55e376f088abc..c706cde69ee11 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + LaMetric Time Binding This is the binding for LaMetric Time. diff --git a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/clock-app.xml b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/clock-app.xml index 9a613321da3d8..39060289682c8 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/clock-app.xml +++ b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/clock-app.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/countdown-app.xml b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/countdown-app.xml index f702e8dc27cd1..d0a9b9ef60508 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/countdown-app.xml +++ b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/countdown-app.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/radio-app.xml b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/radio-app.xml index 5dec87a4a2f16..e09f1498a3b6d 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/radio-app.xml +++ b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/radio-app.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/stopwatch-app.xml b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/stopwatch-app.xml index d9d2d4abdd4ad..2f8fb3e9fd956 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/stopwatch-app.xml +++ b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/stopwatch-app.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/weather-app.xml b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/weather-app.xml index bd6acfaebf2a7..596a6ac000cb3 100644 --- a/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/weather-app.xml +++ b/bundles/org.openhab.binding.lametrictime/src/main/resources/ESH-INF/thing/weather-app.xml @@ -6,7 +6,7 @@ - + diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/README b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/README new file mode 100644 index 0000000000000..f8dc6146b8a0f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/README @@ -0,0 +1,4 @@ +Test images were pulled from LaMetric's developer portal. + +info.png: https://developer.lametric.com/content/apps/icon_thumbs/1248.png +smile.gif: https://developer.lametric.com/content/apps/icon_thumbs/87.gif \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/info.png b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/info.png new file mode 100644 index 0000000000000..c1b8c80da5c33 Binary files /dev/null and b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/info.png differ diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/smile.gif b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/smile.gif new file mode 100644 index 0000000000000..566c38a9b066d Binary files /dev/null and b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/impl/smile.gif differ diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/action.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/action.json new file mode 100644 index 0000000000000..2f5de43688b81 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/action.json @@ -0,0 +1,8 @@ +{ + "enabled": { + "data_type": "bool" + }, + "time": { + "data_type": "string" + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/application-all.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/application-all.json new file mode 100644 index 0000000000000..df03fc30f75bd --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/application-all.json @@ -0,0 +1,15 @@ +{ + "actions": { + "radio.next": {}, + "radio.play": {}, + "radio.prev": {}, + "radio.stop": {} + }, + "package": "com.lametric.radio", + "vendor": "LaMetric", + "version": "1.0.10", + "version_code": "22", + "widgets": { + "589ed1b3fcdaa5180bf4848e55ba8061": {} + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/application-null-maps.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/application-null-maps.json new file mode 100644 index 0000000000000..f79ed2d6ab718 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/application-null-maps.json @@ -0,0 +1,6 @@ +{ + "package": "com.lametric.radio", + "vendor": "LaMetric", + "version": "1.0.10", + "version_code": "22" +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/audio.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/audio.json new file mode 100644 index 0000000000000..32019b9fd81e0 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/audio.json @@ -0,0 +1,3 @@ +{ + "volume": 42 +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-address.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-address.json new file mode 100644 index 0000000000000..cdf5e7aaad0b7 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-address.json @@ -0,0 +1,8 @@ +{ + "active": false, + "address": "AA:AA:AA:AA:AA:AA", + "available": true, + "discoverable": false, + "name": "LM9999", + "pairable": true +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-mac-address.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-mac-address.json new file mode 100644 index 0000000000000..d0ea1c3e05f62 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-mac-address.json @@ -0,0 +1,9 @@ +{ + "active": false, + "mac": "AA:AA:AA:AA:AA:AA", + "address": "AA:AA:AA:AA:AA:AA", + "available": true, + "discoverable": false, + "name": "LM9999", + "pairable": true +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-mac.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-mac.json new file mode 100644 index 0000000000000..7efad145a3c0e --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/bluetooth-mac.json @@ -0,0 +1,8 @@ +{ + "active": false, + "mac": "AA:AA:AA:AA:AA:AA", + "available": true, + "discoverable": false, + "name": "LM9999", + "pairable": true +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-chart.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-chart.json new file mode 100644 index 0000000000000..1072d2e711f94 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-chart.json @@ -0,0 +1,11 @@ +{ + "chartData": [ + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ] +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-goal.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-goal.json new file mode 100644 index 0000000000000..f3c87062d3986 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-goal.json @@ -0,0 +1,4 @@ +{ + "icon": "i120", + "goalData": {} +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-simple.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-simple.json new file mode 100644 index 0000000000000..9f7344060b91a --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/frame-simple.json @@ -0,0 +1,4 @@ +{ + "icon": "i87", + "text": "Hello world!" +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/goal-data.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/goal-data.json new file mode 100644 index 0000000000000..ff57ecf3ba0ac --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/goal-data.json @@ -0,0 +1,6 @@ +{ + "start": 0, + "current": 50, + "end": 100, + "unit": "%" +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/update-action.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/update-action.json new file mode 100644 index 0000000000000..5bcfa96603e2f --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/update-action.json @@ -0,0 +1,6 @@ +{ + "id": "countdown.configure", + "params": { + "duration": 30 + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/widget-updates.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/widget-updates.json new file mode 100644 index 0000000000000..403a18803b062 --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/widget-updates.json @@ -0,0 +1,9 @@ +{ + "frames": [ + { + "icon": "i120", + "text": "12°", + "index": 0 + } + ] +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/widget.json b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/widget.json new file mode 100644 index 0000000000000..83139101e109b --- /dev/null +++ b/bundles/org.openhab.binding.lametrictime/src/test/resources/org/openhab/binding/lametrictime/api/local/model/widget.json @@ -0,0 +1,7 @@ +{ + "package": "com.lametric.radio", + "index": -1, + "settings": { + "_title": "Radio" + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.leapmotion/pom.xml b/bundles/org.openhab.binding.leapmotion/pom.xml index 88fc583c272d8..5beef321ada5c 100644 --- a/bundles/org.openhab.binding.leapmotion/pom.xml +++ b/bundles/org.openhab.binding.leapmotion/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.leapmotion diff --git a/bundles/org.openhab.binding.leapmotion/src/main/feature/feature.xml b/bundles/org.openhab.binding.leapmotion/src/main/feature/feature.xml index 45bc963dee4a5..eeaaf929a3e92 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.leapmotion/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.leapmotion/${project.version} - mvn:${project.groupId}/openhab-addons-external/${project.version}/lib/libLeap - mvn:${project.groupId}/openhab-addons-external/${project.version}/lib/libLeapJava - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.leapmotion/${project.version} + mvn:${project.groupId}/openhab-addons-external/${project.version}/lib/libLeap + mvn:${project.groupId}/openhab-addons-external/${project.version}/lib/libLeapJava + diff --git a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionBindingConstants.java b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionBindingConstants.java index cdf0485080da9..f1bf67462e6bc 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionBindingConstants.java +++ b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionBindingConstants.java @@ -40,5 +40,4 @@ public class LeapMotionBindingConstants { public static final String GESTURE_ANTICLOCKWISE = "anticlockwise"; public static final String GESTURE_FINGERS = "fingers"; public static final String GESTURE_NOHAND = "nohand"; - } diff --git a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionColorProfile.java b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionColorProfile.java index 4e64e028a5420..6fcd82cdaef65 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionColorProfile.java +++ b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionColorProfile.java @@ -97,5 +97,4 @@ private HSBType changeColor(HSBType color, boolean clockwise) { HSBType newState = new HSBType(new DecimalType(hue), color.getSaturation(), color.getBrightness()); return newState; } - } diff --git a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionDimmerProfile.java b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionDimmerProfile.java index 25fba73fcb0ba..6dfcffbeabdbc 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionDimmerProfile.java +++ b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionDimmerProfile.java @@ -85,5 +85,4 @@ public void onTriggerFromHandler(String event) { } } } - } diff --git a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionProfileFactory.java b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionProfileFactory.java index 0559433f614a9..a166048d00283 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionProfileFactory.java +++ b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionProfileFactory.java @@ -111,5 +111,4 @@ public Collection getProfileTypes(@Nullable Locale locale) { return null; } } - } diff --git a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionSwitchProfile.java b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionSwitchProfile.java index b650c2933657f..b0e92848e523d 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionSwitchProfile.java +++ b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/LeapMotionSwitchProfile.java @@ -50,5 +50,4 @@ public void onTriggerFromHandler(String event) { callback.sendCommand(lastState ? OnOffType.OFF : OnOffType.ON); } } - } diff --git a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/discovery/LeapMotionDiscoveryService.java b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/discovery/LeapMotionDiscoveryService.java index 0c2807d5d0576..9965bdb78f22f 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/discovery/LeapMotionDiscoveryService.java +++ b/bundles/org.openhab.binding.leapmotion/src/main/java/org/openhab/binding/leapmotion/internal/discovery/LeapMotionDiscoveryService.java @@ -94,5 +94,4 @@ private void createDiscoveryResult() { private void removeDiscoveryResult() { removeOlderResults(System.currentTimeMillis()); } - } diff --git a/bundles/org.openhab.binding.leapmotion/src/main/resources/ESH-INF/config/dimmerprofile.xml b/bundles/org.openhab.binding.leapmotion/src/main/resources/ESH-INF/config/dimmerprofile.xml index b93f5548b149f..80f46844439e3 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/resources/ESH-INF/config/dimmerprofile.xml +++ b/bundles/org.openhab.binding.leapmotion/src/main/resources/ESH-INF/config/dimmerprofile.xml @@ -8,7 +8,8 @@ - The mode for interpreting gestures. Either it dims depending on the number of shown fingers or it uses the height of the hand over the controller. + The mode for interpreting gestures. Either it dims depending on the number of shown fingers or it uses + the height of the hand over the controller. diff --git a/bundles/org.openhab.binding.leapmotion/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.leapmotion/src/main/resources/ESH-INF/thing/thing-types.xml index 46d8e92c91eae..cd2c55ce55eaa 100644 --- a/bundles/org.openhab.binding.leapmotion/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.leapmotion/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -8,7 +9,7 @@ A Leap Motion Gesture Sensor - + diff --git a/bundles/org.openhab.binding.lghombot/pom.xml b/bundles/org.openhab.binding.lghombot/pom.xml index 8324015639d36..051d33220ec6c 100644 --- a/bundles/org.openhab.binding.lghombot/pom.xml +++ b/bundles/org.openhab.binding.lghombot/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.lghombot diff --git a/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/CameraUtil.java b/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/CameraUtil.java index e8dc949d98cfc..1e969307a04af 100644 --- a/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/CameraUtil.java +++ b/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/CameraUtil.java @@ -80,5 +80,4 @@ static State parseImageFromBytes(byte[] yuvData, int width, int height) { return UnDefType.UNDEF; } } - } diff --git a/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/LGHomBotBindingConstants.java b/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/LGHomBotBindingConstants.java index bdfd0dc19ce93..63c9a1dd8f2aa 100644 --- a/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/LGHomBotBindingConstants.java +++ b/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/LGHomBotBindingConstants.java @@ -82,5 +82,4 @@ public final class LGHomBotBindingConstants { private LGHomBotBindingConstants() { // No need to instance this class. } - } diff --git a/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/LGHomBotConfiguration.java b/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/LGHomBotConfiguration.java index eded25ef2e42d..18d84fdf0f5b6 100644 --- a/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/LGHomBotConfiguration.java +++ b/bundles/org.openhab.binding.lghombot/src/main/java/org/openhab/binding/lghombot/internal/LGHomBotConfiguration.java @@ -43,5 +43,4 @@ public class LGHomBotConfiguration { * Polling time (in seconds) to refresh state from the HomBot itself. */ public int pollingPeriod = 3; - } diff --git a/bundles/org.openhab.binding.lghombot/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.lghombot/src/main/resources/ESH-INF/binding/binding.xml index e64db94377007..46a5740b63387 100644 --- a/bundles/org.openhab.binding.lghombot/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.lghombot/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - LG HomBot Binding diff --git a/bundles/org.openhab.binding.lghombot/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.lghombot/src/main/resources/ESH-INF/thing/thing-types.xml index 219713a7d6e7a..4acf55b898475 100644 --- a/bundles/org.openhab.binding.lghombot/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.lghombot/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -9,29 +10,29 @@ CleaningRobot - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -89,19 +90,19 @@ Current battery charge. BatteryLevel - + Number Current CPU load. - + String Memory used by webserver on HomBot. - + Switch @@ -153,7 +154,7 @@ String Nickname of the HomBot. - + String @@ -178,61 +179,61 @@ Image Image feed from the top camera. - + DateTime Last time the HomBot cleaned. - + Image Map of last cleaned area. - + String Scheduled start time on Monday. - + String Scheduled start time on Tuesday. - + String Scheduled start time on Wednesday. - + String Scheduled start time on Thursday. - + String Scheduled start time on Friday. - + String Scheduled start time on Saturday. - + String Scheduled start time on Sunday. - + diff --git a/bundles/org.openhab.binding.lgtvserial/pom.xml b/bundles/org.openhab.binding.lgtvserial/pom.xml index c5f9dc2c88e0f..bf86c7b21678f 100644 --- a/bundles/org.openhab.binding.lgtvserial/pom.xml +++ b/bundles/org.openhab.binding.lgtvserial/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.lgtvserial diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/feature/feature.xml b/bundles/org.openhab.binding.lgtvserial/src/main/feature/feature.xml index d27108dd3b076..fb214d614633d 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.lgtvserial/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.lgtvserial/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.lgtvserial/${project.version} + diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/LgTvSerialBindingConstants.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/LgTvSerialBindingConstants.java index 9517c04e8aac3..da7927ecd9a1f 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/LgTvSerialBindingConstants.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/LgTvSerialBindingConstants.java @@ -34,5 +34,4 @@ public class LgTvSerialBindingConstants { public static final ThingTypeUID THING_TYPE_LGTV_LVX55_SERIES = new ThingTypeUID(BINDING_ID, "lgtv-LVx55-series"); public static final ThingTypeUID THING_TYPE_LGTV_M6503C = new ThingTypeUID(BINDING_ID, "lgtv-M6503C"); public static final ThingTypeUID THING_TYPE_LGTV_PW_SERIES = new ThingTypeUID(BINDING_ID, "lgtv-PW-series"); - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/LgTvSerialHandlerFactory.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/LgTvSerialHandlerFactory.java index 3ece422c80877..987ffbe4ef2e4 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/LgTvSerialHandlerFactory.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/LgTvSerialHandlerFactory.java @@ -26,9 +26,12 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.lgtvserial.internal.handler.LgTvSerialHandler; import org.openhab.binding.lgtvserial.internal.protocol.serial.SerialCommunicatorFactory; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link LgTvSerialHandlerFactory} is responsible for creating things and thing @@ -48,6 +51,13 @@ public class LgTvSerialHandlerFactory extends BaseThingHandlerFactory { THING_TYPE_LGTV_LK_SERIES, THING_TYPE_LGTV_M6503C, THING_TYPE_LGTV_PW_SERIES) .collect(Collectors.toSet())); + private final SerialPortManager serialPortManager; + + @Activate + public LgTvSerialHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); @@ -58,7 +68,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (supportsThingType(thingTypeUID)) { - return new LgTvSerialHandler(thing, FACTORY); + return new LgTvSerialHandler(thing, FACTORY, serialPortManager); } return null; diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/handler/LgTvSerialHandler.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/handler/LgTvSerialHandler.java index 2fe4b3559544b..ed1fd1d2f7ba1 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/handler/LgTvSerialHandler.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/handler/LgTvSerialHandler.java @@ -28,6 +28,10 @@ import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.lgtvserial.internal.protocol.serial.LGSerialCommand; import org.openhab.binding.lgtvserial.internal.protocol.serial.LGSerialCommunicator; import org.openhab.binding.lgtvserial.internal.protocol.serial.LGSerialResponse; @@ -61,6 +65,11 @@ public class LgTvSerialHandler extends BaseThingHandler { */ private final SerialCommunicatorFactory factory; + /** + * Serial port manager used to get serial port identifiers. + */ + private final SerialPortManager serialPortManager; + /** * Communicator used to send commands to the TV(s). */ @@ -87,9 +96,10 @@ public class LgTvSerialHandler extends BaseThingHandler { * @param thing Thing associated to this handler * @param factory Factory to retrieve a communicator for a given port */ - public LgTvSerialHandler(Thing thing, SerialCommunicatorFactory factory) { + public LgTvSerialHandler(Thing thing, SerialCommunicatorFactory factory, SerialPortManager serialPortManager) { super(thing); this.factory = factory; + this.serialPortManager = serialPortManager; } @Override @@ -118,11 +128,31 @@ public void onSuccess(ChannelUID channel, LGSerialResponse response) { public void onFailure(ChannelUID channel, LGSerialResponse response) { logger.debug("Received error response for channel {}: {}", channel, response.getState()); } - }; if (portName != null) { - communicator = factory.getInstance(portName); + SerialPortIdentifier serialPortIdentifier = serialPortManager.getIdentifier(portName); + if (serialPortIdentifier == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Serial port does not exist: " + portName); + return; + } + + try { + communicator = factory.getInstance(serialPortIdentifier); + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + return; + } catch (PortInUseException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Serial port already used: " + portName); + return; + } catch (UnsupportedCommOperationException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Unsupported operation on '" + portName + "': " + e.getMessage()); + return; + } + if (communicator != null) { communicator.register(responseListener); } else { diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialCommand.java index d3a5dde447f02..ccc278454283c 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialCommand.java @@ -36,11 +36,10 @@ public interface LGSerialCommand { * This method is used to send the serial protocol command to the communicator. * * @param channel Channel related to the command - * @param comm Communicator linked to the serial port - * @param data Data related to this command to send over the wire. If null, this means we should send an FF state - * read command. + * @param comm Communicator linked to the serial port + * @param data Data related to this command to send over the wire. If null, this means we should send an FF state + * read command. * @throws IOException */ void execute(ChannelUID channel, LGSerialCommunicator comm, Object data) throws IOException; - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialCommunicator.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialCommunicator.java index 97747ef9a27b8..e25d80b01c00d 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialCommunicator.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialCommunicator.java @@ -20,13 +20,13 @@ import java.util.Map; import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.NRSerialPort; -import gnu.io.SerialPort; -import gnu.io.UnsupportedCommOperationException; - /** * This class handles the communication (read/writes) between the COM port and the things. * @@ -37,7 +37,7 @@ public class LGSerialCommunicator { private OutputStream output; private InputStream input; - private NRSerialPort port; + private SerialPort port; private Map handlers = new HashMap<>(); private RegistrationCallback callback; @@ -51,16 +51,11 @@ public class LGSerialCommunicator { private static final int BAUD_RATE = 9600; - public LGSerialCommunicator(String portName, RegistrationCallback callback) { - NRSerialPort port = new NRSerialPort(portName, BAUD_RATE); - if (port.connect()) { - try { - port.getSerialPortInstance().setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, - SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); - } catch (UnsupportedCommOperationException e) { - logger.warn("Failed to set serial port communication parameters", e); - } - } + public LGSerialCommunicator(SerialPortIdentifier serialPortIdentifier, RegistrationCallback callback) + throws IOException, PortInUseException, UnsupportedCommOperationException { + SerialPort port = serialPortIdentifier.open(LGSerialCommunicator.class.getCanonicalName(), 2000); + port.setSerialPortParams(BAUD_RATE, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); + this.port = port; this.output = port.getOutputStream(); this.input = port.getInputStream(); @@ -148,9 +143,9 @@ public void close() { } catch (IOException e) { logger.debug("An error occured while closing the serial output stream", e); } - port.disconnect(); + port.close(); // For some reason, there needs some delay after close so we don't fail to open back the serial device - // TODO : investigate if this is still a real issue with the latest NRSerialPort jar + // TODO : investigate if this is still a real issue with the serial transport try { Thread.sleep(2000); } catch (InterruptedException e) { @@ -158,5 +153,4 @@ public void close() { logger.debug("Thread interrupted while closing the communicator"); } } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialResponse.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialResponse.java index 579ae7a3c29ff..b4cc881d0d357 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialResponse.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialResponse.java @@ -27,5 +27,4 @@ public interface LGSerialResponse { State getState(); boolean isSuccess(); - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialResponseListener.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialResponseListener.java index a0611fe50fd31..8d08f54406a12 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialResponseListener.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/LGSerialResponseListener.java @@ -28,5 +28,4 @@ public interface LGSerialResponseListener { void onSuccess(ChannelUID channel, LGSerialResponse response); void onFailure(ChannelUID channel, LGSerialResponse response); - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/RegistrationCallback.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/RegistrationCallback.java index 17c1ca385d603..f3d5fb90a8786 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/RegistrationCallback.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/RegistrationCallback.java @@ -20,5 +20,4 @@ public interface RegistrationCallback { void onUnregister(); - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/SerialCommunicatorFactory.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/SerialCommunicatorFactory.java index e3a909e7e86a6..6136b5d0cc2d0 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/SerialCommunicatorFactory.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/SerialCommunicatorFactory.java @@ -12,9 +12,13 @@ */ package org.openhab.binding.lgtvserial.internal.protocol.serial; +import java.io.IOException; import java.util.HashMap; import java.util.Map; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,31 +32,32 @@ public class SerialCommunicatorFactory { private final Logger logger = LoggerFactory.getLogger(SerialCommunicatorFactory.class); - private Map instances = new HashMap<>(); + private Map instances = new HashMap<>(); - public synchronized LGSerialCommunicator getInstance(String port) { - LGSerialCommunicator comm = instances.get(port); + public synchronized LGSerialCommunicator getInstance(SerialPortIdentifier serialPortIdentifier) + throws IOException, PortInUseException, UnsupportedCommOperationException { + LGSerialCommunicator comm = instances.get(serialPortIdentifier); if (comm == null) { - comm = createCommunicator(port); + comm = createCommunicator(serialPortIdentifier); if (comm != null) { - instances.put(port, comm); + instances.put(serialPortIdentifier, comm); } } return comm; } - private LGSerialCommunicator createCommunicator(final String portName) { - return new LGSerialCommunicator(portName, new RegistrationCallback() { + private LGSerialCommunicator createCommunicator(final SerialPortIdentifier serialPortIdentifier) + throws IOException, PortInUseException, UnsupportedCommOperationException { + return new LGSerialCommunicator(serialPortIdentifier, new RegistrationCallback() { @Override public void onUnregister() { logger.debug("Unregistered last handler, closing"); - deleteInstance(portName); + deleteInstance(serialPortIdentifier); } }); } - protected synchronized void deleteInstance(String port) { - instances.remove(port).close(); + protected synchronized void deleteInstance(SerialPortIdentifier serialPortIdentifier) { + instances.remove(serialPortIdentifier).close(); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AspectRatioCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AspectRatioCommand.java index 1dafeef0f0a10..f2629f889fc25 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AspectRatioCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AspectRatioCommand.java @@ -23,5 +23,4 @@ public class AspectRatioCommand extends BaseStringCommand { protected AspectRatioCommand(int setId) { super('k', 'c', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AutoSleepCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AutoSleepCommand.java index 0b57cb80556ef..1be5b55b1a29b 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AutoSleepCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AutoSleepCommand.java @@ -23,5 +23,4 @@ public class AutoSleepCommand extends BaseDecimalCommand { protected AutoSleepCommand(int setId) { super('f', 'g', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AutoVolumeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AutoVolumeCommand.java index 936031ee067aa..1784d0a138040 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AutoVolumeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/AutoVolumeCommand.java @@ -23,5 +23,4 @@ public class AutoVolumeCommand extends BaseOnOffCommand { protected AutoVolumeCommand(int setId) { super('d', 'u', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BacklightCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BacklightCommand.java index 8484ef09f87d4..3376a156d8631 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BacklightCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BacklightCommand.java @@ -23,5 +23,4 @@ public class BacklightCommand extends BasePercentCommand { protected BacklightCommand(int setId) { super('m', 'g', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BalanceCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BalanceCommand.java index bcf69a007c3ec..9cc690187fb00 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BalanceCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BalanceCommand.java @@ -23,5 +23,4 @@ public class BalanceCommand extends BasePercentCommand { protected BalanceCommand(int setId) { super('k', 't', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseDecimalCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseDecimalCommand.java index d42ebac752962..ae544c206f7ae 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseDecimalCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseDecimalCommand.java @@ -27,9 +27,9 @@ public abstract class BaseDecimalCommand extends BaseLGSerialCommand { /** * Create a command. * - * @param command1 Command category - * @param command2 Command key - * @param setId TV Set id this command is tied to + * @param command1 Command category + * @param command2 Command key + * @param setId TV Set id this command is tied to * @param updatable Define if this command is one that can update the TV or can only ever be a read status command. */ protected BaseDecimalCommand(char command1, char command2, int setId, boolean updatable) { @@ -41,7 +41,7 @@ protected BaseDecimalCommand(char command1, char command2, int setId, boolean up * * @param command1 Command category * @param command2 Command key - * @param setId TV Set id this command is tied to + * @param setId TV Set id this command is tied to */ protected BaseDecimalCommand(char command1, char command2, int setId) { @@ -58,5 +58,4 @@ protected LGSerialResponse createResponse(int set, boolean success, String data) String decimalValue = Integer.toString(Integer.parseInt(data, 16)); return new DecimalResponse(set, success, DecimalType.valueOf(decimalValue)); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseLGSerialCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseLGSerialCommand.java index edecef65d272d..c91deeb1d061a 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseLGSerialCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseLGSerialCommand.java @@ -78,5 +78,4 @@ protected String getCommand(Object data) { } protected abstract String computeSerialDataFrom(Object data); - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseOnOffCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseOnOffCommand.java index bbe448e297c2d..5c0807722698c 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseOnOffCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseOnOffCommand.java @@ -37,5 +37,4 @@ protected String computeSerialDataFrom(Object data) { protected LGSerialResponse createResponse(int set, boolean success, String data) { return new OnOffResponse(set, success, data); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BasePercentCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BasePercentCommand.java index 03710ce5c871c..922c297f7c116 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BasePercentCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BasePercentCommand.java @@ -38,5 +38,4 @@ protected LGSerialResponse createResponse(int set, boolean success, String data) String decimalValue = Integer.toString(Integer.parseInt(data, 16)); return new PercentResponse(set, success, PercentType.valueOf(decimalValue)); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseStringCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseStringCommand.java index f515822f5e8b1..b2df4645348ec 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseStringCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BaseStringCommand.java @@ -48,5 +48,4 @@ protected String computeSerialDataFrom(Object data) { protected LGSerialResponse createResponse(int set, boolean success, String data) { return new StringResponse(set, success, data); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BassCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BassCommand.java index 0d78ec3b2d2e9..c3d09918c0460 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BassCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BassCommand.java @@ -23,5 +23,4 @@ public class BassCommand extends BasePercentCommand { protected BassCommand(int setId) { super('k', 's', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BrightnessCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BrightnessCommand.java index 0e8933e51c42c..de0a2c537faf8 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BrightnessCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/BrightnessCommand.java @@ -23,5 +23,4 @@ public class BrightnessCommand extends BasePercentCommand { protected BrightnessCommand(int setId) { super('k', 'h', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorCommand.java index 005d4786a2c44..98aeb9ad538fb 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorCommand.java @@ -23,5 +23,4 @@ public class ColorCommand extends BasePercentCommand { protected ColorCommand(int setId) { super('k', 'i', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorTemperature2Command.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorTemperature2Command.java index 403f3cf2028ac..b94b9608d7be3 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorTemperature2Command.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorTemperature2Command.java @@ -23,5 +23,4 @@ public class ColorTemperature2Command extends BasePercentCommand { protected ColorTemperature2Command(int setId) { super('x', 'u', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorTemperatureCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorTemperatureCommand.java index 8e8cb2c9f044a..fdde6ad5dbf84 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorTemperatureCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ColorTemperatureCommand.java @@ -23,5 +23,4 @@ public class ColorTemperatureCommand extends BaseStringCommand { protected ColorTemperatureCommand(int setId) { super('k', 'u', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/CommandFactory.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/CommandFactory.java index 0c7b87d799762..af6785c23befa 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/CommandFactory.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/CommandFactory.java @@ -137,5 +137,4 @@ public static LGSerialCommand createCommandFor(ChannelUID channel, LGSerialRespo } return null; } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ContrastCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ContrastCommand.java index db530e53e4b85..71e836c86754a 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ContrastCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ContrastCommand.java @@ -23,5 +23,4 @@ public class ContrastCommand extends BasePercentCommand { protected ContrastCommand(int setId) { super('k', 'g', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/DPMCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/DPMCommand.java index 2cad10de3f974..825840292692a 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/DPMCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/DPMCommand.java @@ -23,5 +23,4 @@ public class DPMCommand extends BaseOnOffCommand { protected DPMCommand(int setId) { super('f', 'j', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ElapsedTimeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ElapsedTimeCommand.java index 0f1e2d75c0330..b19c853b0bb94 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ElapsedTimeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ElapsedTimeCommand.java @@ -23,5 +23,4 @@ public class ElapsedTimeCommand extends BaseDecimalCommand { protected ElapsedTimeCommand(int setId) { super('d', 'l', setId, false); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/EnergySavingCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/EnergySavingCommand.java index 567404a6466fd..2fafbcfc32926 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/EnergySavingCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/EnergySavingCommand.java @@ -25,5 +25,4 @@ public class EnergySavingCommand extends BaseStringCommand implements LGSerialCo protected EnergySavingCommand(int setId) { super('j', 'q', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/FanFaultCheckCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/FanFaultCheckCommand.java index dcceec6760382..4400075da5053 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/FanFaultCheckCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/FanFaultCheckCommand.java @@ -23,5 +23,4 @@ public class FanFaultCheckCommand extends BaseStringCommand { protected FanFaultCheckCommand(int setId) { super('d', 'w', setId, false); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/HPositionCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/HPositionCommand.java index 4a000f223c22e..f0b588d8b5db1 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/HPositionCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/HPositionCommand.java @@ -23,5 +23,4 @@ public class HPositionCommand extends BasePercentCommand { protected HPositionCommand(int setId) { super('f', 'q', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/HSizeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/HSizeCommand.java index 1acbdb94ade91..5eca7a6fb1385 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/HSizeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/HSizeCommand.java @@ -23,5 +23,4 @@ public class HSizeCommand extends BasePercentCommand { protected HSizeCommand(int setId) { super('f', 's', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/IRKeyCodeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/IRKeyCodeCommand.java index d3245e2bfa4a4..b3d31582840f4 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/IRKeyCodeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/IRKeyCodeCommand.java @@ -41,5 +41,4 @@ public void execute(ChannelUID channel, LGSerialCommunicator comm, Object data) public LGSerialResponse parseResponse(String response) { return null; } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ISMMethodCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ISMMethodCommand.java index 65e185de4512f..5733af2f3abf4 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ISMMethodCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ISMMethodCommand.java @@ -23,5 +23,4 @@ public class ISMMethodCommand extends BaseStringCommand { protected ISMMethodCommand(int setId) { super('j', 'p', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/InputSelect2Command.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/InputSelect2Command.java index c14b725b3a90d..2e519b30046f8 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/InputSelect2Command.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/InputSelect2Command.java @@ -23,5 +23,4 @@ public class InputSelect2Command extends BaseStringCommand { protected InputSelect2Command(int setId) { super('x', 'b', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/InputSelectCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/InputSelectCommand.java index d9eada0acd814..44dce219d244f 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/InputSelectCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/InputSelectCommand.java @@ -23,5 +23,4 @@ public class InputSelectCommand extends BaseStringCommand { protected InputSelectCommand(int setId) { super('k', 'b', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LG3DCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LG3DCommand.java index b8eeae1556fae..be3b6df3fe93f 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LG3DCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LG3DCommand.java @@ -23,5 +23,4 @@ public class LG3DCommand extends BaseStringCommand { protected LG3DCommand(int setId) { super('x', 't', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LG3DExtendedCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LG3DExtendedCommand.java index b8e8d2f49510c..8235d83f4d34a 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LG3DExtendedCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LG3DExtendedCommand.java @@ -23,5 +23,4 @@ public class LG3DExtendedCommand extends BaseStringCommand { protected LG3DExtendedCommand(int setId) { super('x', 'v', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LampFaultCheckCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LampFaultCheckCommand.java index 81d7a8d2f453a..2e112259acc3c 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LampFaultCheckCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/LampFaultCheckCommand.java @@ -23,5 +23,4 @@ public class LampFaultCheckCommand extends BaseStringCommand { protected LampFaultCheckCommand(int setId) { super('d', 'p', setId, false); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/NaturalModeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/NaturalModeCommand.java index 5ec26c18cc142..f5f8e0a7a7a3e 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/NaturalModeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/NaturalModeCommand.java @@ -23,5 +23,4 @@ public class NaturalModeCommand extends BaseOnOffCommand { protected NaturalModeCommand(int setId) { super('d', 'j', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/OSDLanguageCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/OSDLanguageCommand.java index 8272fa64e0c19..83d61dfa754d4 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/OSDLanguageCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/OSDLanguageCommand.java @@ -23,5 +23,4 @@ public class OSDLanguageCommand extends BaseStringCommand { protected OSDLanguageCommand(int setId) { super('f', 'i', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/OSDSelectCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/OSDSelectCommand.java index 2ad062bf09029..ccd4e778d9027 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/OSDSelectCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/OSDSelectCommand.java @@ -23,5 +23,4 @@ public class OSDSelectCommand extends BaseOnOffCommand { protected OSDSelectCommand(int setId) { super('k', 'l', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PictureModeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PictureModeCommand.java index 6bd86e7e9dff6..d6b5bfd3bedc0 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PictureModeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PictureModeCommand.java @@ -23,5 +23,4 @@ public class PictureModeCommand extends BaseStringCommand { protected PictureModeCommand(int setId) { super('d', 'x', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerCommand.java index 95c8033908bd1..3e4493f1d0576 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerCommand.java @@ -23,5 +23,4 @@ public class PowerCommand extends BaseOnOffCommand { protected PowerCommand(int setId) { super('k', 'a', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerIndicatorCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerIndicatorCommand.java index 9f6ed48a22720..b346a43d51134 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerIndicatorCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerIndicatorCommand.java @@ -23,5 +23,4 @@ public class PowerIndicatorCommand extends BaseOnOffCommand { protected PowerIndicatorCommand(int setId) { super('f', 'o', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerSavingCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerSavingCommand.java index e6540dbea9633..1197b2064639b 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerSavingCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/PowerSavingCommand.java @@ -23,5 +23,4 @@ public class PowerSavingCommand extends BaseStringCommand { protected PowerSavingCommand(int setId) { super('f', 'l', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/RawCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/RawCommand.java index 42fa344a42ff0..8c2135d66e89c 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/RawCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/RawCommand.java @@ -42,5 +42,4 @@ public void execute(ChannelUID channel, LGSerialCommunicator comm, Object data) comm.write(this, data.toString(), channel); } } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ScreenMuteCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ScreenMuteCommand.java index 5bd48cb28d8ca..6c96bde85da07 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ScreenMuteCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/ScreenMuteCommand.java @@ -23,5 +23,4 @@ public class ScreenMuteCommand extends BaseStringCommand { protected ScreenMuteCommand(int setId) { super('k', 'd', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SerialNoCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SerialNoCommand.java index 874e0b9b3d046..511c60c747f7c 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SerialNoCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SerialNoCommand.java @@ -23,5 +23,4 @@ public class SerialNoCommand extends BaseStringCommand { protected SerialNoCommand(int setId) { super('f', 'y', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SharpnessCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SharpnessCommand.java index 2858691de3166..6a57360ed0da7 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SharpnessCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SharpnessCommand.java @@ -23,5 +23,4 @@ public class SharpnessCommand extends BasePercentCommand { protected SharpnessCommand(int setId) { super('k', 'k', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SleepTimeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SleepTimeCommand.java index 25d681cac68d1..834f5128866c6 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SleepTimeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SleepTimeCommand.java @@ -25,5 +25,4 @@ public class SleepTimeCommand extends BaseDecimalCommand { protected SleepTimeCommand(int setId) { super('f', 'f', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SoftwareVersionCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SoftwareVersionCommand.java index 8571daadf2bc7..954d04919ee68 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SoftwareVersionCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SoftwareVersionCommand.java @@ -23,5 +23,4 @@ public class SoftwareVersionCommand extends BaseStringCommand { protected SoftwareVersionCommand(int setId) { super('f', 'z', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SoundModeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SoundModeCommand.java index e98566d92b186..38e85bdf68d22 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SoundModeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SoundModeCommand.java @@ -23,5 +23,4 @@ public class SoundModeCommand extends BaseStringCommand { protected SoundModeCommand(int setId) { super('d', 'y', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SpeakerCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SpeakerCommand.java index a86267d9062c1..d793be9123c34 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SpeakerCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/SpeakerCommand.java @@ -23,5 +23,4 @@ public class SpeakerCommand extends BaseOnOffCommand { protected SpeakerCommand(int setId) { super('d', 'v', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TemperatureValueCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TemperatureValueCommand.java index 89178e218d872..3ac6a85e9b235 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TemperatureValueCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TemperatureValueCommand.java @@ -33,5 +33,4 @@ protected TemperatureValueCommand(int setId) { protected LGSerialResponse createResponse(int set, boolean success, String data) { return new QuantityResponse(set, success, new QuantityType<>(Integer.parseInt(data, 16), SIUnits.CELSIUS)); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileCommand.java index 88d977db51212..32db710340df3 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileCommand.java @@ -23,5 +23,4 @@ public class TileCommand extends BaseStringCommand { protected TileCommand(int setId) { super('d', 'd', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileHPositionCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileHPositionCommand.java index 4a915e089545c..9e88f6e3af68c 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileHPositionCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileHPositionCommand.java @@ -23,5 +23,4 @@ public class TileHPositionCommand extends BasePercentCommand { protected TileHPositionCommand(int setId) { super('d', 'e', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileHSizeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileHSizeCommand.java index 86f6f0debf929..2fd7f0f48e495 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileHSizeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileHSizeCommand.java @@ -23,5 +23,4 @@ public class TileHSizeCommand extends BasePercentCommand { protected TileHSizeCommand(int setId) { super('d', 'g', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileIdSetCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileIdSetCommand.java index 0dc23840225b4..aea75702416d8 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileIdSetCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileIdSetCommand.java @@ -23,5 +23,4 @@ public class TileIdSetCommand extends BaseStringCommand { protected TileIdSetCommand(int setId) { super('d', 'i', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileVPositionCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileVPositionCommand.java index 3561d240e048a..91212e3b10027 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileVPositionCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileVPositionCommand.java @@ -23,5 +23,4 @@ public class TileVPositionCommand extends BasePercentCommand { protected TileVPositionCommand(int setId) { super('d', 'v', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileVSizeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileVSizeCommand.java index 36dc668c41fe0..85edb3e3d151f 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileVSizeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TileVSizeCommand.java @@ -23,5 +23,4 @@ public class TileVSizeCommand extends BasePercentCommand { protected TileVSizeCommand(int setId) { super('d', 'h', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TimeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TimeCommand.java index c57c0bdfcf16c..e987cf5559de5 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TimeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TimeCommand.java @@ -25,5 +25,4 @@ public class TimeCommand extends BaseStringCommand { protected TimeCommand(int setId) { super('f', 'a', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TintCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TintCommand.java index 2fabb093f5828..6b7020dcc53ed 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TintCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TintCommand.java @@ -23,5 +23,4 @@ public class TintCommand extends BasePercentCommand { protected TintCommand(int setId) { super('k', 'j', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TrebleCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TrebleCommand.java index f8bcf91fb791a..852de969ae027 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TrebleCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/TrebleCommand.java @@ -23,5 +23,4 @@ public class TrebleCommand extends BasePercentCommand { protected TrebleCommand(int setId) { super('k', 'r', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VPositionCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VPositionCommand.java index e9e6c089cc62e..f852cb82e601f 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VPositionCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VPositionCommand.java @@ -23,5 +23,4 @@ public class VPositionCommand extends BasePercentCommand { protected VPositionCommand(int setId) { super('f', 'r', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VSizeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VSizeCommand.java index 9342c80f10615..6af400c402e70 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VSizeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VSizeCommand.java @@ -23,5 +23,4 @@ public class VSizeCommand extends BasePercentCommand { protected VSizeCommand(int setId) { super('f', 't', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VolumeCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VolumeCommand.java index 12371dd737667..420ad5ebedf7a 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VolumeCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VolumeCommand.java @@ -23,5 +23,4 @@ public class VolumeCommand extends BasePercentCommand { protected VolumeCommand(int setId) { super('k', 'f', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VolumeMuteCommand.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VolumeMuteCommand.java index eef7c46e339d1..e231958d0ffcf 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VolumeMuteCommand.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/commands/VolumeMuteCommand.java @@ -23,5 +23,4 @@ public class VolumeMuteCommand extends BaseOnOffCommand { protected VolumeMuteCommand(int setId) { super('k', 'e', setId); } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/DecimalResponse.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/DecimalResponse.java index 0463b94133659..d37f033f7109a 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/DecimalResponse.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/DecimalResponse.java @@ -50,5 +50,4 @@ public State getState() { public boolean isSuccess() { return success; } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/OnOffResponse.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/OnOffResponse.java index 85e6089d0192b..38e97b4851248 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/OnOffResponse.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/OnOffResponse.java @@ -56,5 +56,4 @@ public State getState() { public boolean isSuccess() { return success; } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/PercentResponse.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/PercentResponse.java index dfee61e49c147..762e1cd8cf7d3 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/PercentResponse.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/PercentResponse.java @@ -50,5 +50,4 @@ public State getState() { public boolean isSuccess() { return success; } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/QuantityResponse.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/QuantityResponse.java index 0f4577dbaf90d..397329bc40113 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/QuantityResponse.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/QuantityResponse.java @@ -50,5 +50,4 @@ public State getState() { public boolean isSuccess() { return success; } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/StringResponse.java b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/StringResponse.java index 7a331f399035f..d287ef1534521 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/StringResponse.java +++ b/bundles/org.openhab.binding.lgtvserial/src/main/java/org/openhab/binding/lgtvserial/internal/protocol/serial/responses/StringResponse.java @@ -50,5 +50,4 @@ public State getState() { public boolean isSuccess() { return success; } - } diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/binding/binding.xml index 22df02f755ae7..1292a32fc7407 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + LG TV Serial Binding Controlling LG TVs using serial (RS232C) protocol diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/config/config.xml index 9559f78f602b3..033439cf27f03 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/config/config.xml @@ -6,10 +6,10 @@ serial-port + false Select serial port (COM1, /dev/ttyS0, ...) true - /dev/ttyS0 @@ -19,4 +19,3 @@ - diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-channels.xml b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-channels.xml index 984e2c728bf8f..7e048264a8a25 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-channels.xml +++ b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-channels.xml @@ -250,10 +250,10 @@ - - - - + + + + @@ -396,7 +396,7 @@ String Read the serial numbers - + @@ -447,7 +447,7 @@ String Check the software version - + @@ -461,7 +461,7 @@ Number:Temperature Read the inside temperature value - + @@ -518,7 +518,7 @@ Dimmer To assign the Tile ID for Tiling function - + @@ -566,4 +566,3 @@ - diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types-M6503C.xml b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types-M6503C.xml index 92afce5d0c255..a2c87f5563d64 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types-M6503C.xml +++ b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types-M6503C.xml @@ -4,7 +4,8 @@ xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + @@ -20,13 +21,13 @@ - + - + @@ -37,7 +38,7 @@ - + @@ -53,17 +54,17 @@ - - + @@ -173,4 +174,3 @@ - diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types-SAC34134216.xml b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types-SAC34134216.xml index 2916c00ffedb8..939807d08a0a4 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types-SAC34134216.xml +++ b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types-SAC34134216.xml @@ -4,8 +4,8 @@ xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - - + + @@ -13,8 +13,8 @@ LV and LW except *LV255C, *LV355B, *LV355C models]]> - - + + @@ -25,7 +25,7 @@ - + @@ -36,17 +36,17 @@ - + - + - - + + @@ -57,7 +57,7 @@ - + @@ -68,9 +68,9 @@ - + - + @@ -79,8 +79,8 @@ LK]]> - - + + @@ -91,7 +91,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -111,8 +111,8 @@ PW]]> - - + + @@ -122,7 +122,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -355,4 +355,3 @@ - diff --git a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types.xml index 87b93ef8e2fae..4e05f0c68eb30 100644 --- a/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.lgtvserial/src/main/resources/ESH-INF/thing/thing-types.xml @@ -5,11 +5,12 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> + This would be the thing to use if we haven't yet defined a proper thing limiting the supported + channels. --> - Generic LG television connected through a serial interface. This thing should be used only when there is no proper thing defined for your TV model as it has most existing channels for most known commands. + Generic LG television connected through a serial interface. This thing should be used only when there is + no proper thing defined for your TV model as it has most existing channels for most known commands. @@ -57,7 +58,7 @@ @@ -66,8 +67,7 @@ - + - diff --git a/bundles/org.openhab.binding.lgwebos/README.md b/bundles/org.openhab.binding.lgwebos/README.md index a1160974954d9..f8e431e055bc5 100644 --- a/bundles/org.openhab.binding.lgwebos/README.md +++ b/bundles/org.openhab.binding.lgwebos/README.md @@ -57,14 +57,14 @@ Thing lgwebos:WebOSTV:tv1 [host="192.168.2.119", key="6ef1dff6c7c936c8dc5056fc85 | power | Switch | Current power setting. TV can only be powered off, not on, via the TV's API. Turning on is implemented via Wake On Lan, for which the MAC address must be set in the thing configuration. | RW | | mute | Switch | Current mute setting. | RW | | volume | Dimmer | Current volume setting. Setting and reporting absolute percent values only works when using internal speakers. When connected to an external amp, the volume should be controlled using increase and decrease commands. | RW | -| channel | String | Current channel. Use only the channel number as command to update the channel. | RW | +| channel | String | Current channel. Use the channel number or channel id as command to update the channel. | RW | | toast | String | Displays a short message on the TV screen. See also rules section. | W | | mediaPlayer | Player | Media control player | W | | mediaStop | Switch | Media control stop | W | | appLauncher | String | Application ID of currently running application. This also allows to start applications on the TV by sending a specific Application ID to this channel. | RW | | rcButton | String | Simulates pressing of a button on the TV's remote control. See below for a list of button names. | W | -The list of available application IDs for your TV is logged when the binding is started. +The available application IDs for your TV can be listed using a console command (see below). You have to use one of these IDs as command for the appLauncher channel. Here are examples of values that could be available for your TV: airplay, amazon, com.apple.appletv, com.webos.app.browser, com.webos.app.externalinput.av1, com.webos.app.externalinput.av2, com.webos.app.externalinput.component, com.webos.app.hdmi1, com.webos.app.hdmi2, com.webos.app.hdmi3, com.webos.app.hdmi4, com.webos.app.homeconnect, com.webos.app.igallery, com.webos.app.livetv, com.webos.app.music, com.webos.app.photovideo, com.webos.app.recordings, com.webos.app.screensaver, googleplaymovieswebos, netflix, youtube.leanback.v4. @@ -95,6 +95,20 @@ This list has been compiled mostly through trial and error. Your mileage may var A sample HABPanel remote control widget can be found [in this github repository.](https://github.com/bbrodt/openhab2-misc) +## Console Commands + +The binding provides two specific commands you can use in the console. +Enter the command `lgwebos` to get the usage. + +``` +openhab> lgwebos +Usage: smarthome:lgwebos applications - list applications +Usage: smarthome:lgwebos channels - list channels +``` + +The command `applications` reports in the console the list of all applications with their id and name. +The command `channels` reports in the console the list of all channels with their id, number and name. + ## Example demo.things: diff --git a/bundles/org.openhab.binding.lgwebos/pom.xml b/bundles/org.openhab.binding.lgwebos/pom.xml index a230462914422..9f6896e096a18 100644 --- a/bundles/org.openhab.binding.lgwebos/pom.xml +++ b/bundles/org.openhab.binding.lgwebos/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.lgwebos diff --git a/bundles/org.openhab.binding.lgwebos/src/main/feature/feature.xml b/bundles/org.openhab.binding.lgwebos/src/main/feature/feature.xml index afed8cf537a61..d89efb117bcc4 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.lgwebos/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - openhab.tp-httpclient - mvn:org.openhab.addons.bundles/org.openhab.binding.lgwebos/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + openhab.tp-httpclient + mvn:org.openhab.addons.bundles/org.openhab.binding.lgwebos/${project.version} + diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/Application.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/Application.java index 0cd2bc92169b3..d297fe9d00ccf 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/Application.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/Application.java @@ -41,5 +41,4 @@ public String getName() { public String toString() { return "Application [id=" + id + ", name=" + name + "]"; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/LGWebOSActions.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/LGWebOSActions.java index e906ab46d2084..656d9a0c6c527 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/LGWebOSActions.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/action/LGWebOSActions.java @@ -134,7 +134,6 @@ private List getAppInfos() { return Collections.emptyList(); } return appInfos; - } public List getApplications() { @@ -153,7 +152,6 @@ public void launchApplication( logger.warn("Device with ThingID {} does not support any app with id: {}.", getLGWebOSHandler().getThing().getUID(), appId); } - } @RuleAction(label = "@text/actionLaunchApplicationWithParamsLabel", description = "@text/actionLaunchApplicationWithParamsDesc") diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/BaseChannelHandler.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/BaseChannelHandler.java index 8e71fd56934a4..c47d73c791c82 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/BaseChannelHandler.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/BaseChannelHandler.java @@ -73,7 +73,6 @@ public final synchronized void refreshSubscription(String channelId, LGWebOSHand logger.debug("Subscribed {} on Thing: {}", this.getClass().getName(), handler.getThing().getUID()); subscriptions.put(handler.getThing().getUID(), listener.get()); } - } /** @@ -101,5 +100,4 @@ public final synchronized void removeAnySubscription(LGWebOSHandler handler) { protected ResponseListener getDefaultResponseListener() { return defaultResponseListener; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/ChannelHandler.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/ChannelHandler.java index aadcbfe3d228f..3f4175696ebcb 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/ChannelHandler.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/ChannelHandler.java @@ -68,5 +68,4 @@ public interface ChannelHandler { * @param handler must not be null */ void onDeviceReady(String channelId, LGWebOSHandler handler); - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSHandlerFactory.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSHandlerFactory.java index e5cbd94b32276..945d896b84bfc 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSHandlerFactory.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LGWebOSHandlerFactory.java @@ -101,5 +101,4 @@ protected void deactivate(ComponentContext componentContext) { logger.warn("Unable to to stop websocket client.", e); } } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LauncherApplication.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LauncherApplication.java index f140536abb4d7..0b14ce0ca2ca5 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LauncherApplication.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/LauncherApplication.java @@ -72,7 +72,6 @@ public void onSuccess(List appInfos) { handler.setOptions(channelId, options); } }); - } @Override @@ -102,7 +101,6 @@ public void onReceiveCommand(String channelId, LGWebOSHandler handler, Command c logger.warn("TV does not support any app with id: {}.", value); } } - } @Override @@ -132,4 +130,15 @@ public void onSuccess(@Nullable AppInfo appInfo) { public @Nullable List getAppInfos(ThingUID key) { return applicationListCache.get(key); } + + public List reportApplications(ThingUID thingUID) { + List report = new ArrayList<>(); + List appInfos = applicationListCache.get(thingUID); + if (appInfos != null) { + for (AppInfo a : appInfos) { + report.add(a.getId() + " : " + a.getName()); + } + } + return report; + } } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/PowerControlPower.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/PowerControlPower.java index d9675cd6ff5b8..c5bb397ea0873 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/PowerControlPower.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/PowerControlPower.java @@ -114,5 +114,4 @@ public void onDeviceRemoved(String channelId, LGWebOSHandler handler) { public interface ConfigProvider { String getMacAddress(); } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/TVControlChannel.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/TVControlChannel.java index 3d17b9b582732..1217953d2a003 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/TVControlChannel.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/TVControlChannel.java @@ -64,12 +64,11 @@ public void onSuccess(List channels) { List options = new ArrayList<>(); for (ChannelInfo channel : channels) { String name = channel.getName() == null ? "" : channel.getName(); - options.add(new StateOption(channel.getChannelNumber(), channel.getChannelNumber() + " - " + name)); + options.add(new StateOption(channel.getId(), channel.getChannelNumber() + " - " + name)); } handler.setOptions(channelId, options); } }); - } @Override @@ -92,15 +91,14 @@ public void onReceiveCommand(String channelId, LGWebOSHandler handler, Command c logger.warn("No channel list cached for this device {}, ignoring command.", handler.getThing().getUID().toString()); } else { - Optional channelInfo = channels.stream().filter(c -> c.getChannelNumber().equals(value)) - .findFirst(); + Optional channelInfo = channels.stream() + .filter(c -> c.getId().equals(value) || c.getChannelNumber().equals(value)).findFirst(); if (channelInfo.isPresent()) { handler.getSocket().setChannel(channelInfo.get(), objResponseListener); } else { logger.info("TV does not have a channel: {}.", value); } } - } @Override @@ -121,8 +119,20 @@ public void onSuccess(@Nullable ChannelInfo channelInfo) { if (channelInfo == null) { return; } - handler.postUpdate(channelId, new StringType(channelInfo.getChannelNumber())); + handler.postUpdate(channelId, new StringType(channelInfo.getId())); } }; } + + public List reportChannels(ThingUID thingUID) { + List report = new ArrayList<>(); + List channels = channelListCache.get(thingUID); + if (channels != null) { + for (ChannelInfo channel : channels) { + String name = channel.getName() == null ? "" : channel.getName(); + report.add(channel.getId() + " : " + channel.getChannelNumber() + " - " + name); + } + } + return report; + } } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/VolumeControlMute.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/VolumeControlMute.java index 5bb77624fed65..4d3a09b42f5b9 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/VolumeControlMute.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/VolumeControlMute.java @@ -70,5 +70,4 @@ public void onSuccess(@Nullable Boolean value) { } }; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/VolumeControlVolume.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/VolumeControlVolume.java index a306047ff43d1..ac76a2a6ae2d8 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/VolumeControlVolume.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/VolumeControlVolume.java @@ -94,5 +94,4 @@ public void onSuccess(@Nullable Float value) { } }; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/WakeOnLanUtility.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/WakeOnLanUtility.java index cbe7e71ee11a3..a3eb5f46d6d60 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/WakeOnLanUtility.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/WakeOnLanUtility.java @@ -171,5 +171,4 @@ private static boolean checkIfLinuxCommandExists(String cmd) { } return false; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/console/LGWebOSCommandExtension.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/console/LGWebOSCommandExtension.java new file mode 100644 index 0000000000000..5afe219ee1e30 --- /dev/null +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/console/LGWebOSCommandExtension.java @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.lgwebos.internal.console; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingRegistry; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.io.console.Console; +import org.eclipse.smarthome.io.console.extensions.AbstractConsoleCommandExtension; +import org.eclipse.smarthome.io.console.extensions.ConsoleCommandExtension; +import org.openhab.binding.lgwebos.internal.handler.LGWebOSHandler; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link LGWebOSCommandExtension} is responsible for handling console commands + * + * @author Laurent Garnier - Initial contribution + */ + +@NonNullByDefault +@Component(service = ConsoleCommandExtension.class) +public class LGWebOSCommandExtension extends AbstractConsoleCommandExtension { + + private static final String APPLICATIONS = "applications"; + private static final String CHANNELS = "channels"; + + private final ThingRegistry thingRegistry; + + @Activate + public LGWebOSCommandExtension(final @Reference ThingRegistry thingRegistry) { + super("lgwebos", "Interact with the LG webOS binding."); + this.thingRegistry = thingRegistry; + } + + @Override + public void execute(String[] args, Console console) { + if (args.length == 2) { + LGWebOSHandler handler = null; + try { + ThingUID thingUID = new ThingUID(args[0]); + Thing thing = thingRegistry.get(thingUID); + if ((thing != null) && (thing.getHandler() != null) && (thing.getHandler() instanceof LGWebOSHandler)) { + handler = (LGWebOSHandler) thing.getHandler(); + } + } catch (IllegalArgumentException e) { + handler = null; + } + if (handler == null) { + console.println("Bad thing id '" + args[0] + "'"); + printUsage(console); + } else { + switch (args[1]) { + case APPLICATIONS: + handler.reportApplications().forEach(console::println); + break; + case CHANNELS: + handler.reportChannels().forEach(console::println); + break; + default: + printUsage(console); + break; + } + } + } else { + printUsage(console); + } + } + + @Override + public List getUsages() { + return Arrays.asList(new String[] { buildCommandUsage(" " + APPLICATIONS, "list applications"), + buildCommandUsage(" " + CHANNELS, "list channels") }); + } +} diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/discovery/LGWebOSUpnpDiscoveryParticipant.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/discovery/LGWebOSUpnpDiscoveryParticipant.java index 09836a3e66ec5..8d365be23a676 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/discovery/LGWebOSUpnpDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/discovery/LGWebOSUpnpDiscoveryParticipant.java @@ -77,5 +77,4 @@ public Set getSupportedThingTypeUIDs() { } return null; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSConfiguration.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSConfiguration.java index e89b5b33e7e6b..c20af488debc2 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSConfiguration.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSConfiguration.java @@ -55,5 +55,4 @@ public String toString() { return "WebOSConfiguration [host=" + host + ", port=" + port + ", key.length=" + getKey().length() + ", macAddress=" + macAddress + "]"; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSHandler.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSHandler.java index 8c113698fbc4c..d72f87934a34b 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSHandler.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSHandler.java @@ -256,7 +256,7 @@ public String getKey() { @Override public void storeKey(@Nullable String key) { if (!getKey().equals(key)) { - logger.debug("store new key"); + logger.info("Store {} as access Key in the thing configuration", key); // store it current configuration and avoiding complete re-initialization via handleConfigurationUpdate getLGWebOSConfig().key = key; @@ -315,7 +315,6 @@ public void onStateChanged(LGWebOSTVSocket.State state) { break; } - } @Override @@ -402,4 +401,12 @@ private void findMacAddress() { } } } + + public List reportApplications() { + return appLauncher.reportApplications(getThing().getUID()); + } + + public List reportChannels() { + return ((TVControlChannel) channelHandlers.get(CHANNEL_CHANNEL)).reportChannels(getThing().getUID()); + } } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVKeyboardInput.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVKeyboardInput.java index 7f59a87a071db..4442fa7911492 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVKeyboardInput.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVKeyboardInput.java @@ -198,5 +198,4 @@ private TextInputStatusInfo parseRawKeyboardData(JsonObject rawData) { return keyboard; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVMouseSocket.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVMouseSocket.java index bdea494961694..e360b6cae39e9 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVMouseSocket.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVMouseSocket.java @@ -79,7 +79,6 @@ public interface WebOSTVMouseSocketListener { public void onStateChanged(State oldState, State newState); public void onError(String errorMessage); - } public void setListener(@Nullable WebOSTVMouseSocketListener listener) { @@ -190,21 +189,17 @@ public void button(ButtonType type) { public void button(String keyName) { sendMessage("type:button\n" + "name:" + keyName + "\n" + "\n"); - } public void move(double dx, double dy) { sendMessage("type:move\n" + "dx:" + dx + "\n" + "dy:" + dy + "\n" + "down:0\n" + "\n"); - } public void move(double dx, double dy, boolean drag) { sendMessage("type:move\n" + "dx:" + dx + "\n" + "dy:" + dy + "\n" + "down:" + (drag ? 1 : 0) + "\n" + "\n"); - } public void scroll(double dx, double dy) { sendMessage("type:scroll\n" + "dx:" + dx + "\n" + "dy:" + dy + "\n" + "\n"); } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVSocket.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVSocket.java index f2745f9aaf845..70b0f8f953dfb 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVSocket.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/LGWebOSTVSocket.java @@ -307,11 +307,10 @@ public void onError(String message) { logger.debug("Registration failed with message: {}", message); disconnect(); } - }; this.requests.put(id, new ServiceSubscription<>("dummy", payload, x -> x, dummyListener)); - sendMessage(packet); + sendMessage(packet, !key.isEmpty()); } private int nextRequestId() { @@ -346,7 +345,6 @@ public void sendCommand(ServiceCommand command) { command.getTarget(), state); break; } - } public void unsubscribe(ServiceSubscription subscription) { @@ -363,24 +361,45 @@ public void unsubscribe(ServiceSubscription subscription) { } private void sendMessage(JsonObject json) { + sendMessage(json, false); + } + + private void sendMessage(JsonObject json, boolean checkKey) { String msg = GSON.toJson(json); Session s = this.session; try { if (s != null) { - logger.trace("Message [out]: {}", msg); + if (logger.isTraceEnabled()) { + logger.trace("Message [out]: {}", checkKey ? GSON.toJson(maskKeyInJson(json)) : msg); + } s.getRemote().sendString(msg); } else { - logger.warn("No Connection to TV, skipping [out]: {}", msg); + logger.warn("No Connection to TV, skipping [out]: {}", + checkKey ? GSON.toJson(maskKeyInJson(json)) : msg); } } catch (IOException e) { logger.warn("Unable to send message.", e); } } + private JsonObject maskKeyInJson(JsonObject json) { + if (json.has("payload") && json.getAsJsonObject("payload").has("client-key")) { + JsonObject jsonCopy = json.deepCopy(); + JsonObject payload = jsonCopy.getAsJsonObject("payload"); + payload.remove("client-key"); + payload.addProperty("client-key", "***"); + return jsonCopy; + } + return json; + } + @OnWebSocketMessage public void onMessage(String message) { - logger.trace("Message [in]: {}", message); Response response = GSON.fromJson(message, Response.class); + JsonElement payload = response.getPayload(); + JsonObject jsonPayload = payload == null ? null : payload.getAsJsonObject(); + String messageToLog = (jsonPayload != null && jsonPayload.has("client-key")) ? "***" : message; + logger.trace("Message [in]: {}", messageToLog); ServiceCommand request = null; if (response.getId() != null) { @@ -400,33 +419,33 @@ public void onMessage(String message) { switch (response.getType()) { case "response": if (request == null) { - logger.debug("No matching request found for response message: {}", message); + logger.debug("No matching request found for response message: {}", messageToLog); break; } - if (response.getPayload() == null) { - logger.debug("No payload in response message: {}", message); + if (payload == null) { + logger.debug("No payload in response message: {}", messageToLog); break; } try { - request.processResponse(response.getPayload().getAsJsonObject()); + request.processResponse(jsonPayload); } catch (RuntimeException ex) { // An uncaught runtime exception in @OnWebSocketMessage annotated method will cause the web socket // implementation to call @OnWebSocketError callback in which we would reset the connection. // Users have the ability to create miss-configurations in which IllegalArgumentException could be // thrown logger.warn("Error while processing message: {} - in response to request: {} - Error Message: {}", - message, request, ex.getMessage()); + messageToLog, request, ex.getMessage()); } break; case "error": - logger.debug("Error: {}", message); + logger.debug("Error: {}", messageToLog); if (request == null) { - logger.warn("No matching request found for error message: {}", message); + logger.warn("No matching request found for error message: {}", messageToLog); break; } - if (response.getPayload() == null) { - logger.warn("No payload in error message: {}", message); + if (payload == null) { + logger.warn("No payload in error message: {}", messageToLog); break; } try { @@ -437,43 +456,40 @@ public void onMessage(String message) { // Users have the ability to create miss-configurations in which IllegalArgumentException could be // thrown logger.warn("Error while processing error: {} - in response to request: {} - Error Message: {}", - message, request, ex.getMessage()); + messageToLog, request, ex.getMessage()); } break; case "hello": if (state != State.CONNECTING) { - logger.debug("Skipping response {}, not in CONNECTING state, state was {}", message, state); + logger.debug("Skipping response {}, not in CONNECTING state, state was {}", messageToLog, state); break; } - if (response.getPayload() == null) { - logger.warn("No payload in error message: {}", message); + if (jsonPayload == null) { + logger.warn("No payload in error message: {}", messageToLog); break; } - JsonObject deviceDescription = response.getPayload().getAsJsonObject(); Map map = new HashMap<>(); - map.put(PROPERTY_DEVICE_OS, deviceDescription.get("deviceOS").getAsString()); - map.put(PROPERTY_DEVICE_OS_VERSION, deviceDescription.get("deviceOSVersion").getAsString()); - map.put(PROPERTY_DEVICE_OS_RELEASE_VERSION, - deviceDescription.get("deviceOSReleaseVersion").getAsString()); + map.put(PROPERTY_DEVICE_OS, jsonPayload.get("deviceOS").getAsString()); + map.put(PROPERTY_DEVICE_OS_VERSION, jsonPayload.get("deviceOSVersion").getAsString()); + map.put(PROPERTY_DEVICE_OS_RELEASE_VERSION, jsonPayload.get("deviceOSReleaseVersion").getAsString()); map.put(PROPERTY_LAST_CONNECTED, Instant.now().toString()); config.storeProperties(map); sendRegister(); break; case "registered": if (state != State.REGISTERING) { - logger.debug("Skipping response {}, not in REGISTERING state, state was {}", message, state); + logger.debug("Skipping response {}, not in REGISTERING state, state was {}", messageToLog, state); break; } - if (response.getPayload() == null) { - logger.warn("No payload in registered message: {}", message); + if (jsonPayload == null) { + logger.warn("No payload in registered message: {}", messageToLog); break; } this.requests.remove(response.getId()); - config.storeKey(response.getPayload().getAsJsonObject().get("client-key").getAsString()); + config.storeKey(jsonPayload.get("client-key").getAsString()); setState(State.REGISTERED); break; } - } public interface WebOSTVSocketListener { @@ -481,7 +497,6 @@ public interface WebOSTVSocketListener { public void onStateChanged(State state); public void onError(String errorMessage); - } public ServiceSubscription subscribeMute(ResponseListener listener) { @@ -835,7 +850,6 @@ public void onError(String message) { jsonObj -> GSON.fromJson(jsonObj, AppInfo.class), interceptor); sendCommand(request); return request; - } public ServiceCommand getRunningApp(ResponseListener listener) { @@ -843,7 +857,6 @@ public ServiceCommand getRunningApp(ResponseListener listener) jsonObj -> GSON.fromJson(jsonObj, AppInfo.class), listener); sendCommand(request); return request; - } // KEYBOARD @@ -881,7 +894,6 @@ public void onStateChanged(LGWebOSTVMouseSocket.State oldState, LGWebOSTVMouseSo default: break; } - } @Override @@ -915,7 +927,6 @@ public void onError(String error) { ServiceCommand request = new ServiceCommand<>(uri, null, x -> x, listener); sendCommand(request); - } // Simulate Remote Control Button press @@ -931,5 +942,4 @@ public interface ConfigProvider { String getKey(); } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/command/ServiceCommand.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/command/ServiceCommand.java index fc8895ab27830..4dbc86d69e0b0 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/command/ServiceCommand.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/command/ServiceCommand.java @@ -98,5 +98,4 @@ public ResponseListener getResponseListener() { public String toString() { return "ServiceCommand [type=" + type + ", target=" + target + ", payload=" + payload + "]"; } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/command/ServiceSubscription.java b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/command/ServiceSubscription.java index 18df4b9acff44..02f697f37f859 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/command/ServiceSubscription.java +++ b/bundles/org.openhab.binding.lgwebos/src/main/java/org/openhab/binding/lgwebos/internal/handler/command/ServiceSubscription.java @@ -53,5 +53,4 @@ public ServiceSubscription(String uri, JsonObject payload, Function listener) { socket.closeLaunchSession(this, listener); } - } diff --git a/bundles/org.openhab.binding.lgwebos/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.lgwebos/src/main/resources/ESH-INF/config/config.xml index 8ef209a6434f4..5c8164934c450 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.lgwebos/src/main/resources/ESH-INF/config/config.xml @@ -14,10 +14,13 @@ Key exchanged with TV after pairing. + password - If MAC Address of TV is entered here, the binding will attempt to power on the device via Wake On Lan (WOL), when it receives command ON on channel power. Accepted value is six groups of two hexadecimal digits, separated by hyphens or colons, e.g '3c:cd:93:c2:20:e0'.) + If MAC Address of TV is entered here, the binding will attempt to power on the device via Wake On Lan + (WOL), when it receives command ON on channel power. Accepted value is six groups of two hexadecimal digits, + separated by hyphens or colons, e.g '3c:cd:93:c2:20:e0'.) diff --git a/bundles/org.openhab.binding.lgwebos/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.lgwebos/src/main/resources/ESH-INF/thing/thing-types.xml index 6e0c353ee44b2..02799a74f5aec 100644 --- a/bundles/org.openhab.binding.lgwebos/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.lgwebos/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,28 +9,28 @@ WebOS based smart TV - - - - - - - - - + + + + + + + + + - - - - - + + + + + deviceId - + diff --git a/bundles/org.openhab.binding.lifx/pom.xml b/bundles/org.openhab.binding.lifx/pom.xml index 92c4b8362eefe..d5cce570edc5b 100644 --- a/bundles/org.openhab.binding.lifx/pom.xml +++ b/bundles/org.openhab.binding.lifx/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.lifx diff --git a/bundles/org.openhab.binding.lifx/src/main/feature/feature.xml b/bundles/org.openhab.binding.lifx/src/main/feature/feature.xml index a81e3c8b94bd4..124e1465322b9 100644 --- a/bundles/org.openhab.binding.lifx/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.lifx/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.lifx/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.lifx/${project.version} + diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxBindingConstants.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxBindingConstants.java index c2c1aa6478443..4a00ec7bf3d96 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxBindingConstants.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxBindingConstants.java @@ -108,5 +108,4 @@ public class LifxBindingConstants { public static final Set SUPPORTED_THING_TYPES = Stream.of(THING_TYPE_COLORLIGHT, THING_TYPE_COLORIRLIGHT, THING_TYPE_COLORMZLIGHT, THING_TYPE_WHITELIGHT, THING_TYPE_TILELIGHT) .collect(Collectors.toSet()); - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxChannelFactory.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxChannelFactory.java index 28e8bfa505708..816e1640bf2f5 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxChannelFactory.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxChannelFactory.java @@ -27,5 +27,4 @@ public interface LifxChannelFactory { Channel createColorZoneChannel(ThingUID thingUID, int index); Channel createTemperatureZoneChannel(ThingUID thingUID, int index); - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxChannelFactoryImpl.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxChannelFactoryImpl.java index 061825fd0c082..e00c1149bd7c5 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxChannelFactoryImpl.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxChannelFactoryImpl.java @@ -107,5 +107,4 @@ protected void setLocaleProvider(LocaleProvider localeProvider) { protected void unsetLocaleProvider(LocaleProvider localeProvider) { this.localeProvider = null; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxHandlerFactory.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxHandlerFactory.java index f765ff266d780..dea5ab996a1c0 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxHandlerFactory.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxHandlerFactory.java @@ -70,5 +70,4 @@ protected void setChannelFactory(LifxChannelFactory channelFactory) { protected void unsetChannelFactory(LifxChannelFactory channelFactory) { this.channelFactory = null; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightCommunicationHandler.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightCommunicationHandler.java index 7b274db54a5fc..18e4c3401d9d2 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightCommunicationHandler.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightCommunicationHandler.java @@ -280,5 +280,4 @@ private void wrappedPacketSend(BiFunction } } } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightConfig.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightConfig.java index 33cc6c4d28e89..227188901b5fb 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightConfig.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightConfig.java @@ -43,5 +43,4 @@ public class LifxLightConfig { public Duration getFadeTime() { return Duration.ofMillis(fadetime); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightContext.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightContext.java index f1a77385bfc50..cba1dbc70d857 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightContext.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightContext.java @@ -67,5 +67,4 @@ public LifxLightState getPendingLightState() { public ScheduledExecutorService getScheduler() { return scheduler; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightDiscovery.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightDiscovery.java index 1e70d7456dd2b..782ea56cfa67b 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightDiscovery.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightDiscovery.java @@ -354,5 +354,4 @@ private DiscoveryResult createDiscoveryResult(DiscoveredLight light) throws Ille return builder.build(); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightOnlineStateUpdater.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightOnlineStateUpdater.java index e55cdca466e11..d38bb89dd18b0 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightOnlineStateUpdater.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightOnlineStateUpdater.java @@ -126,5 +126,4 @@ public void handleResponsePacket(Packet packet) { unansweredEchoPackets = 0; currentLightState.setOnline(); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightState.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightState.java index b09edb05e53b9..a36e31e4ef351 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightState.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightState.java @@ -27,9 +27,9 @@ import org.eclipse.smarthome.core.library.types.PercentType; import org.openhab.binding.lifx.internal.fields.HSBK; import org.openhab.binding.lifx.internal.listener.LifxLightStateListener; +import org.openhab.binding.lifx.internal.protocol.Effect; import org.openhab.binding.lifx.internal.protocol.PowerState; import org.openhab.binding.lifx.internal.protocol.SignalStrength; -import org.openhab.binding.lifx.internal.protocol.Effect; /** * The {@link LifxLightState} stores the properties that represent the state of a light. @@ -195,5 +195,4 @@ public void addListener(LifxLightStateListener listener) { public void removeListener(LifxLightStateListener listener) { listeners.remove(listener); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightStateChanger.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightStateChanger.java index d7cb0faa62195..3f3ff8b33889a 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightStateChanger.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxLightStateChanger.java @@ -34,6 +34,7 @@ import org.openhab.binding.lifx.internal.listener.LifxLightStateListener; import org.openhab.binding.lifx.internal.protocol.AcknowledgementResponse; import org.openhab.binding.lifx.internal.protocol.ApplicationRequest; +import org.openhab.binding.lifx.internal.protocol.Effect; import org.openhab.binding.lifx.internal.protocol.GetColorZonesRequest; import org.openhab.binding.lifx.internal.protocol.GetLightInfraredRequest; import org.openhab.binding.lifx.internal.protocol.GetLightPowerRequest; @@ -48,7 +49,6 @@ import org.openhab.binding.lifx.internal.protocol.SetPowerRequest; import org.openhab.binding.lifx.internal.protocol.SetTileEffectRequest; import org.openhab.binding.lifx.internal.protocol.SignalStrength; -import org.openhab.binding.lifx.internal.protocol.Effect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -386,5 +386,4 @@ private void getZonesIfZonesAreSet() { } } } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxSelectorContext.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxSelectorContext.java index 28fac3dc875e4..d25eca781b3cc 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxSelectorContext.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/LifxSelectorContext.java @@ -104,5 +104,4 @@ public void setBroadcastKey(@Nullable SelectionKey broadcastKey) { public void setUnicastKey(@Nullable SelectionKey unicastKey) { this.unicastKey = unicastKey; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/ByteField.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/ByteField.java index e3cf0bbae4d07..fe16d7b1d9f59 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/ByteField.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/ByteField.java @@ -46,5 +46,4 @@ public ByteBuffer value(ByteBuffer bytes) { public ByteBuffer bytesInternal(ByteBuffer value) { return value; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/Field.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/Field.java index b1544242c59db..6ae4f10a02aec 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/Field.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/Field.java @@ -99,5 +99,4 @@ public ByteBuffer bytes(T value) { public Field little() { return new LittleField<>(this); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/FloatField.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/FloatField.java index 8b8d715cb1823..0266e910e9621 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/FloatField.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/FloatField.java @@ -36,5 +36,4 @@ public Float value(ByteBuffer bytes) { protected ByteBuffer bytesInternal(Float value) { return ByteBuffer.allocate(4).putFloat(value); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/HSBKField.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/HSBKField.java index a6f1b3b1fa6d5..5fddd0bcd68df 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/HSBKField.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/HSBKField.java @@ -48,5 +48,4 @@ protected ByteBuffer bytesInternal(HSBK value) { .put(FIELD_SATURATION.bytes(value.getSaturation())).put(FIELD_BRIGHTNESS.bytes(value.getBrightness())) .put(FIELD_KELVIN.bytes(value.getKelvin())); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/LittleField.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/LittleField.java index 7cc6c466bc786..7dc3c36a05bdd 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/LittleField.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/LittleField.java @@ -67,5 +67,4 @@ public static ByteBuffer flip(ByteBuffer buf) { return ret; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/MACAddress.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/MACAddress.java index bd32cc7832a03..5d6050ce01470 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/MACAddress.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/MACAddress.java @@ -147,5 +147,4 @@ public boolean equals(@Nullable Object obj) { return true; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/MACAddressField.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/MACAddressField.java index 3061e325d4f9c..0c51c2cef92e2 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/MACAddressField.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/MACAddressField.java @@ -57,5 +57,4 @@ public ByteBuffer bytes(MACAddress value) { buf.rewind(); return buf; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/StringField.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/StringField.java index b93c90ebb16ed..e8b625a059d6a 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/StringField.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/StringField.java @@ -76,5 +76,4 @@ public StringField utf8() { charset = StandardCharsets.UTF_8; return this; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt16Field.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt16Field.java index 709b3d9ecc8a6..f7f5c16914e8d 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt16Field.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt16Field.java @@ -36,5 +36,4 @@ public Integer value(ByteBuffer bytes) { public ByteBuffer bytesInternal(Integer value) { return ByteBuffer.allocate(2).putShort((short) (value & 0xFFFF)); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt32Field.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt32Field.java index 2b402657eebaa..9a622914dda11 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt32Field.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt32Field.java @@ -36,5 +36,4 @@ public Long value(ByteBuffer bytes) { public ByteBuffer bytesInternal(Long value) { return ByteBuffer.allocate(4).putInt((int) (value & 0xFFFFFFFFL)); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt64Field.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt64Field.java index c2e60a9d989f0..3cc682aa118d0 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt64Field.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt64Field.java @@ -40,5 +40,4 @@ public Long value(ByteBuffer bytes) { protected ByteBuffer bytesInternal(Long value) { return ByteBuffer.allocate(8).putLong(value); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt8Field.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt8Field.java index 0ca0ddf6f5f77..bdcdf7ec48297 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt8Field.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/UInt8Field.java @@ -40,5 +40,4 @@ public Integer value(ByteBuffer bytes) { public ByteBuffer bytesInternal(Integer value) { return ByteBuffer.allocate(1).put((byte) (value & 0xFF)); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/Version.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/Version.java index eb216191bf412..c397a2a8509b6 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/Version.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/Version.java @@ -40,5 +40,4 @@ public long getMinor() { public String toString() { return major + "." + minor; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/VersionField.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/VersionField.java index 616742494e7f2..b68b821507c90 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/VersionField.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/fields/VersionField.java @@ -39,5 +39,4 @@ public Version value(ByteBuffer bytes) { public ByteBuffer bytesInternal(Version value) { return ByteBuffer.allocate(4).putInt((int) (((value.getMajor() << 16) | value.getMinor()) & 0xFFFFFFFFL)); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/handler/LifxLightHandler.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/handler/LifxLightHandler.java index ebb5c9203a9e4..b1b70422022df 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/handler/LifxLightHandler.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/handler/LifxLightHandler.java @@ -718,5 +718,4 @@ private void updateStatusIfChanged(ThingStatus status, ThingStatusDetail statusD updateStatus(status, statusDetail); } } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/listener/LifxLightStateListener.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/listener/LifxLightStateListener.java index 9eab26632530d..f35fec1ff63bc 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/listener/LifxLightStateListener.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/listener/LifxLightStateListener.java @@ -17,9 +17,9 @@ import org.eclipse.smarthome.core.library.types.PercentType; import org.openhab.binding.lifx.internal.LifxLightState; import org.openhab.binding.lifx.internal.fields.HSBK; +import org.openhab.binding.lifx.internal.protocol.Effect; import org.openhab.binding.lifx.internal.protocol.PowerState; import org.openhab.binding.lifx.internal.protocol.SignalStrength; -import org.openhab.binding.lifx.internal.protocol.Effect; /** * The {@link LifxLightStateListener} is notified when the properties of a {@link LifxLightState} change. diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/AcknowledgementResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/AcknowledgementResponse.java index f600a94daf100..c257d96b2eb88 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/AcknowledgementResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/AcknowledgementResponse.java @@ -49,5 +49,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/EchoRequestResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/EchoRequestResponse.java index 7c1f99e692268..01db68a6db286 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/EchoRequestResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/EchoRequestResponse.java @@ -64,5 +64,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GenericHandler.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GenericHandler.java index 086f0577b633e..72b589dc94932 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GenericHandler.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GenericHandler.java @@ -73,5 +73,4 @@ public T handle(ByteBuffer buf) { throw new IllegalArgumentException("Unable to instantiate empty packet", ex); } } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GenericPacket.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GenericPacket.java index 542672bcae9cd..89783669a13a0 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GenericPacket.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GenericPacket.java @@ -43,5 +43,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetColorZonesRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetColorZonesRequest.java index d28b49737898c..75db1e061f05f 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetColorZonesRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetColorZonesRequest.java @@ -82,5 +82,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateMultiZoneResponse.TYPE, StateZoneResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetEchoRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetEchoRequest.java index 29b8f93c1322f..84b8862b36f5d 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetEchoRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetEchoRequest.java @@ -77,5 +77,4 @@ public static GetEchoRequest currentTimeEchoRequest() { request.setPayload(payload); return request; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetGroupRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetGroupRequest.java index 964e8012e5f94..e10f4ae75c9aa 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetGroupRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetGroupRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateGroupResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetHostFirmwareRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetHostFirmwareRequest.java index 35b9ef1ca80bf..686ccf5352604 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetHostFirmwareRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetHostFirmwareRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateHostFirmwareResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetHostInfoRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetHostInfoRequest.java index c8aaf0d634b2f..91f5efa78ed2d 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetHostInfoRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetHostInfoRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateHostInfoResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetInfoRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetInfoRequest.java index 94d35aaa6b6c1..48b2a8e4b5317 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetInfoRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetInfoRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateInfoResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLabelRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLabelRequest.java index 7ba5d5fabeadd..1c825e3820106 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLabelRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLabelRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateLabelResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLightInfraredRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLightInfraredRequest.java index 4bc40a5180fd1..a27f67bf0c6eb 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLightInfraredRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLightInfraredRequest.java @@ -51,5 +51,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateLightInfraredResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLightPowerRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLightPowerRequest.java index 16ce666646257..3eee29946e394 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLightPowerRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLightPowerRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateLightPowerResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLocationRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLocationRequest.java index f4bb2375ae1ae..21d7416ce8781 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLocationRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetLocationRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateLocationResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetPowerRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetPowerRequest.java index 7d5a41ce28f61..d35bbea033589 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetPowerRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetPowerRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StatePowerResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetRequest.java index ce7c0a30d44e8..6c64872f0769c 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetServiceRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetServiceRequest.java index 1bb0555cd5223..4df9c46b725f2 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetServiceRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetServiceRequest.java @@ -51,5 +51,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateServiceResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTagLabelsRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTagLabelsRequest.java index a0e6e331d740e..a2a2fcbc44889 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTagLabelsRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTagLabelsRequest.java @@ -64,5 +64,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { TagLabelsResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTagsRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTagsRequest.java index c3910d05bf2a3..93acb6856c622 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTagsRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTagsRequest.java @@ -46,5 +46,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { TagsResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTileEffectRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTileEffectRequest.java index 2e464a68c31ea..2a6a8bae36c12 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTileEffectRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetTileEffectRequest.java @@ -53,5 +53,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateTileEffectResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetVersionRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetVersionRequest.java index 4479eec318fc9..1df439ddc1324 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetVersionRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetVersionRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateVersionResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetWifiFirmwareRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetWifiFirmwareRequest.java index 22ad119029ce3..c9877ded2f1e1 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetWifiFirmwareRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetWifiFirmwareRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateWifiFirmwareResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetWifiInfoRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetWifiInfoRequest.java index 468dd6e29d52b..06b1f4c6e70fd 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetWifiInfoRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/GetWifiInfoRequest.java @@ -52,5 +52,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateWifiInfoResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/Packet.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/Packet.java index 25dcec356fcc2..621be6494466c 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/Packet.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/Packet.java @@ -394,5 +394,4 @@ public boolean isFulfilled(Packet somePacket) { } return false; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PacketFactory.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PacketFactory.java index b05926d7cca25..4e5b0418c87bb 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PacketFactory.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PacketFactory.java @@ -154,5 +154,4 @@ public final void register(Class clazz) { public static @Nullable PacketHandler createHandler(int packetType) { return getInstance().getHandler(packetType); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PacketHandler.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PacketHandler.java index 5f984d682d5cb..24279788a98e3 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PacketHandler.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PacketHandler.java @@ -37,5 +37,4 @@ public interface PacketHandler { * could not be parsed */ public abstract T handle(ByteBuffer buf); - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PowerState.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PowerState.java index b665c92b7f9c9..b8a000b08bd0f 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PowerState.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/PowerState.java @@ -54,5 +54,4 @@ public static PowerState fromOnOffType(OnOffType onOff) { public OnOffType toOnOffType() { return this == ON ? OnOffType.ON : OnOffType.OFF; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/Product.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/Product.java index ccf659f3ed19c..d15afcd7bd180 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/Product.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/Product.java @@ -281,5 +281,4 @@ public static Product getProductFromProductID(long id) throws IllegalArgumentExc throw new IllegalArgumentException(id + " is not a valid product ID"); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetColorRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetColorRequest.java index b29d5d5938eac..c0747c0535ab9 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetColorRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetColorRequest.java @@ -89,5 +89,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetColorZonesRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetColorZonesRequest.java index 771142d3812cd..b880c2acb4a3b 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetColorZonesRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetColorZonesRequest.java @@ -122,5 +122,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetDimAbsoluteRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetDimAbsoluteRequest.java index 34b3eb3114cba..0d09f2864fbd8 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetDimAbsoluteRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetDimAbsoluteRequest.java @@ -73,5 +73,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLabelRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLabelRequest.java index 1e581b20debcd..2391be4c66982 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLabelRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLabelRequest.java @@ -67,5 +67,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLightInfraredRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLightInfraredRequest.java index f7dd20d59bd05..c5c33bc57391f 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLightInfraredRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLightInfraredRequest.java @@ -67,5 +67,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateLightInfraredResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLightPowerRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLightPowerRequest.java index a387c4d5c39cb..12ef6e75c7b0b 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLightPowerRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetLightPowerRequest.java @@ -86,5 +86,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StateLightPowerResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetPowerRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetPowerRequest.java index 23dfecae3ef11..813c41ab5a727 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetPowerRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetPowerRequest.java @@ -71,5 +71,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] { StatePowerResponse.TYPE }; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetTagsRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetTagsRequest.java index 51e0fa17fcd97..79728d9fe42c6 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetTagsRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetTagsRequest.java @@ -68,5 +68,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetTileEffectRequest.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetTileEffectRequest.java index 1a49bdd3a2c4c..1ea2935332630 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetTileEffectRequest.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SetTileEffectRequest.java @@ -150,5 +150,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SignalStrength.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SignalStrength.java index 687b2add3d748..e5298822e033f 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SignalStrength.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/SignalStrength.java @@ -72,5 +72,4 @@ public double toRSSI() { public String toString() { return "SignalStrength [milliWatts=" + milliWatts + ", rssi=" + Math.round(toRSSI()) + "]"; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateGroupResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateGroupResponse.java index 0a0b95f70603a..fef588c2659cf 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateGroupResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateGroupResponse.java @@ -90,5 +90,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateHostFirmwareResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateHostFirmwareResponse.java index 029193db0727c..fe71423ae5a2a 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateHostFirmwareResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateHostFirmwareResponse.java @@ -84,5 +84,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateHostInfoResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateHostInfoResponse.java index c33a575829f87..c7f08cef8cae9 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateHostInfoResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateHostInfoResponse.java @@ -81,5 +81,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateInfoResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateInfoResponse.java index 170caed171437..9772b10416243 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateInfoResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateInfoResponse.java @@ -90,5 +90,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLabelResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLabelResponse.java index 97e5ba198ee9c..549e1793e4b6b 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLabelResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLabelResponse.java @@ -65,5 +65,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLightInfraredResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLightInfraredResponse.java index 5fd8aa320fb5c..7d6c76aeb414b 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLightInfraredResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLightInfraredResponse.java @@ -56,5 +56,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLightPowerResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLightPowerResponse.java index 939ff6afde4c2..d77edab575335 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLightPowerResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLightPowerResponse.java @@ -58,5 +58,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLocationResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLocationResponse.java index 2fe40417d28c6..4fc53f0564932 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLocationResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateLocationResponse.java @@ -90,5 +90,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateMultiZoneResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateMultiZoneResponse.java index 2d366b0407911..9daca4cfc80b0 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateMultiZoneResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateMultiZoneResponse.java @@ -95,5 +95,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StatePowerResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StatePowerResponse.java index 55065df608330..0ff09f4f60d84 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StatePowerResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StatePowerResponse.java @@ -58,5 +58,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateResponse.java index 1c4be112f87a9..e4f51721208c3 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateResponse.java @@ -95,5 +95,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateServiceResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateServiceResponse.java index c391d0cf52b19..4b9a44ea7414c 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateServiceResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateServiceResponse.java @@ -69,5 +69,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateVersionResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateVersionResponse.java index d301b52c16581..2d67a1293e42c 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateVersionResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateVersionResponse.java @@ -90,5 +90,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateWifiFirmwareResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateWifiFirmwareResponse.java index 876eb43eb876d..233dd59135076 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateWifiFirmwareResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateWifiFirmwareResponse.java @@ -84,5 +84,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateWifiInfoResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateWifiInfoResponse.java index 401b7a71c8139..45235628651a3 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateWifiInfoResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateWifiInfoResponse.java @@ -81,5 +81,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateZoneResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateZoneResponse.java index a975bdd80aefd..b5dbe62fb0b4e 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateZoneResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/StateZoneResponse.java @@ -78,5 +78,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/TagLabelsResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/TagLabelsResponse.java index d90493b9a650d..80473ba7dfad1 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/TagLabelsResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/TagLabelsResponse.java @@ -65,5 +65,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/TagsResponse.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/TagsResponse.java index 0caea16525460..8996ab2df1d09 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/TagsResponse.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/protocol/TagsResponse.java @@ -57,5 +57,4 @@ protected ByteBuffer packetBytes() { public int[] expectedResponses() { return new int[] {}; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxMessageUtil.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxMessageUtil.java index d03a3b4c58dbc..a1b2b951d4206 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxMessageUtil.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxMessageUtil.java @@ -131,5 +131,4 @@ public static boolean sameColors(HSBK... colors) { public static long randomSourceId() { return UUID.randomUUID().getLeastSignificantBits() & (-1L >>> 32); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxNetworkUtil.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxNetworkUtil.java index 70fd4d02bfa11..ec319a8dd7282 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxNetworkUtil.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxNetworkUtil.java @@ -136,5 +136,4 @@ public static int getNewBroadcastPort() { }); return BROADCAST_PORT + (offset % (PORT_MAX - BROADCAST_PORT)); } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxSelectorUtil.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxSelectorUtil.java index 3c76885d7c60f..ca0ebeca261b4 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxSelectorUtil.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxSelectorUtil.java @@ -313,5 +313,4 @@ private static boolean sendPacket(@Nullable LifxSelectorContext context, Packet } return false; } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxThrottlingUtil.java b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxThrottlingUtil.java index e7785afef1dc3..90e334720d6af 100644 --- a/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxThrottlingUtil.java +++ b/bundles/org.openhab.binding.lifx/src/main/java/org/openhab/binding/lifx/internal/util/LifxThrottlingUtil.java @@ -144,5 +144,4 @@ public static void unlock() { tracker.unlock(); } } - } diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/binding/binding.xml index 2a0c5832fbfb5..ef2ea7f4d8ee4 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - LIFX Binding diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/config/config.xml index af6f9df2d1741..b2f662f94f3ab 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/config/config.xml @@ -37,14 +37,16 @@ pattern="(36[0]|3[0-5][0-9]|[12][0-9][0-9]|[1-9][0-9]|[0-9]),(100|[1-9][0-9]|[0-9]),(100|[1-9][0-9]|[0-9])" required="false"> - Comma separated Hue (0-360), saturation (0-100) and brightness (0-100) levels used when switching on the light. Use empty value to leave it as is. + Comma separated Hue (0-360), saturation (0-100) and brightness (0-100) levels used when switching on the + light. Use empty value to leave it as is. - Color temperature level used when switching on the light. Use empty value to leave color temperature as is. + Color temperature level used when switching on the light. Use empty value to leave color temperature as + is. diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/channel.xml b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/channel.xml index 2435546d4dfb8..5536a9ec2eee8 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/channel.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/channel.xml @@ -12,7 +12,7 @@ Lighting - + @@ -23,7 +23,7 @@ Lighting - + @@ -47,7 +47,7 @@ Sets the temperature of the light ColorLight - + @@ -68,7 +68,7 @@ - + diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colorirlight.xml b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colorirlight.xml index a90067477e942..9738e16e99573 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colorirlight.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colorirlight.xml @@ -1,18 +1,19 @@ - - - - - + + + + macAddress - + diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colorlight.xml b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colorlight.xml index 4ba2fe7c74c53..c4e54beabdd10 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colorlight.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colorlight.xml @@ -1,17 +1,18 @@ - - - - + + + macAddress - + diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colormzlight.xml b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colormzlight.xml index 21a8af1d43866..f7276a66b96e7 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colormzlight.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/colormzlight.xml @@ -1,17 +1,18 @@ - - - - + + + macAddress - + diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/tilelight.xml b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/tilelight.xml index 6f155fca97056..5b60250cde7f7 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/tilelight.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/tilelight.xml @@ -7,13 +7,13 @@ - - - - + + + + macAddress - + diff --git a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/whitelight.xml b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/whitelight.xml index 807025c4175f0..dc6f45d746af2 100644 --- a/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/whitelight.xml +++ b/bundles/org.openhab.binding.lifx/src/main/resources/ESH-INF/thing/whitelight.xml @@ -1,17 +1,18 @@ - - - - + + + macAddress - + diff --git a/bundles/org.openhab.binding.linky/pom.xml b/bundles/org.openhab.binding.linky/pom.xml index 0b9c26ed2865b..b5264d0789a69 100644 --- a/bundles/org.openhab.binding.linky/pom.xml +++ b/bundles/org.openhab.binding.linky/pom.xml @@ -1,18 +1,20 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.linky openHAB Add-ons :: Bundles :: Linky Binding - - + + !android.*,!com.android.org.*,!dalvik.*,!javax.annotation.meta.*,!org.apache.harmony.*,!org.conscrypt.*,!sun.* diff --git a/bundles/org.openhab.binding.linky/src/main/feature/feature.xml b/bundles/org.openhab.binding.linky/src/main/feature/feature.xml index f73253e2f2a9b..3a1dd653712d9 100644 --- a/bundles/org.openhab.binding.linky/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.linky/src/main/feature/feature.xml @@ -1,10 +1,9 @@ - - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.linky/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.linky/${project.version} + diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyBindingConstants.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyBindingConstants.java index 2f58b1b0ef92d..c29124a902ed7 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyBindingConstants.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/LinkyBindingConstants.java @@ -37,5 +37,4 @@ public class LinkyBindingConstants { public static final String LAST_MONTH = "monthly#lastMonth"; public static final String THIS_YEAR = "yearly#thisYear"; public static final String LAST_YEAR = "yearly#lastYear"; - } diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/console/LinkyCommandExtension.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/console/LinkyCommandExtension.java index fe0106d599072..1cbc5caad3e4a 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/console/LinkyCommandExtension.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/console/LinkyCommandExtension.java @@ -116,5 +116,4 @@ public List getUsages() { new String[] { buildCommandUsage(" " + REPORT + " []", "report daily consumptions between two dates") }); } - } diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java index 009d57220b37b..fdf3edba32eb2 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/handler/LinkyHandler.java @@ -384,5 +384,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { logger.debug("The Linky binding is read-only and can not handle command {}", command); } } - } diff --git a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/model/LinkyConsumptionData.java b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/model/LinkyConsumptionData.java index 16b060de7f13e..b6ed156029b65 100644 --- a/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/model/LinkyConsumptionData.java +++ b/bundles/org.openhab.binding.linky/src/main/java/org/openhab/binding/linky/internal/model/LinkyConsumptionData.java @@ -69,5 +69,4 @@ public boolean isPositive() { return valeur > 0; } } - } diff --git a/bundles/org.openhab.binding.linky/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.linky/src/main/resources/ESH-INF/binding/binding.xml index 617baff45b801..8ff4c869f7de0 100644 --- a/bundles/org.openhab.binding.linky/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.linky/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Linky Binding Retrieves your energy consumption data from Enedis website diff --git a/bundles/org.openhab.binding.linky/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.linky/src/main/resources/ESH-INF/thing/thing-types.xml index bcf48919676cc..4b503cd85d825 100644 --- a/bundles/org.openhab.binding.linky/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.linky/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -7,15 +8,16 @@ - Provides your energy consumption data. - In order to receive the data, you must activate your account at https://espace-client-particuliers.enedis.fr/web/espace-particuliers/compteur-linky. + Provides your energy consumption data. + In order to receive the data, you must activate your account at + https://espace-client-particuliers.enedis.fr/web/espace-particuliers/compteur-linky. - + - - - - + + + + @@ -31,11 +33,11 @@ - + - + @@ -44,27 +46,27 @@ - + - + - + - + - + - + @@ -75,7 +77,7 @@ - + diff --git a/bundles/org.openhab.binding.linuxinput/pom.xml b/bundles/org.openhab.binding.linuxinput/pom.xml index 9b6ef6f0f3f31..0e48db86d38b8 100644 --- a/bundles/org.openhab.binding.linuxinput/pom.xml +++ b/bundles/org.openhab.binding.linuxinput/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.linuxinput diff --git a/bundles/org.openhab.binding.linuxinput/src/main/feature/feature.xml b/bundles/org.openhab.binding.linuxinput/src/main/feature/feature.xml index 2e411ff0f8f35..5ba575431ca57 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.linuxinput/src/main/feature/feature.xml @@ -1,20 +1,20 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - wrap - mvn:com.github.jnr/jnr-enxio/0.19 - - wrap:mvn:com.github.jnr/jnr-posix/3.0.47$overwrite=merge&Import-Package=jnr.ffi.provider.jffi,jnr.constants,jnr.constants.platform,jnr.constants.platform.windows,jnr.ffi,jnr.ffi.annotations,jnr.ffi.byref,jnr.ffi.mapper,jnr.ffi.provider,jnr.ffi.types,com.kenai.jffi,jnr.ffi.provider.converters - mvn:com.github.jnr/jffi/1.2.18/jar/native - mvn:com.github.jnr/jffi/1.2.18/jar/complete - mvn:com.github.jnr/jnr-constants/0.9.11 - mvn:com.github.jnr/jnr-ffi/2.1.9 - wrap:mvn:com.github.jnr/jnr-a64asm/1.0.0$Bundle-Name=jnr-a64asm&Bundle-SymbolicName=com.github.jnr.jnr-a64asm&Bundle-Version=1.0.0 - wrap:mvn:com.github.jnr/jnr-x86asm/1.0.2$Bundle-Name=jnr-x86asm&Bundle-SymbolicName=com.github.jnr.jnr-x86asm&Bundle-Version=1.0.2 - mvn:org.ow2.asm/asm/5.0.3 - mvn:org.openhab.addons.bundles/org.openhab.binding.linuxinput/${project.version} - + + openhab-runtime-base + wrap + mvn:com.github.jnr/jnr-enxio/0.19 + + wrap:mvn:com.github.jnr/jnr-posix/3.0.47$overwrite=merge&Import-Package=jnr.ffi.provider.jffi,jnr.constants,jnr.constants.platform,jnr.constants.platform.windows,jnr.ffi,jnr.ffi.annotations,jnr.ffi.byref,jnr.ffi.mapper,jnr.ffi.provider,jnr.ffi.types,com.kenai.jffi,jnr.ffi.provider.converters + mvn:com.github.jnr/jffi/1.2.18/jar/native + mvn:com.github.jnr/jffi/1.2.18/jar/complete + mvn:com.github.jnr/jnr-constants/0.9.11 + mvn:com.github.jnr/jnr-ffi/2.1.9 + wrap:mvn:com.github.jnr/jnr-a64asm/1.0.0$Bundle-Name=jnr-a64asm&Bundle-SymbolicName=com.github.jnr.jnr-a64asm&Bundle-Version=1.0.0 + wrap:mvn:com.github.jnr/jnr-x86asm/1.0.2$Bundle-Name=jnr-x86asm&Bundle-SymbolicName=com.github.jnr.jnr-x86asm&Bundle-Version=1.0.2 + mvn:org.ow2.asm/asm/5.0.3 + mvn:org.openhab.addons.bundles/org.openhab.binding.linuxinput/${project.version} + diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/DeviceReadingHandler.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/DeviceReadingHandler.java index b8a007e0f609d..3069c71b8469c 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/DeviceReadingHandler.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/DeviceReadingHandler.java @@ -12,6 +12,9 @@ */ package org.openhab.binding.linuxinput.internal; +import java.io.IOException; +import java.util.concurrent.CancellationException; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Thing; @@ -21,9 +24,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.concurrent.CancellationException; - /** * Abstract handler, that encapsulates the lifecycle of an underlying device. * @@ -63,7 +63,7 @@ public final void initialize() { logger.warn("Could not read event", e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } - } , getClass(), getInstanceName()); + }, getClass(), getInstanceName()); thread.start(); worker = thread; } @@ -110,7 +110,8 @@ public final void dispose() { } private void stopWorker() throws InterruptedException { - @Nullable Thread activeWorker = this.worker; + @Nullable + Thread activeWorker = this.worker; logger.debug("interrupting worker {}", activeWorker); worker = null; diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputBindingConstants.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputBindingConstants.java index 5ef068393e58c..b886f3f6b5922 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputBindingConstants.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputBindingConstants.java @@ -23,7 +23,8 @@ */ @NonNullByDefault public class LinuxInputBindingConstants { - private LinuxInputBindingConstants() { } + private LinuxInputBindingConstants() { + } public static final String BINDING_ID = "linuxinput"; diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputDiscoveryService.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputDiscoveryService.java index d28366554753b..b6a650b2dd987 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputDiscoveryService.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputDiscoveryService.java @@ -12,6 +12,17 @@ */ package org.openhab.binding.linuxinput.internal; +import static org.openhab.binding.linuxinput.internal.LinuxInputBindingConstants.THING_TYPE_DEVICE; + +import java.io.File; +import java.io.IOException; +import java.nio.file.*; +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; @@ -26,17 +37,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.IOException; -import java.nio.file.*; -import java.time.Duration; -import java.util.Collections; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; -import java.util.concurrent.TimeUnit; - -import static org.openhab.binding.linuxinput.internal.LinuxInputBindingConstants.THING_TYPE_DEVICE; - /** * Discovery service for LinuxInputHandlers based on the /dev/input directory. * diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputHandler.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputHandler.java index e9b01bf1d4560..912f8b1642b75 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputHandler.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputHandler.java @@ -12,6 +12,13 @@ */ package org.openhab.binding.linuxinput.internal; +import static org.openhab.binding.linuxinput.internal.LinuxInputBindingConstants.*; + +import java.io.IOException; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.util.*; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.CoreItemFactory; @@ -26,13 +33,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.util.*; - -import static org.openhab.binding.linuxinput.internal.LinuxInputBindingConstants.*; - /** * Handler for Linux Input devices. * @@ -109,7 +109,8 @@ boolean delayedSetup() throws IOException { @Override protected void closeDevice() throws IOException { - @Nullable EvdevDevice currentDevice = device; + @Nullable + EvdevDevice currentDevice = device; device = null; if (currentDevice != null) { @@ -130,7 +131,8 @@ String getInstanceName() { @Override void handleEventsInThread() throws IOException { try (Selector selector = EvdevDevice.openSelector()) { - @Nullable EvdevDevice currentDevice = device; + @Nullable + EvdevDevice currentDevice = device; if (currentDevice == null) { throw new IOException("trying to handle events without an device"); } @@ -163,7 +165,8 @@ private void handleEvent(EvdevDevice.InputEvent event) { if (event.type() != EvdevLibrary.Type.KEY) { return; } - @Nullable Channel channel = channels.get(event.getCode()); + @Nullable + Channel channel = channels.get(event.getCode()); if (channel == null) { String msg = "Could not find channel for code {}"; if (isInitialized()) { diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputHandlerFactory.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputHandlerFactory.java index 6bfb1ab3c005f..203312131a454 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputHandlerFactory.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/LinuxInputHandlerFactory.java @@ -12,6 +12,11 @@ */ package org.openhab.binding.linuxinput.internal; +import static org.openhab.binding.linuxinput.internal.LinuxInputBindingConstants.THING_TYPE_DEVICE; + +import java.util.Collections; +import java.util.Set; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Thing; @@ -21,11 +26,6 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.osgi.service.component.annotations.Component; -import java.util.Collections; -import java.util.Set; - -import static org.openhab.binding.linuxinput.internal.LinuxInputBindingConstants.THING_TYPE_DEVICE; - /** * InputHandlerFactory for Linux Input devices. * diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/EvdevDevice.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/EvdevDevice.java index 162ab8171cb44..b6b07f1bd3177 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/EvdevDevice.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/EvdevDevice.java @@ -12,15 +12,7 @@ */ package org.openhab.binding.linuxinput.internal.evdev4j; -import jnr.constants.platform.Errno; -import jnr.constants.platform.OpenFlags; -import jnr.enxio.channels.NativeDeviceChannel; -import jnr.enxio.channels.NativeFileSelectorProvider; -import jnr.ffi.byref.PointerByReference; -import jnr.posix.POSIX; -import jnr.posix.POSIXFactory; -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.openhab.binding.linuxinput.internal.evdev4j.jnr.EvdevLibrary; +import static org.openhab.binding.linuxinput.internal.evdev4j.Utils.combineFlags; import java.io.Closeable; import java.io.IOException; @@ -37,7 +29,16 @@ import java.util.List; import java.util.Optional; -import static org.openhab.binding.linuxinput.internal.evdev4j.Utils.combineFlags; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.linuxinput.internal.evdev4j.jnr.EvdevLibrary; + +import jnr.constants.platform.Errno; +import jnr.constants.platform.OpenFlags; +import jnr.enxio.channels.NativeDeviceChannel; +import jnr.enxio.channels.NativeFileSelectorProvider; +import jnr.ffi.byref.PointerByReference; +import jnr.posix.POSIX; +import jnr.posix.POSIXFactory; /** * Classbased access to libevdev-input functionality. diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/LastErrorException.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/LastErrorException.java index 11da336fa995f..36226c30169b7 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/LastErrorException.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/LastErrorException.java @@ -17,9 +17,10 @@ import java.text.MessageFormat; import java.util.Optional; +import org.eclipse.jdt.annotation.NonNullByDefault; + import jnr.constants.platform.linux.Errno; import jnr.posix.POSIX; -import org.eclipse.jdt.annotation.NonNullByDefault; /** * Exception wrapping an operating system errno. diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/Utils.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/Utils.java index fc155af72e79c..50633b20ddc85 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/Utils.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/Utils.java @@ -14,9 +14,10 @@ import java.util.Optional; -import jnr.constants.Constant; import org.eclipse.jdt.annotation.NonNullByDefault; +import jnr.constants.Constant; + /** * @author Thomas Weißschuh - Initial contribution */ diff --git a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/jnr/EvdevLibrary.java b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/jnr/EvdevLibrary.java index 286a7550abf4c..0a31637a136bb 100644 --- a/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/jnr/EvdevLibrary.java +++ b/bundles/org.openhab.binding.linuxinput/src/main/java/org/openhab/binding/linuxinput/internal/evdev4j/jnr/EvdevLibrary.java @@ -126,7 +126,8 @@ public InputEvent(Runtime runtime) { @SuppressWarnings("unused") class ReadFlag { - private ReadFlag() { } + private ReadFlag() { + } public static final int SYNC = 1; public static final int NORMAL = 2; @@ -135,7 +136,8 @@ private ReadFlag() { } } class KeyEventValue { - private KeyEventValue() { } + private KeyEventValue() { + } public static final int UP = 0; public static final int DOWN = 1; diff --git a/bundles/org.openhab.binding.lirc/pom.xml b/bundles/org.openhab.binding.lirc/pom.xml index f35b20393a890..7fc79d0aadf1f 100644 --- a/bundles/org.openhab.binding.lirc/pom.xml +++ b/bundles/org.openhab.binding.lirc/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.lirc diff --git a/bundles/org.openhab.binding.lirc/src/main/feature/feature.xml b/bundles/org.openhab.binding.lirc/src/main/feature/feature.xml index 6aaff9cd5f012..3684dc445f27c 100644 --- a/bundles/org.openhab.binding.lirc/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.lirc/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.lirc/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.lirc/${project.version} + diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/LIRCBindingConstants.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/LIRCBindingConstants.java index 7d17b0981dd89..740286f1b9163 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/LIRCBindingConstants.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/LIRCBindingConstants.java @@ -46,5 +46,4 @@ public class LIRCBindingConstants { // List of all properties public static final String PROPERTY_REMOTE = "remote"; - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/LIRCResponseException.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/LIRCResponseException.java index 1888795d31140..f91a4a248bc6c 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/LIRCResponseException.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/LIRCResponseException.java @@ -55,5 +55,4 @@ public LIRCResponseException(Throwable cause) { public LIRCResponseException(String message, Throwable cause) { super(message, cause); } - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/config/LIRCBridgeConfiguration.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/config/LIRCBridgeConfiguration.java index 78c732d71f0da..6adb5e31da8fe 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/config/LIRCBridgeConfiguration.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/config/LIRCBridgeConfiguration.java @@ -50,5 +50,4 @@ public int getPortNumber() { public void setPortNumber(int portNumber) { this.portNumber = portNumber; } - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/config/LIRCRemoteConfiguration.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/config/LIRCRemoteConfiguration.java index e613411786130..c241517111d69 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/config/LIRCRemoteConfiguration.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/config/LIRCRemoteConfiguration.java @@ -34,5 +34,4 @@ public String getRemote() { public void setRemote(String remote) { this.remote = remote; } - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCConnector.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCConnector.java index 7fbbfe61daddf..53b17cc0fb0ed 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCConnector.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCConnector.java @@ -21,7 +21,6 @@ import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; -import org.apache.commons.io.IOUtils; import org.openhab.binding.lirc.internal.config.LIRCBridgeConfiguration; import org.openhab.binding.lirc.internal.messages.LIRCButtonEvent; import org.openhab.binding.lirc.internal.messages.LIRCResponse; @@ -75,23 +74,19 @@ public void disconnect() { } if (outWriter != null) { logger.debug("Close print writer stream"); - IOUtils.closeQuietly(outWriter); + outWriter.close(); outWriter = null; } - if (out != null) { - logger.debug("Close tcp out stream"); - IOUtils.closeQuietly(out); - out = null; - } - if (in != null) { - logger.debug("Close tcp in stream"); - IOUtils.closeQuietly(in); - in = null; - } if (socket != null) { logger.debug("Close socket"); - IOUtils.closeQuietly(socket); + try { + socket.close(); + } catch (IOException e) { + logger.debug("Error while closing the socket: {}", e.getMessage()); + } socket = null; + out = null; + in = null; } logger.debug("Disconnected"); } @@ -193,5 +188,4 @@ public synchronized void sendMessageToListeners(LIRCResponse message) { logger.error("Error invoking event listener", e); } } - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCEventListener.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCEventListener.java index aa9ce31148504..03fbc2b1c1303 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCEventListener.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCEventListener.java @@ -45,5 +45,4 @@ public interface LIRCEventListener { * Error occured. */ void errorOccured(String error); - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCStreamReader.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCStreamReader.java index ac50b58de8731..71d18f67ed446 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCStreamReader.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/connector/LIRCStreamReader.java @@ -22,7 +22,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.io.IOUtils; import org.openhab.binding.lirc.internal.LIRCResponseException; import org.openhab.binding.lirc.internal.messages.LIRCButtonEvent; import org.openhab.binding.lirc.internal.messages.LIRCResponse; @@ -104,7 +103,11 @@ public void run() { logger.error("Invalid message received", e); } } - IOUtils.closeQuietly(reader); + try { + reader.close(); + } catch (IOException e) { + logger.debug("Error while closing the input stream: {}", e.getMessage()); + } } private void processResponse(String responseText) throws LIRCResponseException { @@ -137,5 +140,4 @@ private void processResponse(String responseText) throws LIRCResponseException { LIRCResponse response = new LIRCResponse(command, success, data); connector.sendMessageToListeners(response); } - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/discovery/LIRCRemoteDiscoveryService.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/discovery/LIRCRemoteDiscoveryService.java index 2d3ef4ee598c7..70033ca162a6a 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/discovery/LIRCRemoteDiscoveryService.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/discovery/LIRCRemoteDiscoveryService.java @@ -77,5 +77,4 @@ private void addRemote(ThingUID bridge, String remote) { .withProperties(properties).build(); thingDiscovered(discoveryResult); } - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/handler/LIRCBridgeHandler.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/handler/LIRCBridgeHandler.java index 672b2447d85b4..8f28612e24b9c 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/handler/LIRCBridgeHandler.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/handler/LIRCBridgeHandler.java @@ -195,7 +195,5 @@ public void errorOccured(String error) { logger.error("Error occured: {}", error); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, error); } - } - } diff --git a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/messages/LIRCResponse.java b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/messages/LIRCResponse.java index 3e0faaec8cda6..a0daeab8c6ea4 100644 --- a/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/messages/LIRCResponse.java +++ b/bundles/org.openhab.binding.lirc/src/main/java/org/openhab/binding/lirc/internal/messages/LIRCResponse.java @@ -41,5 +41,4 @@ public boolean isSuccess() { public String[] getData() { return data; } - } diff --git a/bundles/org.openhab.binding.lirc/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.lirc/src/main/resources/ESH-INF/binding/binding.xml index 20b2c6a4b2343..a7a50a7341391 100644 --- a/bundles/org.openhab.binding.lirc/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.lirc/src/main/resources/ESH-INF/binding/binding.xml @@ -1,10 +1,12 @@ - LIRC Binding The LIRC binding allows transmission and receipt of - standard infrared remote control signals via a LIRC server. + standard infrared remote control signals via a LIRC + server. Andrew Nagle diff --git a/bundles/org.openhab.binding.lirc/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.lirc/src/main/resources/ESH-INF/thing/thing-types.xml index c3f53524fbe36..7d730ebc7369d 100644 --- a/bundles/org.openhab.binding.lirc/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.lirc/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -9,8 +10,8 @@ An IR remote control - - + + diff --git a/bundles/org.openhab.binding.logreader/pom.xml b/bundles/org.openhab.binding.logreader/pom.xml index c29ee7df46187..0601e304eb1c0 100644 --- a/bundles/org.openhab.binding.logreader/pom.xml +++ b/bundles/org.openhab.binding.logreader/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.logreader diff --git a/bundles/org.openhab.binding.logreader/src/main/feature/feature.xml b/bundles/org.openhab.binding.logreader/src/main/feature/feature.xml index 588337bb6a077..0f16c6808f568 100644 --- a/bundles/org.openhab.binding.logreader/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.logreader/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.logreader/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.logreader/${project.version} + diff --git a/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/binding/binding.xml index ab12464301947..e702d5f3c6ae4 100644 --- a/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - LogReader Binding diff --git a/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/thing/channels.xml index 083464f84cbd7..4b9db8aa39768 100644 --- a/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/thing/channels.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/thing/reader.xml b/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/thing/reader.xml index f460d2b1b0849..bdcfc3534347f 100644 --- a/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/thing/reader.xml +++ b/bundles/org.openhab.binding.logreader/src/main/resources/ESH-INF/thing/reader.xml @@ -1,5 +1,6 @@ - @@ -9,17 +10,17 @@ Log reader to analyze log events - - - - - - - + + + + + + + - - - + + + diff --git a/bundles/org.openhab.binding.loxone/pom.xml b/bundles/org.openhab.binding.loxone/pom.xml index a7e9761c558e4..d7d656250c2d7 100644 --- a/bundles/org.openhab.binding.loxone/pom.xml +++ b/bundles/org.openhab.binding.loxone/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.loxone diff --git a/bundles/org.openhab.binding.loxone/src/main/feature/feature.xml b/bundles/org.openhab.binding.loxone/src/main/feature/feature.xml index 86b6d39dfd083..06f9d7351c744 100644 --- a/bundles/org.openhab.binding.loxone/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.loxone/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.loxone/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.loxone/${project.version} + diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxDynamicStateDescriptionProvider.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxDynamicStateDescriptionProvider.java index e523fb2744ca0..bd31f94e708a5 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxDynamicStateDescriptionProvider.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxDynamicStateDescriptionProvider.java @@ -43,7 +43,7 @@ public class LxDynamicStateDescriptionProvider implements DynamicStateDescriptio * Set a state description for a channel. This description will be used when preparing the channel state by * the framework for presentation. A previous description, if existed, will be replaced. * - * @param channelUID channel UID + * @param channelUID channel UID * @param description state description for the channel */ void setDescription(ChannelUID channelUID, StateDescription description) { diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxServerHandler.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxServerHandler.java index 7c4928e28e745..f3237f84aca8f 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxServerHandler.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxServerHandler.java @@ -736,5 +736,4 @@ private String buildName(String name) { } return name; } - } diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxServerHandlerApi.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxServerHandlerApi.java index ddce35e2c10c3..eb985c066926c 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxServerHandlerApi.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/LxServerHandlerApi.java @@ -37,7 +37,7 @@ public interface LxServerHandlerApi { /** * Sends an action to a Loxone Miniserver's control. * - * @param id identifier of the control + * @param id identifier of the control * @param operation identifier of the operation * @throws IOException when communication error with Miniserver occurs */ @@ -65,7 +65,7 @@ public interface LxServerHandlerApi { * Sets channel's state to a new value * * @param channelId channel ID - * @param state new state value + * @param state new state value */ void setChannelState(ChannelUID channelId, State state); @@ -74,7 +74,7 @@ public interface LxServerHandlerApi { * interpreted and displayed. It is called when a dynamic state update is received from the Miniserver with a new * way of displaying control's state. * - * @param channelId channel ID + * @param channelId channel ID * @param description a new state description */ void setChannelStateDescription(ChannelUID channelId, StateDescription description); diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/controls/LxControl.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/controls/LxControl.java index da8d27c9b965c..777d11f8bba56 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/controls/LxControl.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/controls/LxControl.java @@ -736,5 +736,4 @@ private ChannelUID getChannelId(int index) { } return new ChannelUID(config.thingHandler.getThingId(), controlId); } - } diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/controls/LxControlJalousie.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/controls/LxControlJalousie.java index 50782ce9a24b1..42f0a1e76ac10 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/controls/LxControlJalousie.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/controls/LxControlJalousie.java @@ -226,7 +226,7 @@ public void onStateChange(LxState state) { * position. * * @param position end position to move jalousie to, floating point number from 0..1 (0-fully closed to 1-fully - * open) + * open) * @throws IOException when something went wrong with communication */ private void moveToPosition(Double position) throws IOException { diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurity.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurity.java index 35ca7be176bfd..642a8e233c8eb 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurity.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurity.java @@ -21,8 +21,6 @@ import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; -import org.apache.commons.codec.DecoderException; -import org.apache.commons.codec.binary.Hex; import org.eclipse.smarthome.core.util.HexUtils; import org.openhab.binding.loxone.internal.LxServerHandler; import org.openhab.binding.loxone.internal.LxServerHandlerApi; @@ -135,13 +133,13 @@ String hashString(String string, String hashKeyHex) { return null; } try { - byte[] hashKeyBytes = Hex.decodeHex(hashKeyHex.toCharArray()); + byte[] hashKeyBytes = HexUtils.hexToBytes(hashKeyHex); SecretKeySpec signKey = new SecretKeySpec(hashKeyBytes, "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(signKey); byte[] rawData = mac.doFinal(string.getBytes()); return HexUtils.bytesToHex(rawData); - } catch (DecoderException | NoSuchAlgorithmException | InvalidKeyException e) { + } catch (NoSuchAlgorithmException | InvalidKeyException e) { return null; } } @@ -217,5 +215,4 @@ public static LxWsSecurity create(LxWsSecurityType type, String swVersion, int d return new LxWsSecurityToken(debugId, thingHandler, socket, user, password); } } - } diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurityHash.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurityHash.java index a2483f474fcf3..4ed2ea6734223 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurityHash.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurityHash.java @@ -37,11 +37,11 @@ class LxWsSecurityHash extends LxWsSecurity { /** * Create a hash-based authentication instance. * - * @param debugId instance of the client used for debugging purposes only + * @param debugId instance of the client used for debugging purposes only * @param thingHandler API to the thing handler - * @param socket websocket to perform communication with Miniserver - * @param user user to authenticate - * @param password password to authenticate + * @param socket websocket to perform communication with Miniserver + * @param user user to authenticate + * @param password password to authenticate */ LxWsSecurityHash(int debugId, LxServerHandlerApi thingHandler, LxWebSocket socket, String user, String password) { super(debugId, thingHandler, socket, user, password); diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurityToken.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurityToken.java index c87ea275cebed..881ebf10010e3 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurityToken.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/security/LxWsSecurityToken.java @@ -407,7 +407,6 @@ private boolean acquireToken() { persistToken(); logger.debug("[{}] Token acquired.", debugId); return true; - } private boolean useToken() { diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxResponse.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxResponse.java index 07db405306860..595e7b15d47fb 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxResponse.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxResponse.java @@ -117,7 +117,7 @@ public String getValueAsString() { * Deserializes response value as a given type * * @param gson GSON object used for deserialization - * @param class to deserialize response to + * @param class to deserialize response to * @param type class type to deserialize response to * @return deserialized response */ diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxState.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxState.java index fd2fec2d81baa..2873de6c3015f 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxState.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxState.java @@ -39,8 +39,8 @@ public class LxState { /** * Create a control state object. * - * @param uuid UUID of the state - * @param name name of the state + * @param uuid UUID of the state + * @param name name of the state * @param control control to which this state belongs */ public LxState(LxUuid uuid, String name, LxControl control) { diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxTemperatureHSBType.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxTemperatureHSBType.java index 1360c63a8c58d..7af1e4839dd5b 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxTemperatureHSBType.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxTemperatureHSBType.java @@ -49,11 +49,11 @@ public static HSBType fromBrightnessTemperature(String value) { * Re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a value of * fromHigh to toHigh, values in-between to values in-between, etc. * - * @param x the number to map - * @param fromLow the lower bound of the value's current range + * @param x the number to map + * @param fromLow the lower bound of the value's current range * @param fromHigh the upper bound of the value's current range - * @param toLow the lower bound of the value's target range - * @param toHigh the upper bound of the value's target range + * @param toLow the lower bound of the value's target range + * @param toHigh the upper bound of the value's target range * @return the mapped value */ private static int map(int x, int fromLow, int fromHigh, int toLow, int toHigh) { @@ -124,7 +124,7 @@ private static int calculateBlue(int temp) { /** * Constrains a number to be within a range. * - * @param x the number to constrain + * @param x the number to constrain * @param min the minimum value * @param max the maximum value * @return the constrained value @@ -138,5 +138,4 @@ private static int constrain(int x, int min, int max) { return max; } } - } diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxWsBinaryHeader.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxWsBinaryHeader.java index c8af7b3c7adbc..6e7135a3b55aa 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxWsBinaryHeader.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxWsBinaryHeader.java @@ -26,33 +26,33 @@ public class LxWsBinaryHeader { * */ public enum LxWsMessageType { - /** - * Text message - jetty websocket client will pass it on automatically to a callback - */ - TEXT_MESSAGE, - /** - * Binary file - */ - BINARY_FILE, - /** - * A set of value states for controls that changed their state - */ - EVENT_TABLE_OF_VALUE_STATES, - /** - * A set of text states for controls that changed their state - */ - EVENT_TABLE_OF_TEXT_STATES, - EVENT_TABLE_OF_DAYTIMER_STATES, - OUT_OF_SERVICE_INDICATOR, - /** - * Response to keepalive request message - */ - KEEPALIVE_RESPONSE, - EVENT_TABLE_OF_WEATHER_STATES, - /** - * Unknown header - */ - UNKNOWN + /** + * Text message - jetty websocket client will pass it on automatically to a callback + */ + TEXT_MESSAGE, + /** + * Binary file + */ + BINARY_FILE, + /** + * A set of value states for controls that changed their state + */ + EVENT_TABLE_OF_VALUE_STATES, + /** + * A set of text states for controls that changed their state + */ + EVENT_TABLE_OF_TEXT_STATES, + EVENT_TABLE_OF_DAYTIMER_STATES, + OUT_OF_SERVICE_INDICATOR, + /** + * Response to keepalive request message + */ + KEEPALIVE_RESPONSE, + EVENT_TABLE_OF_WEATHER_STATES, + /** + * Unknown header + */ + UNKNOWN } private LxWsMessageType type = LxWsMessageType.UNKNOWN; diff --git a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxWsSecurityType.java b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxWsSecurityType.java index 08debdd4b7786..d134cfd796bc1 100644 --- a/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxWsSecurityType.java +++ b/bundles/org.openhab.binding.loxone/src/main/java/org/openhab/binding/loxone/internal/types/LxWsSecurityType.java @@ -31,11 +31,12 @@ public enum LxWsSecurityType { * Token-based authentication with AES-256 command encryption */ TOKEN; + /** * Encode security type based on index * * @param index - * 0 for auto, 1 for hash, 2 for token + * 0 for auto, 1 for hash, 2 for token * @return * security type fo given index */ diff --git a/bundles/org.openhab.binding.loxone/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.loxone/src/main/resources/ESH-INF/thing/thing-types.xml index 47f1c4df36982..52ef9ccf6c210 100644 --- a/bundles/org.openhab.binding.loxone/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.loxone/src/main/resources/ESH-INF/thing/thing-types.xml @@ -62,7 +62,8 @@ password - User password on the Loxone Miniserver. In token-based authentication this password will be cleared after token is acquired. + User password on the Loxone Miniserver. In token-based authentication this password will be cleared + after token is acquired. @@ -92,12 +93,14 @@ - Time in seconds between user login error as a result of wrong name/password or no authority and next connection attempt (seconds, 0-3600) + Time in seconds between user login error as a result of wrong name/password or no authority and next + connection attempt (seconds, 0-3600) 60 - Time between connection close (as a result of some communication error) and next connection attempt (seconds, 0-3600) + Time between connection close (as a result of some communication error) and next connection attempt + (seconds, 0-3600) 30 @@ -124,7 +127,7 @@ Switch Loxone's digital information controls (InfoOnlyDigital, read-only). - + @@ -137,7 +140,7 @@ String Loxone's state information controls (TextState, read-only). - + @@ -150,14 +153,14 @@ Number Loxone's time counter (TimedSwitch, read-only). - + Number Loxone's state information controls (InfoOnlyAnalog, read-only). - + @@ -184,7 +187,7 @@ Number Loxone's radio button controls (Radio). - + @@ -253,8 +256,7 @@ Number Loxone Intelligent Room Controller V2 Comfort Tolerance. - + - diff --git a/bundles/org.openhab.binding.loxone/src/test/java/org/openhab/binding/loxone/internal/controls/LxServerHandlerDummy.java b/bundles/org.openhab.binding.loxone/src/test/java/org/openhab/binding/loxone/internal/controls/LxServerHandlerDummy.java index 04c74a58bbc36..d3644acfdaeeb 100644 --- a/bundles/org.openhab.binding.loxone/src/test/java/org/openhab/binding/loxone/internal/controls/LxServerHandlerDummy.java +++ b/bundles/org.openhab.binding.loxone/src/test/java/org/openhab/binding/loxone/internal/controls/LxServerHandlerDummy.java @@ -97,7 +97,6 @@ public void removeControl(LxControl control) { @Override public void setChannelState(ChannelUID channelId, State state) { // TODO Auto-generated method stub - } @Override @@ -116,7 +115,6 @@ public String getSetting(String name) { @Override public void setSettings(Map properties) { // TODO Auto-generated method stub - } @Override diff --git a/bundles/org.openhab.binding.lutron/README.md b/bundles/org.openhab.binding.lutron/README.md index b412881bd7c1c..4b600f86e477d 100644 --- a/bundles/org.openhab.binding.lutron/README.md +++ b/bundles/org.openhab.binding.lutron/README.md @@ -34,7 +34,7 @@ This binding currently supports the following thing types: * **palladiomkeypad** - Palladiom Keypad (HomeWorks QS only) * **pico** - Pico Keypad * **grafikeyekeypad** - GRAFIK Eye QS Keypad (RadioRA 2/HomeWorks QS only) -* **virtualkeypad** - Repeater virtual keypad +* **virtualkeypad** - Repeater/processor integration buttons or Caseta Smart Bridge scene buttons * **vcrx** - Visor control receiver module (VCRX) * **qsio** - QS IO Interface (HomeWorks QS only) * **wci** - QS Wallbox Closure Interface (WCI) (HomeWorks QS only) @@ -126,7 +126,7 @@ Thing switch porch [ integrationId=8 ] ### Occupancy Sensors An **occupancysensor** thing interfaces to Lutron Radio Powr Savr wireless occupancy/vacancy sensors. -It accepts no configuration parameters other than `integrationID`. +It accepts no configuration parameters other than `integrationId`. The binding creates one *occupancystatus* channel, Item type Switch, category Motion. It is read-only, and ignores all commands. @@ -142,7 +142,7 @@ Thing occupancysensor shopsensor [ integrationId=7 ] ### seeTouch and Hybrid seeTouch Keypads seeTouch and Hybrid seeTouch keypads are interfaced with using the **keypad** thing. -In addition to the usual `integrationID` parameter, it accepts `model` and `autorelease` parameters. +In addition to the usual `integrationId` parameter, it accepts `model` and `autorelease` parameters. The `model` parameter should be set to the Lutron keypad model number. This will cause the handler to create only the appropriate channels for that particular keypad model. The default is "Generic", which will cause the handler to create all possible channels, some of which will likely not be appropriate for your model. @@ -191,7 +191,7 @@ end ### Tabletop seeTouch Keypads Tabletop seeTouch keypads use the **ttkeypad** thing. -It accepts the same `integrationID`, `model`, and `autorelease` parameters and creates the same channel types as the **keypad** thing. +It accepts the same `integrationId`, `model`, and `autorelease` parameters and creates the same channel types as the **keypad** thing. See the **keypad** section above for a full discussion of configuration and use. Component numbering: For button and LED layouts and numbering, see the Lutron Integration Protocol Guide (rev. AA) p.110 (https://www.lutron.com/TechnicalDocumentLibrary/040249.pdf). @@ -208,7 +208,7 @@ Thing ttkeypad bedroomkeypad [ integrationId=11, model="T10RL" autorelease=true ### International seeTouch Keypads (HomeWorks QS) International seeTouch keypads used in the HomeWorks QS system use the **intlkeypad** thing. -It accepts the same `integrationID`, `model`, and `autorelease` parameters and creates the same button and LED channel types as the **keypad** thing. +It accepts the same `integrationId`, `model`, and `autorelease` parameters and creates the same button and LED channel types as the **keypad** thing. See the **keypad** section above for a full discussion of configuration and use. To support this keypad's contact closure inputs, CCI channels named *cci1* and *cci2* are created with item type Contact and category Switch. @@ -229,7 +229,7 @@ Thing intlkeypad kitchenkeypad [ integrationId=15, model="10BRL" autorelease=tru ### Palladiom Keypads (HomeWorks QS) Palladiom keypads used in the HomeWorks QS system use the **palladiomkeypad** thing. -It accepts the same `integrationID`, `model`, and `autorelease` parameters and creates the same button and LED channel types as the **keypad** thing. +It accepts the same `integrationId`, `model`, and `autorelease` parameters and creates the same button and LED channel types as the **keypad** thing. See the **keypad** section above for a full discussion of configuration and use. Component numbering: For button and LED layouts and numbering, see the Lutron Integration Protocol Guide (rev. AA) p.95 (https://www.lutron.com/TechnicalDocumentLibrary/040249.pdf). @@ -247,7 +247,7 @@ Thing palladiomkeypad kitchenkeypad [ integrationId=16, model="4W" autorelease=t ### Pico Keypads Pico keypads use the **pico** thing. -It accepts the same `integrationID`, `model`, and `autorelease` parameters and creates the same channel types as the **keypad** and **ttkeypad** things. +It accepts the same `integrationId`, `model`, and `autorelease` parameters and creates the same channel types as the **keypad** and **ttkeypad** things. The only difference is that no LED channels will be created, since Pico keypads have no indicator LEDs. See the discussion above for a full discussion of configuration and use. @@ -272,7 +272,7 @@ In this configuration, the integrated dimmers will appear to openHAB as separate If your GRAFIK Eye is being used as a stand-alone device and is not integrated in to a RadioRA 2 or HomeWorks QS system, then *this is not the thing you are looking for*. You should instead be using the **grafikeye** thing (see below). -The **grafikeyekeypad** thing accepts the same `integrationID`, `model`, and `autorelease` parameters and creates the same button, LED, and CCI, channel types as the other keypad things (see above). +The **grafikeyekeypad** thing accepts the same `integrationId`, `model`, and `autorelease` parameters and creates the same button, LED, and CCI, channel types as the other keypad things (see above). The model parameter should be set to indicate whether there are zero, one, two, or three columns of buttons on the left side of the panel. Note that this count does not include the column of 5 scene buttons always found on the right side of the panel. @@ -293,13 +293,22 @@ Thing lutron:grafikeyekeypad:theaterkeypad (lutron:ipbridge:radiora2) [ integrat ### Virtual Keypads -The **virtualkeypad** thing is used to interface to the virtual buttons on the RadioRA 2 main repeater. +The **virtualkeypad** thing is used to interface to the virtual buttons on the RadioRA 2 main repeater or HomeWorks processor. These are sometimes referred to in the Lutron documentation as phantom buttons or integration buttons, and are used only for integration. There are 100 of these virtual buttons, and 100 corresponding virtual indicator LEDs. +The **virtualkeypad** thing can also be used to interface to the Smart Bridge scene buttons on Caseta systems. +This allows you to trigger your defined scenes via the virtual keypad buttons. +For this to work, the optional `model` parameter must be set to `Caseta`. +When used with Caseta, no virtual indicator LED channels are created. + The behavior of this binding is the same as the other keypad bindings, with the exception that the button and LED channels created have the Advanced flag set. This means, among other things, that they will not be automatically linked to items in the Paper UI's Simple Mode. +In most cases the integrationId parameter should be set to 1. + +Supported settings for `model` parameter: Caseta, Other (default) + Thing configuration file example: ``` diff --git a/bundles/org.openhab.binding.lutron/pom.xml b/bundles/org.openhab.binding.lutron/pom.xml index bd7f47cc67414..49e12db5f1836 100644 --- a/bundles/org.openhab.binding.lutron/pom.xml +++ b/bundles/org.openhab.binding.lutron/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.lutron diff --git a/bundles/org.openhab.binding.lutron/src/main/feature/feature.xml b/bundles/org.openhab.binding.lutron/src/main/feature/feature.xml index 54f387eaac281..22b267a7e26c4 100644 --- a/bundles/org.openhab.binding.lutron/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.lutron/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.lutron/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.lutron/${project.version} + diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/LutronHandlerFactory.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/LutronHandlerFactory.java index e08c375221600..acd686b67e5ef 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/LutronHandlerFactory.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/LutronHandlerFactory.java @@ -33,6 +33,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.eclipse.smarthome.io.net.http.HttpClientFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.lutron.internal.discovery.LutronDeviceDiscoveryService; import org.openhab.binding.lutron.internal.grxprg.GrafikEyeHandler; import org.openhab.binding.lutron.internal.grxprg.PrgBridgeHandler; @@ -65,6 +66,7 @@ import org.openhab.binding.lutron.internal.radiora.handler.PhantomButtonHandler; import org.openhab.binding.lutron.internal.radiora.handler.RS232Handler; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; @@ -103,9 +105,17 @@ public class LutronHandlerFactory extends BaseThingHandlerFactory { private final Logger logger = LoggerFactory.getLogger(LutronHandlerFactory.class); + private final SerialPortManager serialPortManager; + private @NonNullByDefault({}) HttpClient httpClient; // shared instance obtained from HttpClientFactory service and passed to device discovery service + @Activate + public LutronHandlerFactory(final @Reference SerialPortManager serialPortManager) { + // Obtain the serial port manager service using an OSGi reference + this.serialPortManager = serialPortManager; + } + @Reference protected void setHttpClientFactory(HttpClientFactory httpClientFactory) { this.httpClient = httpClientFactory.getCommonHttpClient(); @@ -180,7 +190,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } else if (thingTypeUID.equals(PrgConstants.THING_TYPE_GRAFIKEYE)) { return new GrafikEyeHandler(thing); } else if (thingTypeUID.equals(RadioRAConstants.THING_TYPE_RS232)) { - return new RS232Handler((Bridge) thing); + return new RS232Handler((Bridge) thing, serialPortManager); } else if (thingTypeUID.equals(RadioRAConstants.THING_TYPE_DIMMER)) { return new org.openhab.binding.lutron.internal.radiora.handler.DimmerHandler(thing); } else if (thingTypeUID.equals(RadioRAConstants.THING_TYPE_SWITCH)) { @@ -188,7 +198,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } else if (thingTypeUID.equals(RadioRAConstants.THING_TYPE_PHANTOM)) { return new PhantomButtonHandler(thing); } else if (thingTypeUID.equals(HwConstants.THING_TYPE_HWSERIALBRIDGE)) { - return new HwSerialBridgeHandler((Bridge) thing); + return new HwSerialBridgeHandler((Bridge) thing, serialPortManager); } else if (thingTypeUID.equals(HwConstants.THING_TYPE_HWDIMMER)) { return new HwDimmerHandler(thing); } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/LutronDeviceDiscoveryService.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/LutronDeviceDiscoveryService.java index acd3783e5ee61..c199a07d3b83a 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/LutronDeviceDiscoveryService.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/LutronDeviceDiscoveryService.java @@ -391,6 +391,7 @@ private void processOutput(Output output, Stack context) { case NON_DIM: case NON_DIM_INC: case NON_DIM_ELV: + case RELAY_LIGHTING: notifyDiscovery(THING_TYPE_SWITCH, output.getIntegrationId(), label); break; diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/LutronMdnsBridgeDiscoveryService.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/LutronMdnsBridgeDiscoveryService.java index cd97445587551..bd32656db04ff 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/LutronMdnsBridgeDiscoveryService.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/LutronMdnsBridgeDiscoveryService.java @@ -56,6 +56,7 @@ public class LutronMdnsBridgeDiscoveryService implements MDNSDiscoveryParticipan private static final String PRODFAM_RA2_SELECT = "RA2 Select"; private static final String PRODTYP_RA2_SELECT = "Main Repeater"; private static final String DEVCLASS_RA2_SELECT = "080E0401"; + private static final String DEVCLASS_CONNECT_BRIDGE = "08090301"; private static final String DEFAULT_LABEL = "Unknown Lutron bridge"; private static final Pattern HOSTNAME_REGEX = Pattern.compile("lutron-([0-9a-f]+)\\."); // ex: lutron-01f1529a.local @@ -107,14 +108,17 @@ public String getServiceType() { String bridgeHostName = ipAddresses[0].getHostName(); logger.debug("Lutron mDNS bridge hostname: {}", bridgeHostName); - if (devclass != null && devclass.equals(DEVCLASS_CASETA_SBP2)) { + if (DEVCLASS_CASETA_SBP2.equals(devclass)) { properties.put(PROPERTY_PRODFAM, PRODFAM_CASETA); properties.put(PROPERTY_PRODTYP, PRODTYP_CASETA_SBP2); label = PRODFAM_CASETA + " " + PRODTYP_CASETA_SBP2; - } else if (devclass != null && devclass.equals(DEVCLASS_RA2_SELECT)) { + } else if (DEVCLASS_RA2_SELECT.equals(devclass)) { properties.put(PROPERTY_PRODFAM, PRODFAM_RA2_SELECT); properties.put(PROPERTY_PRODTYP, PRODTYP_RA2_SELECT); label = PRODFAM_RA2_SELECT + " " + PRODTYP_RA2_SELECT; + } else if (DEVCLASS_CONNECT_BRIDGE.equals(devclass)) { + logger.debug("Lutron Connect Bridge discovered. Ignoring."); + return null; } else { logger.info("Lutron device with unknown DEVCLASS discovered via mDNS: {}. Configure device manually.", devclass); diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/GreenMode.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/GreenMode.java index 30c8eea2ea431..eb8d75ac0c18b 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/GreenMode.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/GreenMode.java @@ -30,5 +30,4 @@ public String getName() { public Integer getIntegrationId() { return integrationId; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/OutputType.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/OutputType.java index 499a84d81881f..c5bf3a4f507a3 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/OutputType.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/OutputType.java @@ -33,6 +33,7 @@ public enum OutputType { NON_DIM, NON_DIM_ELV, NON_DIM_INC, + RELAY_LIGHTING, SHEER_BLIND, SYSTEM_SHADE, VENETIAN_BLIND, diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/Project.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/Project.java index a297e3bfde2ec..a059ea85c7132 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/Project.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/Project.java @@ -48,5 +48,4 @@ public List getTimeclocks() { public List getGreenModes() { return greenmodes != null ? greenmodes : Collections. emptyList(); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/Timeclock.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/Timeclock.java index 151f70f750b05..f96fa2314822e 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/Timeclock.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/discovery/project/Timeclock.java @@ -29,5 +29,4 @@ public String getName() { public Integer getIntegrationId() { return integrationId; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/GrafikEyeConfig.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/GrafikEyeConfig.java index c4b52bc42dc2d..6dc8bac86b673 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/GrafikEyeConfig.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/GrafikEyeConfig.java @@ -175,5 +175,4 @@ public int getPolling() { public void setPolling(int polling) { this.polling = polling; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/GrafikEyeHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/GrafikEyeHandler.java index 0f77ded220952..bf2b41239717d 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/GrafikEyeHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/GrafikEyeHandler.java @@ -222,7 +222,7 @@ private void handleRefresh(String id) { /** * Gets the trailing number from the channel id (which usually represents the zone number). * - * @param id a non-null, possibly empty channel id + * @param id a non-null, possibly empty channel id * @param channelConstant a non-null, non-empty channel id constant to use in the parse. * @return the trailing number or null if a parse exception occurs */ @@ -311,7 +311,6 @@ public void run() { if (status == ThingStatus.ONLINE && _config != null) { getProtocolHandler().refreshState(_config.getControlUnit()); } - } }, 1, _config.getPolling(), TimeUnit.SECONDS); } @@ -368,7 +367,7 @@ boolean isShade(int zone) { * Helper method to expose the ability to change state outside of the class * * @param channelId the channel id - * @param state the new state + * @param state the new state */ void stateChanged(String channelId, State state) { updateState(channelId, state); diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgBridgeHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgBridgeHandler.java index 3ef13701beea7..c8bec6438b295 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgBridgeHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgBridgeHandler.java @@ -253,7 +253,6 @@ public void initialize() { public void run() { connect(); } - }, 1, TimeUnit.SECONDS); } @@ -318,7 +317,6 @@ public void run() { _retryConnection = null; connect(); } - }, config.getRetryPolling(), TimeUnit.SECONDS); } } else { diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgHandlerCallback.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgHandlerCallback.java index 25d6208f4422e..ff420335c33b8 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgHandlerCallback.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgHandlerCallback.java @@ -31,7 +31,7 @@ interface PrgHandlerCallback { * * @param status a non-null {@link org.eclipse.smarthome.core.thing.ThingStatus} * @param detail a non-null {@link org.eclipse.smarthome.core.thing.ThingStatusDetail} - * @param msg a possibly null, possibly empty message + * @param msg a possibly null, possibly empty message */ void statusChanged(ThingStatus status, ThingStatusDetail detail, String msg); @@ -39,7 +39,7 @@ interface PrgHandlerCallback { * Callback to the {@link PrgBridgeHandler} to update the state of an item * * @param channelId the non-null, non-empty channel id - * @param state the new non-null {@State} + * @param state the new non-null {@State} */ void stateChanged(String channelId, State state); @@ -47,8 +47,8 @@ interface PrgHandlerCallback { * Callback to the {@link PrgBridgeHandler} to update the state of an item in a specific {@link GrafikEyeHandler}. * * @param controlUnit the control unit identifier to update - * @param channelId the non-null, non-empty channel id - * @param state the new non-null {@State} + * @param channelId the non-null, non-empty channel id + * @param state the new non-null {@State} */ void stateChanged(int controlUnit, String channelId, State state); @@ -57,7 +57,7 @@ interface PrgHandlerCallback { * or not * * @param controlUnit the control unit identifier - * @param zone the zone identify + * @param zone the zone identify * @return true if a shade zone, false otherwise */ boolean isShade(int controlUnit, int zone); diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgProtocolHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgProtocolHandler.java index 45cf23ccd2baf..a1485fdc23120 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgProtocolHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/grxprg/PrgProtocolHandler.java @@ -377,7 +377,6 @@ private void validateZone(int zone) { if (zone < 1 || zone > 8) { throw new IllegalArgumentException("Invalid zone (must be between 1 and 8): " + zone); } - } /** @@ -1168,7 +1167,6 @@ public void responseException(Exception exception) { _callback.statusChanged(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Exception occurred reading from PRG: " + exception); } - } /** @@ -1220,6 +1218,5 @@ public void responseException(Exception e) { } catch (InterruptedException e1) { } } - } } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/BaseKeypadHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/BaseKeypadHandler.java index bd44664c79680..80152256442ff 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/BaseKeypadHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/BaseKeypadHandler.java @@ -402,5 +402,4 @@ public void handleUpdate(LutronCommandType type, String... parameters) { } } } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/CcoHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/CcoHandler.java index dca2a8cbba444..26b0bfbc9c2ae 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/CcoHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/CcoHandler.java @@ -206,5 +206,4 @@ public void handleUpdate(LutronCommandType type, String... parameters) { } } } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/GrafikEyeKeypadHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/GrafikEyeKeypadHandler.java index 505a50f589bd3..fa067ba8978cf 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/GrafikEyeKeypadHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/GrafikEyeKeypadHandler.java @@ -61,5 +61,4 @@ public GrafikEyeKeypadHandler(Thing thing) { super(thing); kp = new KeypadConfigGrafikEye(); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/IntlKeypadHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/IntlKeypadHandler.java index 16bfe6de1e12c..2edf6a7441726 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/IntlKeypadHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/IntlKeypadHandler.java @@ -64,5 +64,4 @@ public IntlKeypadHandler(Thing thing) { super(thing); kp = new KeypadConfigIntlSeetouch(); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/KeypadHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/KeypadHandler.java index 37d112542149d..14b0d153ce66b 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/KeypadHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/KeypadHandler.java @@ -107,5 +107,4 @@ public KeypadHandler(Thing thing) { super(thing); kp = new KeypadConfigSeetouch(); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/LutronHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/LutronHandler.java index b6240738e77f6..c4dc311ef0b1d 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/LutronHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/LutronHandler.java @@ -124,5 +124,4 @@ protected void queryTimeclock(Object... parameters) { protected void queryGreenMode(Object... parameters) { sendCommand(new LutronCommand(LutronOperation.QUERY, LutronCommandType.MODE, getIntegrationId(), parameters)); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/MaintainedCcoHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/MaintainedCcoHandler.java index 58bd7e7c3220b..659dc679ab3bb 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/MaintainedCcoHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/MaintainedCcoHandler.java @@ -27,5 +27,4 @@ public MaintainedCcoHandler(Thing thing) { super(thing); this.outputType = CcoOutputType.MAINTAINED; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/OccupancySensorHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/OccupancySensorHandler.java index 3d57c588c5b25..38df645c5ddd4 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/OccupancySensorHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/OccupancySensorHandler.java @@ -90,5 +90,4 @@ public void handleUpdate(LutronCommandType type, String... parameters) { } } } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PalladiomKeypadHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PalladiomKeypadHandler.java index 082f6951affc6..37455e0ad2efa 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PalladiomKeypadHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PalladiomKeypadHandler.java @@ -67,5 +67,4 @@ public PalladiomKeypadHandler(Thing thing) { super(thing); kp = new KeypadConfigPalladiom(); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PicoKeypadHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PicoKeypadHandler.java index b32787ee8ef94..15869558f4393 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PicoKeypadHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PicoKeypadHandler.java @@ -56,5 +56,4 @@ protected void configureComponents(@Nullable String model) { break; } } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PulsedCcoHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PulsedCcoHandler.java index a0954467063e2..2a4ab1b3a06c9 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PulsedCcoHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/PulsedCcoHandler.java @@ -27,5 +27,4 @@ public PulsedCcoHandler(Thing thing) { super(thing); this.outputType = CcoOutputType.PULSED; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/QSIOHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/QSIOHandler.java index d879cb0aef41a..40510db1586b2 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/QSIOHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/QSIOHandler.java @@ -97,5 +97,4 @@ protected void configureComponents(@Nullable String model) { public QSIOHandler(Thing thing) { super(thing); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/TabletopKeypadHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/TabletopKeypadHandler.java index c4d15e2f45ed6..dc4ffdb945ef2 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/TabletopKeypadHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/TabletopKeypadHandler.java @@ -61,5 +61,4 @@ public TabletopKeypadHandler(Thing thing) { super(thing); kp = new KeypadConfigTabletopSeetouch(); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/TimeclockHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/TimeclockHandler.java index d78afeb458398..598e127b89c53 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/TimeclockHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/TimeclockHandler.java @@ -207,5 +207,4 @@ public void handleUpdate(LutronCommandType type, String... parameters) { return; } } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/VcrxHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/VcrxHandler.java index 08c8d2834e2bf..dadc4b29a5710 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/VcrxHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/VcrxHandler.java @@ -122,5 +122,4 @@ protected void configureComponents(@Nullable String model) { public VcrxHandler(Thing thing) { super(thing); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/VirtualKeypadHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/VirtualKeypadHandler.java index 56bf19d0f2025..ce7d08883d5c3 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/VirtualKeypadHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/VirtualKeypadHandler.java @@ -28,6 +28,9 @@ @NonNullByDefault public class VirtualKeypadHandler extends BaseKeypadHandler { + private static final String MODEL_OPTION_CASETA = "Caseta"; + private static final String MODEL_OPTION_OTHER = "Other"; + private class Component implements KeypadComponent { private final int id; private final String channel; @@ -81,11 +84,15 @@ protected boolean isCCI(int id) { @Override protected void configureComponents(@Nullable String model) { - logger.debug("Configuring components for virtual keypad"); + String mod = model == null ? MODEL_OPTION_OTHER : model; + logger.debug("Configuring components for virtual keypad for model {}", mod); + boolean caseta = mod.equalsIgnoreCase(MODEL_OPTION_CASETA); for (int x = 1; x <= 100; x++) { buttonList.add(new Component(x, String.format("button%d", x), "Virtual Button", ComponentType.BUTTON)); - ledList.add(new Component(x + 100, String.format("led%d", x), "Virtual LED", ComponentType.LED)); + if (!caseta) { // Caseta scene buttons have no virtual LEDs + ledList.add(new Component(x + 100, String.format("led%d", x), "Virtual LED", ComponentType.LED)); + } } } @@ -94,5 +101,4 @@ public VirtualKeypadHandler(Thing thing) { // Mark all channels "Advanced" since most are unlikely to be used in any particular config advancedChannels = true; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/WciHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/WciHandler.java index 555246d8ff42e..348b720d1c1a8 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/WciHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/handler/WciHandler.java @@ -118,5 +118,4 @@ protected void configureComponents(@Nullable String model) { public WciHandler(Thing thing) { super(thing); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/hw/HwSerialBridgeHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/hw/HwSerialBridgeHandler.java index dd887747c034a..338a403953a2f 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/hw/HwSerialBridgeHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/hw/HwSerialBridgeHandler.java @@ -32,17 +32,16 @@ import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * * This is the main handler for HomeWorks RS232 Processors. @@ -62,12 +61,14 @@ public class HwSerialBridgeHandler extends BaseBridgeHandler implements SerialPo private HwDiscoveryService discoveryService; + private final SerialPortManager serialPortManager; private SerialPort serialPort; private OutputStreamWriter serialOutput; private BufferedReader serialInput; - public HwSerialBridgeHandler(Bridge bridge) { + public HwSerialBridgeHandler(Bridge bridge, SerialPortManager serialPortManager) { super(bridge); + this.serialPortManager = serialPortManager; } @Override @@ -99,9 +100,14 @@ public void setDiscoveryService(HwDiscoveryService discoveryService) { } private void openConnection() { + SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(serialPortName); + if (portIdentifier == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Invalid port: " + serialPortName); + return; + } + try { logger.info("Connecting to Lutron HomeWorks Processor using {}.", serialPortName); - CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName); serialPort = portIdentifier.open(this.getClass().getName(), 2000); logger.debug("Connection established using {}. Configuring IO parameters. ", serialPortName); @@ -128,9 +134,6 @@ private void openConnection() { if (updateTime) { startUpdateProcessorTimeJob(); } - - } catch (NoSuchPortException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Invalid port: " + serialPortName); } catch (PortInUseException portInUseException) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Port in use: " + serialPortName); } catch (UnsupportedCommOperationException | IOException e) { @@ -201,7 +204,6 @@ private void handleIncomingMessage(String line) { logger.error("Error parsing incoming message", e); } } - } private HwDimmerHandler findHandler(String address) { @@ -267,5 +269,4 @@ public void dispose() { logger.debug("Finished disposing bridge."); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/keypadconfig/KeypadConfigGrafikEye.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/keypadconfig/KeypadConfigGrafikEye.java index 50f1e23826e70..c6bb0c4cb09b4 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/keypadconfig/KeypadConfigGrafikEye.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/keypadconfig/KeypadConfigGrafikEye.java @@ -153,5 +153,4 @@ public KeypadConfigGrafikEye() { modelData.put("3COL", combinedList(SCENE_BUTTON_GROUP, COL1_BUTTON_GROUP, COL2_BUTTON_GROUP, COL3_BUTTON_GROUP, CCI_GROUP, SCENE_LED_GROUP, COL1_LED_GROUP, COL2_LED_GROUP, COL3_LED_GROUP)); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/keypadconfig/KeypadConfigTabletopSeetouch.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/keypadconfig/KeypadConfigTabletopSeetouch.java index 673d751966d5d..52538331fda97 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/keypadconfig/KeypadConfigTabletopSeetouch.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/keypadconfig/KeypadConfigTabletopSeetouch.java @@ -164,5 +164,4 @@ public KeypadConfigTabletopSeetouch() { modelData.put("Generic", combinedList(BUTTONGROUP1, BUTTONGROUP2, BUTTONGROUP3, BUTTONGROUPBOTTOM_GENERIC, LEDGROUP1, LEDGROUP2, LEDGROUP3, LEDGROUPBOTTOM_RL)); // Superset of all models } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RS232Connection.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RS232Connection.java index 588892ff75662..a4f135351e240 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RS232Connection.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RS232Connection.java @@ -15,23 +15,19 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.List; import java.util.TooManyListenersException; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.lutron.internal.radiora.protocol.RadioRAFeedback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * RS232 connection to the RadioRA Classic system. * @@ -42,6 +38,7 @@ public class RS232Connection implements RadioRAConnection, SerialPortEventListen private final Logger logger = LoggerFactory.getLogger(RS232Connection.class); + protected SerialPortManager serialPortManager; protected SerialPort serialPort; protected BufferedReader inputReader; @@ -49,25 +46,26 @@ public class RS232Connection implements RadioRAConnection, SerialPortEventListen protected RadioRAFeedbackListener listener; protected RS232MessageParser parser = new RS232MessageParser(); + public RS232Connection(SerialPortManager serialPortManager) { + super(); + this.serialPortManager = serialPortManager; + } + @Override public void open(String portName, int baud) throws RadioRAConnectionException { - CommPortIdentifier commPort = null; - - try { - commPort = CommPortIdentifier.getPortIdentifier(portName); - } catch (NoSuchPortException e) { - logAvailablePorts(); + SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(portName); + if (portIdentifier == null) { throw new RadioRAConnectionException(String.format("Port not found", portName)); } try { - serialPort = commPort.open("openhab", 5000); + serialPort = portIdentifier.open("openhab", 5000); serialPort.notifyOnDataAvailable(true); serialPort.setSerialPortParams(baud, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); serialPort.addEventListener(this); inputReader = new BufferedReader(new InputStreamReader(serialPort.getInputStream())); } catch (PortInUseException e) { - throw new RadioRAConnectionException(String.format("Port %s already in use", commPort.getName())); + throw new RadioRAConnectionException(String.format("Port %s already in use", portIdentifier.getName())); } catch (UnsupportedCommOperationException e) { throw new RadioRAConnectionException("Error initializing - Failed to set serial port params"); } catch (TooManyListenersException e) { @@ -92,28 +90,6 @@ public void disconnect() { serialPort.close(); } - private void logAvailablePorts() { - if (logger.isDebugEnabled()) { - logger.debug("Available ports:"); - for (CommPortIdentifier port : getAvailableSerialPorts()) { - logger.debug("{}", port.getName()); - } - } - } - - protected List getAvailableSerialPorts() { - List ports = new ArrayList<>(); - Enumeration portIds = CommPortIdentifier.getPortIdentifiers(); - while (portIds.hasMoreElements()) { - CommPortIdentifier id = (CommPortIdentifier) portIds.nextElement(); - if (CommPortIdentifier.PORT_SERIAL == id.getPortType()) { - ports.add(id); - } - } - - return ports; - } - @Override public void serialEvent(SerialPortEvent ev) { switch (ev.getEventType()) { @@ -147,5 +123,4 @@ public void serialEvent(SerialPortEvent ev) { public void setListener(RadioRAFeedbackListener listener) { this.listener = listener; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RS232MessageParser.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RS232MessageParser.java index 30b6abd27e899..b43cc24755bed 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RS232MessageParser.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RS232MessageParser.java @@ -61,5 +61,4 @@ protected String parsePrefix(String msg) { return arr[0]; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConnection.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConnection.java index 99c98e2d8ecdd..db769edcabd24 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConnection.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConnection.java @@ -27,5 +27,4 @@ public interface RadioRAConnection { public void write(String command); public void setListener(RadioRAFeedbackListener listener); - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConnectionException.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConnectionException.java index b54b435319fde..2211ce326ea01 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConnectionException.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConnectionException.java @@ -25,5 +25,4 @@ public class RadioRAConnectionException extends Exception { public RadioRAConnectionException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConstants.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConstants.java index 86523234d1482..695b62737543b 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConstants.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAConstants.java @@ -32,5 +32,4 @@ public class RadioRAConstants { "ra-switch"); public static final ThingTypeUID THING_TYPE_PHANTOM = new ThingTypeUID(LutronBindingConstants.BINDING_ID, "ra-phantomButton"); - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAFeedbackListener.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAFeedbackListener.java index 2e30348d0b6fd..9019756e25606 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAFeedbackListener.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/RadioRAFeedbackListener.java @@ -23,5 +23,4 @@ public interface RadioRAFeedbackListener { void handleRadioRAFeedback(RadioRAFeedback feedback); - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/DimmerConfig.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/DimmerConfig.java index 8b7c5c8f64331..4acf553982067 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/DimmerConfig.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/DimmerConfig.java @@ -48,5 +48,4 @@ public BigDecimal getFadeInSec() { public void setFadeInSec(BigDecimal fadeInSec) { this.fadeInSec = fadeInSec; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/PhantomButtonConfig.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/PhantomButtonConfig.java index 3341c63d3507c..51734bf1eaa13 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/PhantomButtonConfig.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/PhantomButtonConfig.java @@ -40,5 +40,4 @@ public BigDecimal getFadeSec() { public void setFadeSec(BigDecimal fadeSec) { this.fadeSec = fadeSec; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/RS232Config.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/RS232Config.java index acdd990afb5d4..c647c1a13e76f 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/RS232Config.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/RS232Config.java @@ -47,5 +47,4 @@ public int getZoneMapQueryInterval() { public void setZoneMapQueryInterval(int zoneMapQueryInterval) { this.zoneMapQueryInterval = zoneMapQueryInterval; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/SwitchConfig.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/SwitchConfig.java index e548f47d86baa..b58dc02064edb 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/SwitchConfig.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/config/SwitchConfig.java @@ -29,5 +29,4 @@ public int getZoneNumber() { public void setZoneNumber(int zoneNumber) { this.zoneNumber = zoneNumber; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/PhantomButtonHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/PhantomButtonHandler.java index 0eb4c3f9a2748..2fd9a48247a7b 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/PhantomButtonHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/PhantomButtonHandler.java @@ -51,7 +51,6 @@ public void handleFeedback(RadioRAFeedback feedback) { if (feedback instanceof LEDMapFeedback) { handleLEDMapFeedback((LEDMapFeedback) feedback); } - } private void handleLEDMapFeedback(LEDMapFeedback feedback) { @@ -59,5 +58,4 @@ private void handleLEDMapFeedback(LEDMapFeedback feedback) { updateState(LutronBindingConstants.CHANNEL_SWITCH, zoneEnabled ? OnOffType.ON : OnOffType.OFF); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/RS232Handler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/RS232Handler.java index d8287692fdbe5..9f3c402cee06d 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/RS232Handler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/RS232Handler.java @@ -23,6 +23,7 @@ import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.lutron.internal.radiora.RS232Connection; import org.openhab.binding.lutron.internal.radiora.RadioRAConnection; import org.openhab.binding.lutron.internal.radiora.RadioRAConnectionException; @@ -48,10 +49,10 @@ public class RS232Handler extends BaseBridgeHandler implements RadioRAFeedbackLi private ScheduledFuture zoneMapScheduledTask; - public RS232Handler(Bridge bridge) { + public RS232Handler(Bridge bridge, SerialPortManager serialPortManager) { super(bridge); - this.connection = new RS232Connection(); + this.connection = new RS232Connection(serialPortManager); this.connection.setListener(this); } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/SwitchHandler.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/SwitchHandler.java index 6e1eae9f469f0..228478ab8de75 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/SwitchHandler.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/handler/SwitchHandler.java @@ -58,7 +58,6 @@ public void handleFeedback(RadioRAFeedback feedback) { } else if (feedback instanceof ZoneMapFeedback) { handleZoneMapFeedback((ZoneMapFeedback) feedback); } - } private void handleZoneMapFeedback(ZoneMapFeedback feedback) { @@ -80,5 +79,4 @@ private void handleLocalZoneChangeFeedback(LocalZoneChangeFeedback feedback) { updateState(LutronBindingConstants.CHANNEL_SWITCH, OnOffType.valueOf(feedback.getState().toString())); } } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ButtonPressCommand.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ButtonPressCommand.java index 829f6fe34cbc4..947811c3a0106 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ButtonPressCommand.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ButtonPressCommand.java @@ -60,5 +60,4 @@ public List getArgs() { return args; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/LEDMapFeedback.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/LEDMapFeedback.java index 89cd46230fcdb..aa8314f6b1d5b 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/LEDMapFeedback.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/LEDMapFeedback.java @@ -55,5 +55,4 @@ public char getZoneValue(int zone) { return bitmap.charAt(zone - 1); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/LocalZoneChangeFeedback.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/LocalZoneChangeFeedback.java index c809f9ed515b9..703ffe604e5c1 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/LocalZoneChangeFeedback.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/LocalZoneChangeFeedback.java @@ -65,5 +65,4 @@ public State getState() { public int getZoneNumber() { return zoneNumber; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/RadioRACommand.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/RadioRACommand.java index b12b66f1acf35..9dd6d7eff8aa4 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/RadioRACommand.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/RadioRACommand.java @@ -44,5 +44,4 @@ public String toString() { return str.toString(); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/RadioRAFeedback.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/RadioRAFeedback.java index 581b524bf8b3a..4e34fd4503ef3 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/RadioRAFeedback.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/RadioRAFeedback.java @@ -28,5 +28,4 @@ public String[] parse(String msg, int numParams) { return params; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/SetDimmerLevelCommand.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/SetDimmerLevelCommand.java index 3393939979275..ab59f27111757 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/SetDimmerLevelCommand.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/SetDimmerLevelCommand.java @@ -54,5 +54,4 @@ public List getArgs() { return args; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/SetSwitchLevelCommand.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/SetSwitchLevelCommand.java index b1069eb1d6458..d72d3ec67dcce 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/SetSwitchLevelCommand.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/SetSwitchLevelCommand.java @@ -56,5 +56,4 @@ public List getArgs() { return args; } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ZoneMapFeedback.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ZoneMapFeedback.java index a3692959163e5..28a7a97841ba3 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ZoneMapFeedback.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ZoneMapFeedback.java @@ -55,5 +55,4 @@ public char getZoneValue(int zone) { return zoneStates.charAt(zone - 1); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ZoneMapInquiryCommand.java b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ZoneMapInquiryCommand.java index 4184e4d150f78..becf27d649031 100644 --- a/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ZoneMapInquiryCommand.java +++ b/bundles/org.openhab.binding.lutron/src/main/java/org/openhab/binding/lutron/internal/radiora/protocol/ZoneMapInquiryCommand.java @@ -32,5 +32,4 @@ public String getCommand() { public List getArgs() { return Collections.emptyList(); } - } diff --git a/bundles/org.openhab.binding.lutron/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.lutron/src/main/resources/ESH-INF/binding/binding.xml index 4f6a48cff4fae..7316f34cddbe2 100644 --- a/bundles/org.openhab.binding.lutron/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.lutron/src/main/resources/ESH-INF/binding/binding.xml @@ -1,11 +1,11 @@ - + Lutron Binding - The Lutron binding interfaces with Lutron lighting control and home automation systems such as RadioRA, RadioRA 2, HomeWorks, HomeWorks QS, RA2 Select, Caseta, and GRAFIK Eye. + The Lutron binding interfaces with Lutron lighting control and home automation systems such as RadioRA, + RadioRA 2, HomeWorks, HomeWorks QS, RA2 Select, Caseta, and GRAFIK Eye. Allan Tong, Bob Adair diff --git a/bundles/org.openhab.binding.lutron/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.lutron/src/main/resources/ESH-INF/thing/thing-types.xml index c7daade509b6b..e50555c415d03 100644 --- a/bundles/org.openhab.binding.lutron/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.lutron/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -542,6 +542,15 @@ Address in the Lutron control system + + + System type for virtual keypad + + + + + Other + Automatically release pressed buttons @@ -688,7 +697,8 @@ - The user name to log in to the PRG access point (typically "nwk" for connection 1 or "nwk2" for connection 2) + The user name to log in to the PRG access point (typically "nwk" for connection 1 or "nwk2" for + connection 2) nwk @@ -879,10 +889,12 @@ serial-port + false The serial port name for the HomeWorks processor. Valid values - are e.g. COM1 for Windows and /dev/ttyS0 or /dev/ttyUSB0 for Linux. + are e.g. COM1 for Windows and /dev/ttyS0 + or /dev/ttyUSB0 for Linux. @@ -890,7 +902,8 @@ The baud rate to use for the RS232 connection. - Valid values are 300, 600, 1200, 2400, 4800, 9600 (default), + Valid values are 300, 600, 1200, 2400, 4800, 9600 + (default), 19200, 38400, 57600, and 115200. 9600 @@ -914,8 +927,10 @@ The older HomeWorks processors seem to have difficulty keeping track of the time, - especially where daylight savings is concerned. If this option is selected, the HomeWorks - bridge will automatically update the processor on initialization and once per day thereafter. + especially where + daylight savings is concerned. If this option is selected, the HomeWorks + bridge will automatically update the + processor on initialization and once per day thereafter. @@ -924,14 +939,14 @@ - + Controls dimmable loads - + @@ -959,6 +974,7 @@ serial-port + false The serial port to use to communicate with a Lutron RadioRA system @@ -1198,7 +1214,7 @@ Somenumber - + @@ -1247,7 +1263,8 @@ Number - Specifies the fade (in seconds [truncated to nearest minute if more than 60 seconds]) when applying intensity changes + Specifies the fade (in seconds [truncated to nearest minute if more than 60 seconds]) when applying + intensity changes Zone diff --git a/bundles/org.openhab.binding.mail/pom.xml b/bundles/org.openhab.binding.mail/pom.xml index 32ae63f3a3312..f77b912a9cbae 100644 --- a/bundles/org.openhab.binding.mail/pom.xml +++ b/bundles/org.openhab.binding.mail/pom.xml @@ -1,10 +1,12 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.mail diff --git a/bundles/org.openhab.binding.mail/src/main/feature/feature.xml b/bundles/org.openhab.binding.mail/src/main/feature/feature.xml index c4bf2fe840be8..08d40165adcc6 100644 --- a/bundles/org.openhab.binding.mail/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.mail/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:com.sun.mail/javax.mail/1.6.2 - mvn:org.openhab.addons.bundles/org.openhab.binding.mail/${project.version} - + + openhab-runtime-base + mvn:com.sun.mail/javax.mail/1.6.2 + mvn:org.openhab.addons.bundles/org.openhab.binding.mail/${project.version} + diff --git a/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/POP3IMAPHandler.java b/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/POP3IMAPHandler.java index 5da17457ed18b..255d4d5f148e6 100644 --- a/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/POP3IMAPHandler.java +++ b/bundles/org.openhab.binding.mail/src/main/java/org/openhab/binding/mail/internal/POP3IMAPHandler.java @@ -71,7 +71,7 @@ public void initialize() { protocol = baseProtocol; if (config.security == ServerSecurity.SSL) { - protocol.concat("s"); + protocol = protocol.concat("s"); } if (config.port == 0) { diff --git a/bundles/org.openhab.binding.mail/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.mail/src/main/resources/ESH-INF/binding/binding.xml index 6cbb270db2c11..f374815dc7fa7 100644 --- a/bundles/org.openhab.binding.mail/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.mail/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,5 @@ - diff --git a/bundles/org.openhab.binding.mail/src/test/java/org/openhab/binding/mail/MailBuilderTest.java b/bundles/org.openhab.binding.mail/src/test/java/org/openhab/binding/mail/MailBuilderTest.java index 825ceb1a64160..b4d79bc742030 100644 --- a/bundles/org.openhab.binding.mail/src/test/java/org/openhab/binding/mail/MailBuilderTest.java +++ b/bundles/org.openhab.binding.mail/src/test/java/org/openhab/binding/mail/MailBuilderTest.java @@ -89,5 +89,4 @@ public void fieldsSetInMail() throws EmailException, MessagingException, IOExcep assertEquals(TEST_EMAIL, builder.build().getToAddresses().get(0).getAddress()); assertEquals(2, builder.withRecipients(TEST_EMAIL).build().getToAddresses().size()); } - } diff --git a/bundles/org.openhab.binding.max/pom.xml b/bundles/org.openhab.binding.max/pom.xml index 771a524d98cfb..00c90e86cb8c1 100644 --- a/bundles/org.openhab.binding.max/pom.xml +++ b/bundles/org.openhab.binding.max/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.max diff --git a/bundles/org.openhab.binding.max/src/main/feature/feature.xml b/bundles/org.openhab.binding.max/src/main/feature/feature.xml index 8a1a84b6cc78c..46e8e8aeea16e 100644 --- a/bundles/org.openhab.binding.max/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.max/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.max/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.max/${project.version} + diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/MaxBackupUtils.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/MaxBackupUtils.java index 08548e4b79c98..93a72a9d4d856 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/MaxBackupUtils.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/MaxBackupUtils.java @@ -65,7 +65,6 @@ public void buildBackup(String msgLine) { inProgress = false; saveMsg(msg.toString(), cube); } - } private void saveMsg(String data, String cube) { diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/ACommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/ACommand.java index cad27ec20d264..051ee41e62cda 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/ACommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/ACommand.java @@ -28,5 +28,4 @@ public String getCommandString() { public String getReturnStrings() { return "A:"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/CCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/CCommand.java index 126616bb5fb17..4fcfe81cd0e8f 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/CCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/CCommand.java @@ -34,5 +34,4 @@ public String getCommandString() { public String getReturnStrings() { return "C:"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/CubeCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/CubeCommand.java index 32c83d17181f8..7c9ce357af9fc 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/CubeCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/CubeCommand.java @@ -30,5 +30,4 @@ public abstract class CubeCommand { * end of the message */ public abstract String getReturnStrings(); - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/FCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/FCommand.java index 41c6dfb5823cb..d098cac6f0741 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/FCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/FCommand.java @@ -52,5 +52,4 @@ public String getCommandString() { public String getReturnStrings() { return "F:"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/LCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/LCommand.java index 15515a5f99e53..bb9e96b38973f 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/LCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/LCommand.java @@ -28,5 +28,4 @@ public String getCommandString() { public String getReturnStrings() { return "L:"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/MCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/MCommand.java index 2b0b6e491b440..6e08679e47be1 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/MCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/MCommand.java @@ -181,5 +181,4 @@ public String getCommandString() { public String getReturnStrings() { return "A:"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/NCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/NCommand.java index 326355ed63013..2b58beb6bedf6 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/NCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/NCommand.java @@ -32,5 +32,4 @@ public String getCommandString() { public String getReturnStrings() { return "N:"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/TCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/TCommand.java index 7698c928454c5..486f8a88fbda0 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/TCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/TCommand.java @@ -61,5 +61,4 @@ public String getCommandString() { public String getReturnStrings() { return "A:"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/UdpCubeCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/UdpCubeCommand.java index 30489d081c4d0..35ad91e50a69f 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/UdpCubeCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/UdpCubeCommand.java @@ -223,7 +223,6 @@ private void sendUdpCommand(String commandString, String ipAddress) { // Ignore } } - } /** @@ -244,5 +243,4 @@ public void setIpAddress(String ipAddress) { public Map getCommandResponse() { return commandResponse; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/ZCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/ZCommand.java index b427f169e8b70..93e9a4b3a7dde 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/ZCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/command/ZCommand.java @@ -87,5 +87,4 @@ public String getCommandString() { public String getReturnStrings() { return "A:"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/config/MaxCubeBridgeConfiguration.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/config/MaxCubeBridgeConfiguration.java index 787e4c2c68d13..405ee14d9389b 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/config/MaxCubeBridgeConfiguration.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/config/MaxCubeBridgeConfiguration.java @@ -59,5 +59,4 @@ public class MaxCubeBridgeConfiguration { /** NTP Server 2 hostname */ public String ntpServer2; - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/DeviceConfiguration.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/DeviceConfiguration.java index 15e77ee784c18..a2f723c77a976 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/DeviceConfiguration.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/DeviceConfiguration.java @@ -126,5 +126,4 @@ public Map getProperties() { public void setProperties(HashMap properties) { this.properties = properties; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/HeatingThermostat.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/HeatingThermostat.java index 0972037b82665..3c19fd2e6116a 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/HeatingThermostat.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/HeatingThermostat.java @@ -173,5 +173,4 @@ public Date getActualTempLastUpdated() { public void setActualTempLastUpdated(Date actualTempLastUpdated) { this.actualTempLastUpdated = actualTempLastUpdated; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/ShutterContact.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/ShutterContact.java index a18796aecfd22..a5600cf341c6b 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/ShutterContact.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/ShutterContact.java @@ -43,5 +43,4 @@ public OpenClosedType getShutterState() { public DeviceType getType() { return DeviceType.ShutterContact; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/UnsupportedDevice.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/UnsupportedDevice.java index 9859686695450..6e217a45e036f 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/UnsupportedDevice.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/device/UnsupportedDevice.java @@ -34,5 +34,4 @@ public DeviceType getType() { public String getName() { return "Unsupported device"; } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxCubeBridgeDiscovery.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxCubeBridgeDiscovery.java index a4ebd2d8304e7..df4cc4557418e 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxCubeBridgeDiscovery.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/discovery/MaxCubeBridgeDiscovery.java @@ -217,5 +217,4 @@ private void sendDiscoveryMessage(String discoverString) { logger.debug("IO error during MAX! Cube discovery: {}", e.getMessage()); } } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/IncompleteMessageException.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/IncompleteMessageException.java index 2cdf5c067cb42..9b3f59a0c4ad1 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/IncompleteMessageException.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/IncompleteMessageException.java @@ -24,5 +24,4 @@ public class IncompleteMessageException extends Exception { * required variable to avoid IncorrectMultilineIndexException warning */ private static final long serialVersionUID = -8882867114144637120L; - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/IncorrectMultilineIndexException.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/IncorrectMultilineIndexException.java index feb0229c35a73..12facda5d49db 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/IncorrectMultilineIndexException.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/IncorrectMultilineIndexException.java @@ -24,5 +24,4 @@ public class IncorrectMultilineIndexException extends Exception { * required variable to avoid IncorrectMultilineIndexException warning */ private static final long serialVersionUID = 3102159039702650238L; - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/MessageIsWaitingException.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/MessageIsWaitingException.java index 4218b9db5658a..9614ee081f7a9 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/MessageIsWaitingException.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/MessageIsWaitingException.java @@ -25,5 +25,4 @@ public class MessageIsWaitingException extends Exception { * required variable to avoid IncorrectMultilineIndexException warning */ private static final long serialVersionUID = -7317329978634583853L; - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/NoMessageAvailableException.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/NoMessageAvailableException.java index c4b61dfaa119a..4ac0fae214b09 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/NoMessageAvailableException.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/NoMessageAvailableException.java @@ -24,5 +24,4 @@ public class NoMessageAvailableException extends Exception { * required variable to avoid IncorrectMultilineIndexException warning */ private static final long serialVersionUID = -7663390696233390452L; - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/UnprocessableMessageException.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/UnprocessableMessageException.java index 71f4d99b96e88..cd1ac601a2bb0 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/UnprocessableMessageException.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/UnprocessableMessageException.java @@ -24,5 +24,4 @@ public class UnprocessableMessageException extends Exception { * required variable to avoid IncorrectMultilineIndexException warning */ private static final long serialVersionUID = -9071779402960309265L; - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/UnsupportedMessageTypeException.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/UnsupportedMessageTypeException.java index c9c32e877922e..07f02ee48e5a7 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/UnsupportedMessageTypeException.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/exceptions/UnsupportedMessageTypeException.java @@ -24,5 +24,4 @@ public class UnsupportedMessageTypeException extends Exception { * required variable to avoid IncorrectMultilineIndexException warning */ private static final long serialVersionUID = -5163044407682700913L; - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/factory/MaxCubeHandlerFactory.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/factory/MaxCubeHandlerFactory.java index 24f359918e50c..8b9805c47c695 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/factory/MaxCubeHandlerFactory.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/factory/MaxCubeHandlerFactory.java @@ -122,5 +122,4 @@ protected ThingHandler createHandler(Thing thing) { return null; } } - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/DeviceStatusListener.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/DeviceStatusListener.java index 34abe0f719c47..0c8f57b5647ec 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/DeviceStatusListener.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/DeviceStatusListener.java @@ -64,5 +64,4 @@ public interface DeviceStatusListener { * The device which config is changed. */ public void onDeviceConfigUpdate(Bridge bridge, Device device); - } diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxCubeBridgeHandler.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxCubeBridgeHandler.java index b7f6c1153e1db..59dbe809f1606 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxCubeBridgeHandler.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/MaxCubeBridgeHandler.java @@ -292,7 +292,6 @@ private void cubeConfigReset() { clearDeviceList(); propertiesSet = false; roomPropertiesSet = false; - } public void cubeReboot() { @@ -981,7 +980,6 @@ private void sendNtpUpdate(Map configurationParameters) { } queueCommand(new SendCommand("Cube(" + getThing().getUID().getId() + ")", new FCommand(ntpServer1, ntpServer2), "Update NTP info")); - } private boolean socketConnect() throws UnknownHostException, IOException { diff --git a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/SendCommand.java b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/SendCommand.java index 673cc8870bb45..55942ea9ae550 100644 --- a/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/SendCommand.java +++ b/bundles/org.openhab.binding.max/src/main/java/org/openhab/binding/max/internal/handler/SendCommand.java @@ -126,5 +126,4 @@ public String toString() { .append("cubeCommand", cubeCommand).append("serialNumber", serialNumber).append("key", key) .append("commandText", commandText).toString(); } - } diff --git a/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/binding/binding.xml index a7c069fb17c81..e083cf4cbb681 100644 --- a/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + MAX! Binding This is the binding for the eQ-3 MAX! Home Solution. diff --git a/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/thing/bridge.xml index 906f04774cd5d..14398467d7440 100644 --- a/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/thing/bridge.xml @@ -9,8 +9,8 @@ - - + + serialNumber @@ -121,14 +121,14 @@ Number Free memory slots to store commands send to the devices - + Number Duty Cycle for sending commands to the devices - + diff --git a/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/thing/thing-types.xml index 697fd28bfdf9b..b07796a65a229 100644 --- a/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.max/src/main/resources/ESH-INF/thing/thing-types.xml @@ -5,19 +5,19 @@ - + This is a MAX! HeatingThermostat - - - - - - + + + + + + serialNumber @@ -108,9 +108,11 @@ Experimental feature! Rate of the actual refresh in minutes. - 0-9=refresh disabled. Minimum refresh rate once/10 minutes, recommended + 0-9=refresh disabled. Minimum refresh rate + once/10 minutes, recommended 60min. The settings of the heating thermostats are changed to trigger an - update of temperature, as the actual temperature only is updated when the + update of + temperature, as the actual temperature only is updated when the valves changes. 0 true @@ -133,19 +135,19 @@ - + This is a MAX! HeatingThermostat+ - - - - - - + + + + + + serialNumber @@ -237,9 +239,11 @@ Experimental feature! Rate of the actual refresh in minutes. - 0-9=refresh disabled. Minimum refresh rate once/10 minutes, recommended + 0-9=refresh disabled. Minimum refresh rate + once/10 minutes, recommended 60min. The settings of the heating thermostats are changed to trigger an - update of temperature, as the actual temperature only is updated when the + update of + temperature, as the actual temperature only is updated when the valves changes. 0 true @@ -262,19 +266,19 @@ - + This is a MAX! WallThermostat+ - - - - - - + + + + + + serialNumber @@ -327,14 +331,14 @@ - + This is a MAX! EcoSwitch - + serialNumber @@ -371,15 +375,15 @@ - + This is a MAX! Shutter Contact - - + + serialNumber @@ -464,7 +468,7 @@ heating - + @@ -475,7 +479,7 @@ heating - + diff --git a/bundles/org.openhab.binding.mcp23017/README.md b/bundles/org.openhab.binding.mcp23017/README.md index 41c638c30e129..93ef9da12b198 100644 --- a/bundles/org.openhab.binding.mcp23017/README.md +++ b/bundles/org.openhab.binding.mcp23017/README.md @@ -94,6 +94,6 @@ rule "living_room_led contact" when Item living_room_led_contact changed to OPEN then - living_room_led_switch.sendCommand(living_room_led_switch.state != ON ? ON : OFF) + living_room_led_switch.sendCommand(if(living_room_led_switch.state != ON) ON else OFF) end ``` diff --git a/bundles/org.openhab.binding.mcp23017/pom.xml b/bundles/org.openhab.binding.mcp23017/pom.xml index 8231f440176ce..0c0ff3543e27a 100644 --- a/bundles/org.openhab.binding.mcp23017/pom.xml +++ b/bundles/org.openhab.binding.mcp23017/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.mcp23017 diff --git a/bundles/org.openhab.binding.mcp23017/src/main/feature/feature.xml b/bundles/org.openhab.binding.mcp23017/src/main/feature/feature.xml index 9bfe8060d35c5..0b24b0fbecb9b 100644 --- a/bundles/org.openhab.binding.mcp23017/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.mcp23017/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.mcp23017/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.mcp23017/${project.version} + diff --git a/bundles/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/Mcp23017BindingConstants.java b/bundles/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/Mcp23017BindingConstants.java index 482be5071045f..4d2875ab425e3 100644 --- a/bundles/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/Mcp23017BindingConstants.java +++ b/bundles/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/Mcp23017BindingConstants.java @@ -71,5 +71,4 @@ public class Mcp23017BindingConstants { .of(CHANNEL_A0, CHANNEL_A1, CHANNEL_A2, CHANNEL_A3, CHANNEL_A4, CHANNEL_A5, CHANNEL_A6, CHANNEL_A7, CHANNEL_B0, CHANNEL_B1, CHANNEL_B2, CHANNEL_B3, CHANNEL_B4, CHANNEL_B5, CHANNEL_B6, CHANNEL_B7) .collect(Collectors.toSet()); - } diff --git a/bundles/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/Mcp23017HandlerFactory.java b/bundles/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/Mcp23017HandlerFactory.java index 9546317fd8081..e070f90a8da05 100644 --- a/bundles/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/Mcp23017HandlerFactory.java +++ b/bundles/org.openhab.binding.mcp23017/src/main/java/org/openhab/binding/mcp23017/internal/Mcp23017HandlerFactory.java @@ -55,5 +55,4 @@ protected ThingHandler createHandler(Thing thing) { logger.debug("No handler match for {}", thingTypeUID.getAsString()); return null; } - } diff --git a/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/binding/binding.xml index 32149b2ea6ee7..c9d7afc72b19d 100644 --- a/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + MCP23017 Binding This is the binding for MCP23017 I/O expansion chips. diff --git a/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/config/config.xml index 8b9814f8144e0..3e7a171ae5db7 100644 --- a/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/thing/channels.xml index 4457f2dc9ada2..46108a0c3fc7a 100644 --- a/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/thing/channels.xml @@ -1,5 +1,6 @@ - @@ -8,22 +9,22 @@ MCP 23017 pins working in DIGITAL_INPUT mode (contact) - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -32,22 +33,22 @@ MCP 23017 pins working in DIGITAL_OUTPUT mode (switch) - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -56,8 +57,8 @@ channel type for MCP23017 pin in DIGITAL_INPUT mode (contact) Contact - - + + @@ -65,8 +66,8 @@ channel type for MCP23017 pin in DIGITAL_INPUT mode (switch) Switch - - + + diff --git a/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/thing/thing-types.xml index 9382568e91def..c2cae24a6e6ca 100644 --- a/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.mcp23017/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.melcloud/pom.xml b/bundles/org.openhab.binding.melcloud/pom.xml index 3f60e9ce09d86..fb8f1f2dd67f3 100644 --- a/bundles/org.openhab.binding.melcloud/pom.xml +++ b/bundles/org.openhab.binding.melcloud/pom.xml @@ -1,15 +1,17 @@ - + + - 4.0.0 + 4.0.0 - - org.openhab.addons.bundles - org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT - + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + - org.openhab.binding.melcloud + org.openhab.binding.melcloud - openHAB Add-ons :: Bundles :: MELCloud Binding + openHAB Add-ons :: Bundles :: MELCloud Binding diff --git a/bundles/org.openhab.binding.melcloud/src/main/feature/feature.xml b/bundles/org.openhab.binding.melcloud/src/main/feature/feature.xml index 4a0e9cd87b42f..7794523ae465a 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.melcloud/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.melcloud/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.melcloud/${project.version} + diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/MelCloudHandlerFactory.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/MelCloudHandlerFactory.java index e69c6a23d67ac..4276675f70e40 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/MelCloudHandlerFactory.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/MelCloudHandlerFactory.java @@ -58,5 +58,4 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return null; } - } diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/MelCloudConnection.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/MelCloudConnection.java index c3ef722b104ef..4cd6668073720 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/MelCloudConnection.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/MelCloudConnection.java @@ -185,7 +185,6 @@ public HeatpumpDeviceStatus sendHeatpumpDeviceStatus(HeatpumpDeviceStatus heatpu setConnected(false); throw new MelCloudCommException("Error occurred during heatpump device command sending", e); } - } public synchronized boolean isConnected() { diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Device.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Device.java index ce8bda29cd8f0..611940f509d17 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Device.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Device.java @@ -553,5 +553,4 @@ public Permissions getPermissions() { public void setPermissions(Permissions permissions) { this.permissions = permissions; } - } diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/DeviceProps.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/DeviceProps.java index 13b678a07a751..67c9727f18a6b 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/DeviceProps.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/DeviceProps.java @@ -1102,5 +1102,4 @@ public List getUnits() { public void setUnits(List units) { this.units = units; } - } diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/LoginData.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/LoginData.java index 2ddefdbd0859d..51f2ab1d0ca51 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/LoginData.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/LoginData.java @@ -506,5 +506,4 @@ public Double getMapLatitude() { public void setMapLatitude(Double mapLatitude) { this.mapLatitude = mapLatitude; } - } diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Preset.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Preset.java index f957f0f6cc08b..59d95c7ee831d 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Preset.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Preset.java @@ -154,5 +154,4 @@ public String getNumberDescription() { public void setNumberDescription(String numberDescription) { this.numberDescription = numberDescription; } - } diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/QuantizedCoordinates.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/QuantizedCoordinates.java index 908e913dda071..3b9406bca157f 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/QuantizedCoordinates.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/QuantizedCoordinates.java @@ -44,5 +44,4 @@ public Double getLongitude() { public void setLongitude(Double longitude) { this.longitude = longitude; } - } diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Structure.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Structure.java index 572847cfa5891..8a2ab1f829ca7 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Structure.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/Structure.java @@ -69,5 +69,4 @@ public List getClients() { public void setClients(List clients) { this.clients = clients; } - } diff --git a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/WeatherObservation.java b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/WeatherObservation.java index ea57239dd41ab..c6733fc755107 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/WeatherObservation.java +++ b/bundles/org.openhab.binding.melcloud/src/main/java/org/openhab/binding/melcloud/internal/api/json/WeatherObservation.java @@ -143,5 +143,4 @@ public Integer getWeatherType() { public void setWeatherType(Integer weatherType) { this.weatherType = weatherType; } - } diff --git a/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/acDevice.xml b/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/acDevice.xml index 5fd39e12e5480..18c1b34153f42 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/acDevice.xml +++ b/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/acDevice.xml @@ -6,23 +6,23 @@ - + Air conditioning device - - - - - - - - - - - + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/channels.xml index 53ab174f9b92a..c22a0e21c3e67 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/channels.xml @@ -15,28 +15,28 @@ Switch Device has a pending command(s) - + Switch Is device in offline state. - + DateTime Last communication time between device and MELCloud - + DateTime Next communication time between device and MELCloud - + @@ -59,7 +59,7 @@ Number:Temperature Set temperature - + @@ -116,7 +116,7 @@ Number:Temperature Room temperature - + @@ -124,7 +124,7 @@ Number:Temperature Temperature of water i - + @@ -137,14 +137,14 @@ Number:Temperature Room temperature for zone 1 - + Number:Temperature Set temperature for zone 1 - + diff --git a/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/heatpumpDevice.xml b/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/heatpumpDevice.xml index dcc9d7b0ea677..aa0d2faf7c96a 100644 --- a/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/heatpumpDevice.xml +++ b/bundles/org.openhab.binding.melcloud/src/main/resources/ESH-INF/thing/heatpumpDevice.xml @@ -6,21 +6,21 @@ - + Heatpump device - - - - - - - - - + + + + + + + + + diff --git a/bundles/org.openhab.binding.meteoblue/pom.xml b/bundles/org.openhab.binding.meteoblue/pom.xml index 1b016bd034a0e..5c03d196408f4 100644 --- a/bundles/org.openhab.binding.meteoblue/pom.xml +++ b/bundles/org.openhab.binding.meteoblue/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.meteoblue diff --git a/bundles/org.openhab.binding.meteoblue/src/main/feature/feature.xml b/bundles/org.openhab.binding.meteoblue/src/main/feature/feature.xml index b4ca47ed78843..9d7ce2580561b 100644 --- a/bundles/org.openhab.binding.meteoblue/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.meteoblue/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.meteoblue/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.meteoblue/${project.version} + diff --git a/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/binding/binding.xml index cc8dacd17c848..2a3563000c185 100644 --- a/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + meteoblue Binding The meteoblue binding retrieves weather information from the meteoblue weather service. diff --git a/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/thing/bridge.xml index cb3f783fbb582..1666bc4e4af80 100644 --- a/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,18 +1,19 @@ - - - - - The meteoblue account holds settings for use with the meteoblue weather service. + + + + + The meteoblue account holds settings for use with the meteoblue weather service. - - - password - - API key to access the meteoblue service - - - + + + password + + API key to access the meteoblue service + + + diff --git a/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/thing/thing-types.xml index 855180564f29a..1c6ad767fc46b 100644 --- a/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.meteoblue/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,13 +1,13 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + @@ -62,7 +62,8 @@ - Time Zone of this location (e.g. America/Louisville). See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + Time Zone of this location (e.g. America/Louisville). See + https://en.wikipedia.org/wiki/List_of_tz_database_time_zones @@ -71,43 +72,43 @@ - + This is the weather forecast - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -130,7 +131,7 @@ The low temperature Temperature - + @@ -138,7 +139,7 @@ The high temperature Temperature - + @@ -146,7 +147,7 @@ The average temperature Temperature - + @@ -154,7 +155,7 @@ The low "feels like" temperature Temperature - + @@ -162,7 +163,7 @@ The high "feels like" temperature Temperature - + @@ -213,21 +214,21 @@ Maximum wind speed Wind - + Number:Speed Wind - + Number:Speed Wind - + @@ -235,7 +236,7 @@ Low Pressure Pressure - + @@ -243,7 +244,7 @@ High Pressure Pressure - + @@ -251,7 +252,7 @@ Mean Pressure Pressure - + @@ -267,7 +268,7 @@ Prediction of total precipitation Rain - + @@ -275,17 +276,18 @@ Prediction of convective precipitation (rainfall) Rain - + String Precipitation distribution around the location as a 7x7 array, - encoded from south to north and west to east - (e.g. 2112211093222219212110112229922133311912239022192). + encoded from south to north and west to + east + (e.g. 2112211093222219212110112229922133311912239022192). Rain - + @@ -293,7 +295,7 @@ Image representing the Rain Spot precipitation distribution Rain - + @@ -301,7 +303,7 @@ Prediction of the fraction of total precipitation that will fall as snow Rain - + @@ -309,7 +311,7 @@ Prediction of snowfall Rain - + @@ -348,7 +350,7 @@ Number The estimated certainty of the forecast (0 = very low, 5 = very high) - + diff --git a/bundles/org.openhab.binding.meteostick/pom.xml b/bundles/org.openhab.binding.meteostick/pom.xml index 78375e0db76ee..a07652c4f93de 100644 --- a/bundles/org.openhab.binding.meteostick/pom.xml +++ b/bundles/org.openhab.binding.meteostick/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.meteostick diff --git a/bundles/org.openhab.binding.meteostick/src/main/feature/feature.xml b/bundles/org.openhab.binding.meteostick/src/main/feature/feature.xml index 8325de6024f4a..cb6ab36920a17 100644 --- a/bundles/org.openhab.binding.meteostick/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.meteostick/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.meteostick/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.meteostick/${project.version} + diff --git a/bundles/org.openhab.binding.meteostick/src/main/java/org/openhab/binding/meteostick/internal/MeteostickHandlerFactory.java b/bundles/org.openhab.binding.meteostick/src/main/java/org/openhab/binding/meteostick/internal/MeteostickHandlerFactory.java index bcc3ae6a809e8..329f0b0860343 100644 --- a/bundles/org.openhab.binding.meteostick/src/main/java/org/openhab/binding/meteostick/internal/MeteostickHandlerFactory.java +++ b/bundles/org.openhab.binding.meteostick/src/main/java/org/openhab/binding/meteostick/internal/MeteostickHandlerFactory.java @@ -12,15 +12,20 @@ */ package org.openhab.binding.meteostick.internal; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.meteostick.internal.handler.MeteostickBridgeHandler; import org.openhab.binding.meteostick.internal.handler.MeteostickSensorHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,10 +35,18 @@ * * @author Chris Jackson - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.meteostick") public class MeteostickHandlerFactory extends BaseThingHandlerFactory { private Logger logger = LoggerFactory.getLogger(MeteostickHandlerFactory.class); + private final SerialPortManager serialPortManager; + + @Activate + public MeteostickHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return MeteostickBridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID) @@ -41,13 +54,13 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { logger.debug("MeteoStick thing factory: createHandler {} of type {}", thing.getThingTypeUID(), thing.getUID()); ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (MeteostickBridgeHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { - return new MeteostickBridgeHandler((Bridge) thing); + return new MeteostickBridgeHandler((Bridge) thing, serialPortManager); } if (MeteostickSensorHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { diff --git a/bundles/org.openhab.binding.meteostick/src/main/java/org/openhab/binding/meteostick/internal/handler/MeteostickBridgeHandler.java b/bundles/org.openhab.binding.meteostick/src/main/java/org/openhab/binding/meteostick/internal/handler/MeteostickBridgeHandler.java index 81f086bd64b8b..883a0597f2334 100644 --- a/bundles/org.openhab.binding.meteostick/src/main/java/org/openhab/binding/meteostick/internal/handler/MeteostickBridgeHandler.java +++ b/bundles/org.openhab.binding.meteostick/src/main/java/org/openhab/binding/meteostick/internal/handler/MeteostickBridgeHandler.java @@ -37,18 +37,16 @@ import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPort; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * The {@link MeteostickBridgeHandler} is responsible for handling commands, which are * sent to one of the channels. @@ -63,6 +61,7 @@ public class MeteostickBridgeHandler extends BaseBridgeHandler { private static final int RECEIVE_TIMEOUT = 3000; private SerialPort serialPort; + private final SerialPortManager serialPortManager; private ReceiveThread receiveThread; private ScheduledFuture offlineTimerJob; @@ -74,8 +73,9 @@ public class MeteostickBridgeHandler extends BaseBridgeHandler { private ConcurrentMap eventListeners = new ConcurrentHashMap<>(); - public MeteostickBridgeHandler(Bridge thing) { + public MeteostickBridgeHandler(Bridge thing, SerialPortManager serialPortManager) { super(thing); + this.serialPortManager = serialPortManager; } @Override @@ -146,13 +146,18 @@ protected void unsubscribeEvents(int channel, MeteostickEventListener handler) { * @throws SerialInterfaceException when a connection error occurs. */ private boolean connectPort(final String serialPortName) { - logger.info("MeteoStick Connecting to serial port {}", serialPortName); + logger.debug("MeteoStick Connecting to serial port {}", serialPortName); + + SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(serialPortName); + if (portIdentifier == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, + "Serial Error: Port " + serialPortName + " does not exist"); + return false; + } boolean success = false; try { - CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(serialPortName); - CommPort commPort = portIdentifier.open("org.openhab.binding.meteostick", 2000); - serialPort = (SerialPort) commPort; + serialPort = portIdentifier.open("org.openhab.binding.meteostick", 2000); serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); serialPort.enableReceiveThreshold(1); @@ -166,12 +171,9 @@ private boolean connectPort(final String serialPortName) { serialPort.addEventListener(this.receiveThread); serialPort.notifyOnDataAvailable(true); - logger.info("Serial port is initialized"); + logger.debug("Serial port is initialized"); success = true; - } catch (NoSuchPortException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, - "Serial Error: Port " + serialPortName + " does not exist"); } catch (PortInUseException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, "Serial Error: Port " + serialPortName + " in use"); @@ -203,7 +205,7 @@ private void disconnect() { this.serialPort.close(); this.serialPort = null; } - logger.info("Disconnected from serial port"); + logger.debug("Disconnected from serial port"); } private void sendToMeteostick(String string) { diff --git a/bundles/org.openhab.binding.meteostick/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.meteostick/src/main/resources/ESH-INF/binding/binding.xml index 2da235ae7e1fd..9298b4b3349d4 100644 --- a/bundles/org.openhab.binding.meteostick/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.meteostick/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - MeteoStick Binding diff --git a/bundles/org.openhab.binding.meteostick/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.meteostick/src/main/resources/ESH-INF/thing/thing-types.xml index 5587839d277d9..561d09957fbf0 100644 --- a/bundles/org.openhab.binding.meteostick/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.meteostick/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -7,13 +8,14 @@ Meteostick USB Receiver - - + + serial-port + false Serial port that the Meteostick is plugged into @@ -34,25 +36,25 @@ - + Davis Integrated Sensor Suite - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.miele/pom.xml b/bundles/org.openhab.binding.miele/pom.xml index fc232203a13f4..e918cdc1e8d77 100644 --- a/bundles/org.openhab.binding.miele/pom.xml +++ b/bundles/org.openhab.binding.miele/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.miele diff --git a/bundles/org.openhab.binding.miele/src/main/feature/feature.xml b/bundles/org.openhab.binding.miele/src/main/feature/feature.xml index 44c58e640fba6..152c30aeddcf1 100644 --- a/bundles/org.openhab.binding.miele/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.miele/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.miele/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.miele/${project.version} + diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java index 8bfd12dcd81ee..26b0dc6c5aa96 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/MieleBindingConstants.java @@ -49,5 +49,4 @@ public class MieleBindingConstants { public static final String INTERFACE = "interface"; public static final String USER_NAME = "userName"; public static final String PASSWORD = "password"; - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleMDNSDiscoveryParticipant.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleMDNSDiscoveryParticipant.java index fbeec362e14e0..50a80b576508f 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleMDNSDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/discovery/MieleMDNSDiscoveryParticipant.java @@ -114,5 +114,4 @@ private boolean isMieleGateway(ServiceInfo service) { return service.getApplication().contains(SERVICE_NAME) && service.getPropertyString(PATH_PROPERTY_NAME) != null && service.getPropertyString(PATH_PROPERTY_NAME).equalsIgnoreCase(PATH_TO_CHECK_FOR_XGW3000); } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceStatusListener.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceStatusListener.java index 23c9346d25799..ac31ad4a7fd7c 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceStatusListener.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/ApplianceStatusListener.java @@ -54,5 +54,4 @@ public interface ApplianceStatusListener { * @param appliance The XGW homedevice definition of the appliance that was removed */ void onApplianceAdded(HomeDevice appliance); - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineChannelSelector.java index b3cc6986f46de..7f2fced4b0369 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineChannelSelector.java @@ -141,5 +141,4 @@ public String getMieleEnum(String s, DeviceMetaData dmd) { return null; } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java index ca542e2229835..8ebc19bc87310 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/CoffeeMachineHandler.java @@ -78,5 +78,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { channelID, command.toString()); } } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishWasherHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishWasherHandler.java index af131d8309db3..23d1a5568a109 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishWasherHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishWasherHandler.java @@ -79,5 +79,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { channelID, command.toString()); } } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishwasherChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishwasherChannelSelector.java index 49685d70ce756..69ea12ed9b1e3 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishwasherChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/DishwasherChannelSelector.java @@ -200,5 +200,4 @@ public String getMieleEnum(String s, DeviceMetaData dmd) { return null; } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeChannelSelector.java index 1821e1a1a3f28..5d4fd31f8af86 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeChannelSelector.java @@ -77,8 +77,7 @@ public State getState(String s, DeviceMetaData dmd) { private final Class typeClass; private final boolean isProperty; - FridgeChannelSelector(String propertyID, String channelID, Class typeClass, - boolean isProperty) { + FridgeChannelSelector(String propertyID, String channelID, Class typeClass, boolean isProperty) { this.mieleID = propertyID; this.channelID = channelID; this.typeClass = typeClass; diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java index 3d7a254cf4a98..6009be3678fe7 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/FridgeFreezerHandler.java @@ -84,5 +84,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { channelID, command.toString()); } } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobHandler.java index 8c9a5626017c0..6eebbd1690976 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HobHandler.java @@ -33,5 +33,4 @@ public HobHandler(Thing thing) { public void handleCommand(ChannelUID channelUID, Command command) { super.handleCommand(channelUID, command); } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodChannelSelector.java index 43ff4ee791b29..633867c07c8b5 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodChannelSelector.java @@ -64,8 +64,7 @@ public State getState(String s, DeviceMetaData dmd) { private final Class typeClass; private final boolean isProperty; - HoodChannelSelector(String propertyID, String channelID, Class typeClass, - boolean isProperty) { + HoodChannelSelector(String propertyID, String channelID, Class typeClass, boolean isProperty) { this.mieleID = propertyID; this.channelID = channelID; this.typeClass = typeClass; diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java index 9e8beb65e788e..c944298c2bee8 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/HoodHandler.java @@ -82,5 +82,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { channelID, command.toString()); } } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java index cfe96f397a201..d7194209e0cc5 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/MieleApplianceHandler.java @@ -143,8 +143,9 @@ public void handleCommand(ChannelUID channelUID, Command command) { } @Override - public void onApplianceStateChanged(String UID, DeviceClassObject dco) { - String myUID = ((String) getThing().getProperties().get(PROTOCOL_PROPERTY_NAME)) + (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID); + public void onApplianceStateChanged(String UID, DeviceClassObject dco) { + String myUID = ((String) getThing().getProperties().get(PROTOCOL_PROPERTY_NAME)) + + (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID); String modelID = StringUtils.right(dco.DeviceClass, dco.DeviceClass.length() - new String("com.miele.xgw3000.gateway.hdm.deviceclasses.Miele").length()); @@ -176,7 +177,8 @@ public void onApplianceStateChanged(String UID, DeviceClassObject dco) { @Override public void onAppliancePropertyChanged(String UID, DeviceProperty dp) { - String myUID = ((String) getThing().getProperties().get(PROTOCOL_PROPERTY_NAME)) + (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID); + String myUID = ((String) getThing().getProperties().get(PROTOCOL_PROPERTY_NAME)) + + (String) getThing().getConfiguration().getProperties().get(APPLIANCE_ID); if (myUID.equals(UID)) { try { diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerChannelSelector.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerChannelSelector.java index 5556be0edef67..2e0ca19d169fd 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerChannelSelector.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerChannelSelector.java @@ -209,5 +209,4 @@ public String getMieleEnum(String s, DeviceMetaData dmd) { return null; } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java index 37d8b30852473..c9ff24f9564ac 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/TumbleDryerHandler.java @@ -79,5 +79,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { channelID, command.toString()); } } - } diff --git a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java index 286ebcacca431..20bec177412cc 100644 --- a/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java +++ b/bundles/org.openhab.binding.miele/src/main/java/org/openhab/binding/miele/internal/handler/WashingMachineHandler.java @@ -80,5 +80,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { channelID, command.toString()); } } - } diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/binding/binding.xml index bdc80cf8b1cef..a9ae1c8359276 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Miele Binding This is the binding for Miele@home appliances diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/channeltypes.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/channeltypes.xml index 9fa2e04dc90f8..6d652dfc2d668 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/channeltypes.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/channeltypes.xml @@ -1,5 +1,6 @@ - @@ -71,7 +72,7 @@ Switch the appliance on or off - + Switch @@ -212,4 +213,3 @@ - diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/coffeemachine.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/coffeemachine.xml index 7691488adc01c..d4d6f8588f028 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/coffeemachine.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/coffeemachine.xml @@ -1,24 +1,25 @@ - - + This is a Miele@home compatible coffee machine - - - - - - + + + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/dishwasher.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/dishwasher.xml index a6a7075b59acd..5aae629917f2c 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/dishwasher.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/dishwasher.xml @@ -1,27 +1,28 @@ - - + This is a Miele@home compatible dishwasher - - - - - - - - - + + + + + + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/fridge.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/fridge.xml index b64e6ead9d133..0e76fa038fc95 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/fridge.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/fridge.xml @@ -1,24 +1,25 @@ - - + This is a Miele@home compatible fridge - - - - - - + + + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/fridgefreezer.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/fridgefreezer.xml index edd63bceb004c..0982b2581a42c 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/fridgefreezer.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/fridgefreezer.xml @@ -1,29 +1,30 @@ - - + This is a Miele@home compatible fridgefreezer - - - - - - - - - - - + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/hob.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/hob.xml index 296b92b39b5e8..c091f9ad6c0b3 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/hob.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/hob.xml @@ -1,37 +1,38 @@ - - + This is a Miele@home compatible hob - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/hood.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/hood.xml index 68066a0266cf3..668c81ef11a2a 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/hood.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/hood.xml @@ -1,22 +1,23 @@ - - + This is a Miele@home compatible hood - - - - + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/oven.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/oven.xml index 2e5fd3a97a0e4..0e42274429a32 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/oven.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/oven.xml @@ -1,33 +1,34 @@ - - + This is a Miele@home compatible oven - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/tumbledryer.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/tumbledryer.xml index bfa1caa52b5ac..22c81484ff98c 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/tumbledryer.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/tumbledryer.xml @@ -1,29 +1,30 @@ - - + This is a Miele@home compatible tumbledryer - - - - - - - - - - - + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/washingmachine.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/washingmachine.xml index 5e78b9256a771..3330fd36ef4b5 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/washingmachine.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/washingmachine.xml @@ -1,30 +1,31 @@ - - + This is a Miele@home compatible washing machine - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/xgw3000.xml b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/xgw3000.xml index f14a16d4c355f..36cb38e137c65 100644 --- a/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/xgw3000.xml +++ b/bundles/org.openhab.binding.miele/src/main/resources/ESH-INF/thing/xgw3000.xml @@ -1,5 +1,6 @@ - @@ -22,7 +23,8 @@ network-address - Network address of openHAB host interface where the binding will listen for multicast events coming from the Miele@home gateway + Network address of openHAB host interface where the binding will listen for multicast events coming + from the Miele@home gateway true diff --git a/bundles/org.openhab.binding.mihome/pom.xml b/bundles/org.openhab.binding.mihome/pom.xml index 123f270a91df6..ec2a204818009 100644 --- a/bundles/org.openhab.binding.mihome/pom.xml +++ b/bundles/org.openhab.binding.mihome/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.mihome diff --git a/bundles/org.openhab.binding.mihome/src/main/feature/feature.xml b/bundles/org.openhab.binding.mihome/src/main/feature/feature.xml index 73fd4bf9808bc..a98b44182915a 100644 --- a/bundles/org.openhab.binding.mihome/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.mihome/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.mihome/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.mihome/${project.version} + diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/EncryptionHelper.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/EncryptionHelper.java index eb52822be3f94..11ed1fc005c57 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/EncryptionHelper.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/EncryptionHelper.java @@ -123,5 +123,4 @@ private String bytesToHex(byte[] bytes) { } return new String(hexChars); } - } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/discovery/XiaomiBridgeDiscoveryService.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/discovery/XiaomiBridgeDiscoveryService.java index 4b57504d80a65..7887c92dcdb03 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/discovery/XiaomiBridgeDiscoveryService.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/discovery/XiaomiBridgeDiscoveryService.java @@ -19,6 +19,7 @@ import java.util.Map; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; import org.eclipse.smarthome.config.discovery.DiscoveryService; @@ -38,6 +39,7 @@ * @author Patrick Boos - Initial contribution * @author Kuba Wolanin - logger fixes */ +@NonNullByDefault @Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.mihome") public class XiaomiBridgeDiscoveryService extends AbstractDiscoveryService implements XiaomiSocketListener { @@ -45,7 +47,7 @@ public class XiaomiBridgeDiscoveryService extends AbstractDiscoveryService imple private static final int DISCOVERY_TIMEOUT_SEC = 30; private final Logger logger = LoggerFactory.getLogger(XiaomiBridgeDiscoveryService.class); - private XiaomiDiscoverySocket socket; + private final XiaomiDiscoverySocket socket = new XiaomiDiscoverySocket("discovery"); public XiaomiBridgeDiscoveryService() { super(SUPPORTED_THING_TYPES, DISCOVERY_TIMEOUT_SEC, false); @@ -53,8 +55,7 @@ public XiaomiBridgeDiscoveryService() { @Override protected void startScan() { - socket = (socket == null) ? new XiaomiDiscoverySocket() : socket; - socket.intialize(); + socket.initialize(); logger.debug("Start scan for bridges"); socket.registerListener(this); discoverGateways(); @@ -65,17 +66,13 @@ protected synchronized void stopScan() { super.stopScan(); logger.debug("Stop scan"); removeOlderResults(getTimestampOfLastScan()); - if (socket != null) { - socket.unregisterListener(this); - } + socket.unregisterListener(this); } @Override public void deactivate() { super.deactivate(); - if (socket != null) { - socket.unregisterListener(this); - } + socket.unregisterListener(this); } @Override diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorCurtainHandler.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorCurtainHandler.java index e5afd8592efd9..7e95b0ae07bda 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorCurtainHandler.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorCurtainHandler.java @@ -65,8 +65,7 @@ void execute(ChannelUID channelUID, Command command) { status = lastDirection; } } else if (command instanceof PercentType) { - getXiaomiBridgeHandler().writeToDevice(getItemId(), new String[] { STATUS }, - new Object[] { AUTO }); + getXiaomiBridgeHandler().writeToDevice(getItemId(), new String[] { STATUS }, new Object[] { AUTO }); getXiaomiBridgeHandler().writeToDevice(getItemId(), new String[] { CURTAIN_LEVEL }, new Object[] { status }); } else { @@ -114,5 +113,4 @@ void parseDefault(JsonObject data) { } } } - } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorGatewayHandler.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorGatewayHandler.java index 24b1eb224b56a..6af4678e631af 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorGatewayHandler.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorGatewayHandler.java @@ -210,5 +210,4 @@ private void writeBridgeRingtone(int ringtoneId, int volume) { private void stopRingtone() { getXiaomiBridgeHandler().writeToBridge(new String[] { MID }, new Object[] { 10000 }); } - } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorPlugHandler.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorPlugHandler.java index 44f4de2e8e8aa..d32daf6d6a4e9 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorPlugHandler.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiActorPlugHandler.java @@ -100,5 +100,4 @@ private void getStatusFromData(JsonObject data) { } } } - } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiAqaraActorSwitch2Handler.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiAqaraActorSwitch2Handler.java index 8e6e14052bf89..161324cc0eda7 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiAqaraActorSwitch2Handler.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiAqaraActorSwitch2Handler.java @@ -87,5 +87,4 @@ void parseDefault(JsonObject data) { updateState(CHANNEL_SWITCH_CH1, isOn ? OnOffType.ON : OnOffType.OFF); } } - } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiBridgeHandler.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiBridgeHandler.java index acd67512bbb19..842839aebeabb 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiBridgeHandler.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiBridgeHandler.java @@ -131,8 +131,8 @@ public void initialize() { return; } logger.debug("Init socket on Port: {}", port); - socket = new XiaomiBridgeSocket(port); - socket.intialize(); + socket = new XiaomiBridgeSocket(port, getThing().getUID().getId()); + socket.initialize(); socket.registerListener(this); scheduler.schedule(() -> { diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiSensorMagnetHandler.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiSensorMagnetHandler.java index a2178d966ac57..b118d27f876bc 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiSensorMagnetHandler.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/handler/XiaomiSensorMagnetHandler.java @@ -96,5 +96,4 @@ void execute(ChannelUID channelUID, Command command) { void onTimer() { triggerChannel(CHANNEL_OPEN_ALARM, "ALARM"); } - } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiBridgeSocket.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiBridgeSocket.java index b21a401e5d901..b78af9ab9d783 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiBridgeSocket.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiBridgeSocket.java @@ -13,10 +13,10 @@ package org.openhab.binding.mihome.internal.socket; import java.io.IOException; -import java.net.DatagramSocket; import java.net.InetAddress; import java.net.MulticastSocket; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,35 +26,37 @@ * @author Dieter Schmidt - Initial contribution * */ +@NonNullByDefault public class XiaomiBridgeSocket extends XiaomiSocket { private final Logger logger = LoggerFactory.getLogger(XiaomiBridgeSocket.class); - public XiaomiBridgeSocket(int port) { - super(port); + public XiaomiBridgeSocket(int port, String owner) { + super(port, owner); } /** * Sets up the {@link XiaomiBridgeSocket}. * * Connects the socket to the specific multicast address and port. - * Starts the {@link ReceiverThread} for the socket. */ @Override - synchronized DatagramSocket setupSocket() { - DatagramSocket openSocket = getOpenSockets().get(getPort()); - if (openSocket != null) { - return openSocket; + protected synchronized void setupSocket() { + MulticastSocket socket = (MulticastSocket) getSocket(); + if (socket != null) { + logger.debug("Socket already setup"); + return; } + try { logger.debug("Setup socket"); - setSocket(new MulticastSocket(getPort())); // must bind receive side - ((MulticastSocket) getSocket()).joinGroup(InetAddress.getByName(MCAST_ADDR)); - logger.debug("Initialized socket to {}:{} on {}:{}", getSocket().getRemoteSocketAddress(), - getSocket().getPort(), getSocket().getLocalAddress(), getSocket().getLocalPort()); + socket = new MulticastSocket(getPort()); + setSocket(socket); // must bind receive side + socket.joinGroup(InetAddress.getByName(MCAST_ADDR)); + logger.debug("Initialized socket to {}:{} on {}:{}", socket.getRemoteSocketAddress(), socket.getPort(), + socket.getLocalAddress(), socket.getLocalPort()); } catch (IOException e) { logger.error("Setup socket error", e); } - return getSocket(); } } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiDiscoverySocket.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiDiscoverySocket.java index ca4058824c856..bd0bdca21c9ff 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiDiscoverySocket.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiDiscoverySocket.java @@ -17,6 +17,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,35 +27,35 @@ * @author Dieter Schmidt - Initial contribution * */ +@NonNullByDefault public class XiaomiDiscoverySocket extends XiaomiSocket { private static final int MCAST_PORT = 4321; private final Logger logger = LoggerFactory.getLogger(XiaomiDiscoverySocket.class); - public XiaomiDiscoverySocket() { - super(); + public XiaomiDiscoverySocket(String owner) { + super(owner); } /** * Sets up the {@link XiaomiDiscoverySocket}. * * Connects the socket to the specific multicast address and port. - * Starts the {@link ReceiverThread} for the socket. */ @Override - DatagramSocket setupSocket() { + protected void setupSocket() { synchronized (XiaomiDiscoverySocket.class) { try { logger.debug("Setup discovery socket"); - setSocket(new DatagramSocket(0)); - logger.debug("Initialized socket to {}:{} on {}:{}", getSocket().getInetAddress(), - getSocket().getPort(), getSocket().getLocalAddress(), getSocket().getLocalPort()); + DatagramSocket socket = new DatagramSocket(0); + setSocket(socket); + logger.debug("Initialized socket to {}:{} on {}:{}", socket.getInetAddress(), socket.getPort(), + socket.getLocalAddress(), socket.getLocalPort()); } catch (IOException e) { logger.error("Setup socket error", e); } } - return getSocket(); } /** @@ -70,5 +71,4 @@ public void sendMessage(String message) { logger.error("Sending error", e); } } - } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiSocket.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiSocket.java index d999845ac7a84..b6f50e3ed0021 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiSocket.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiSocket.java @@ -17,11 +17,11 @@ import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mihome.internal.discovery.XiaomiBridgeDiscoveryService; import org.openhab.binding.mihome.internal.handler.XiaomiBridgeHandler; import org.slf4j.Logger; @@ -38,71 +38,66 @@ * @author Dieter Schmidt - JavaDoc, refactored, reviewed * */ +@NonNullByDefault public abstract class XiaomiSocket { static final String MCAST_ADDR = "224.0.0.50"; - private static final int BUFFER_LENGTH = 1024; - private DatagramPacket datagramPacket = new DatagramPacket(new byte[BUFFER_LENGTH], BUFFER_LENGTH); - - private List listeners = new CopyOnWriteArrayList<>(); + private static final int BUFFER_LENGTH = 1024; private static final JsonParser PARSER = new JsonParser(); private final Logger logger = LoggerFactory.getLogger(XiaomiSocket.class); - private static Map openSockets = new ConcurrentHashMap<>(); + private final DatagramPacket datagramPacket = new DatagramPacket(new byte[BUFFER_LENGTH], BUFFER_LENGTH); + private final Set listeners = new CopyOnWriteArraySet<>(); - private int port; - private DatagramSocket socket; - private Thread socketReceiveThread; + private final int port; + private @Nullable DatagramSocket socket; + private final Thread socketReceiveThread = new Thread(this::receiveData); /** * Sets up an {@link XiaomiSocket} with the MiHome multicast address and a random port * + * @param owner identifies the socket owner */ - public XiaomiSocket() { - this(0); + public XiaomiSocket(String owner) { + this(0, owner); } /** * Sets up an {@link XiaomiSocket} with the MiHome multicast address and a specific port * - * @param port - the socket will be bound to this port + * @param port the socket will be bound to this port + * @param owner identifies the socket owner */ - public XiaomiSocket(int port) { + public XiaomiSocket(int port, String owner) { this.port = port; + socketReceiveThread.setName("XiaomiSocketReceiveThread(" + port + ", " + owner + ")"); } - public void intialize() { + public void initialize() { setupSocket(); - runReceiveThread(); - } - - protected void runReceiveThread() { - socketReceiveThread = new ReceiverThread(); - socketReceiveThread.start(); - if (getSocket() != null) { - getOpenSockets().put(getSocket().getLocalPort(), getSocket()); - logger.debug("There are {} open sockets: {}", getOpenSockets().size(), getOpenSockets()); + if (!socketReceiveThread.isAlive()) { + logger.trace("Starting receiver thread {}", socketReceiveThread); + socketReceiveThread.start(); } } - abstract DatagramSocket setupSocket(); + protected abstract void setupSocket(); /** * Interrupts the {@link ReceiverThread} and closes the {@link XiaomiSocket}. */ private void closeSocket() { synchronized (XiaomiSocket.class) { - if (socketReceiveThread != null) { - logger.debug("Interrupting Thread {}", socketReceiveThread); - socketReceiveThread.interrupt(); - } - if (getSocket() != null) { - logger.debug("Closing socket {}", getSocket()); - openSockets.remove(getSocket().getLocalPort()); - getSocket().close(); - setSocket(null); + logger.debug("Interrupting receiver thread {}", socketReceiveThread); + socketReceiveThread.interrupt(); + + DatagramSocket socket = this.socket; + if (socket != null) { + logger.debug("Closing socket {}", socket); + socket.close(); + this.socket = null; } } } @@ -111,15 +106,16 @@ private void closeSocket() { * Registers a {@link XiaomiSocketListener} to be called back, when data is received. * If no {@link XiaomiSocket} exists, when the method is called, it is being set up. * - * @param listener - {@link XiaomiSocketListener} to be called back + * @param listener {@link XiaomiSocketListener} to be called back */ public synchronized void registerListener(XiaomiSocketListener listener) { - if (!getListeners().contains(listener)) { - logger.trace("Adding socket listener {}", listener); - getListeners().add(listener); + if (listeners.add(listener)) { + logger.trace("Added socket listener {}", listener); } - if (getSocket() == null) { - intialize(); + + DatagramSocket socket = this.socket; + if (socket == null) { + initialize(); } } @@ -127,12 +123,14 @@ public synchronized void registerListener(XiaomiSocketListener listener) { * Unregisters a {@link XiaomiSocketListener}. If there are no listeners left, * the {@link XiaomiSocket} is being closed. * - * @param listener - {@link XiaomiSocketListener} to be unregistered + * @param listener {@link XiaomiSocketListener} to be unregistered */ public synchronized void unregisterListener(XiaomiSocketListener listener) { - getListeners().remove(listener); + if (listeners.remove(listener)) { + logger.trace("Removed socket listener {}", listener); + } - if (getListeners().isEmpty()) { + if (listeners.isEmpty()) { closeSocket(); } } @@ -140,36 +138,35 @@ public synchronized void unregisterListener(XiaomiSocketListener listener) { /** * Sends a message through the {@link XiaomiSocket} to a specific address and port * - * @param message - Message to be sent - * @param address - Address, to which the message shall be sent - * @param port - Port, through which the message shall be sent + * @param message the message to be sent + * @param address the message destination address + * @param port the message destination port */ public void sendMessage(String message, InetAddress address, int port) { + DatagramSocket socket = this.socket; + if (socket == null) { + logger.error("Error while sending message (socket is null)"); + return; + } + try { byte[] sendData = message.getBytes(StandardCharsets.UTF_8); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, address, port); logger.trace("Sending message: {} to {}:{}", message, address, port); - getSocket().send(sendPacket); + socket.send(sendPacket); } catch (IOException e) { - logger.error("Sending error", e); + logger.error("Error while sending message", e); } } /** - * @return - the port number of this {@link XiaomiSocket} + * @return the port number of this {@link XiaomiSocket} */ public int getPort() { return port; } - /** - * @return - a list of already open sockets - */ - public static Map getOpenSockets() { - return openSockets; - } - - protected DatagramSocket getSocket() { + protected @Nullable DatagramSocket getSocket() { return socket; } @@ -177,71 +174,58 @@ protected void setSocket(DatagramSocket socket) { this.socket = socket; } - protected List getListeners() { - return listeners; - } - /** - * The thread, which waits for data on the {@link XiaomiSocket} and handles it, when received - * - * @author Patrick Boos - Initial contribution - * @author Dieter Schmidt - comments and synchronized block for callback instead of copy - * + * This method is the main method of the receiver thread for the {@link XiaomiBridgeSocket}. + * If the socket has data, it parses the data to a json object and calls all + * {@link XiaomiSocketListener} and passes the data to them. */ - private class ReceiverThread extends Thread { - @Override - public void run() { - logger.trace("Staring reveicer thread for socket on port {}", getSocket().getLocalPort()); - receiveData(getSocket(), datagramPacket); + private void receiveData() { + DatagramSocket socket = this.socket; + if (socket == null) { + logger.error("Failed to receive data (socket is null)"); + return; } - /** - * This method is the main method of the {@link ReceiverThread} for the {@link XiaomiBridgeSocket}. - * If the socket has data, it parses the data to a json object and calls all - * {@link XiaomiSocketListener} and passes the data to them. - * - * @param socket - The multicast socket to listen to - * @param dgram - The datagram to receive - */ - private void receiveData(DatagramSocket socket, DatagramPacket dgram) { - try { - while (true) { - logger.trace("Thread {} waiting for data on port {}", this, socket.getLocalPort()); - socket.receive(dgram); - InetAddress address = dgram.getAddress(); - logger.debug("Received Datagram from {}:{} on Port {}", address.getHostAddress(), dgram.getPort(), - socket.getLocalPort()); - String sentence = new String(dgram.getData(), 0, dgram.getLength()); - JsonObject message = PARSER.parse(sentence).getAsJsonObject(); - notifyAll(getListeners(), message, address); - logger.trace("Data received and notified {} listeners", getListeners().size()); - } - } catch (IOException e) { - if (!isInterrupted()) { - logger.error("Error while receiving", e); - } else { - logger.trace("Receiver thread was interrupted"); - } + Thread currentThread = Thread.currentThread(); + int localPort = socket.getLocalPort(); + + try { + while (!currentThread.isInterrupted()) { + logger.trace("Thread {} waiting for data on port {}", currentThread.getName(), localPort); + socket.receive(datagramPacket); + InetAddress address = datagramPacket.getAddress(); + logger.debug("Received Datagram from {}:{} on port {}", address.getHostAddress(), + datagramPacket.getPort(), localPort); + String sentence = new String(datagramPacket.getData(), 0, datagramPacket.getLength()); + JsonObject message = PARSER.parse(sentence).getAsJsonObject(); + notifyListeners(message, address); + logger.trace("Data received and notified {} listeners", listeners.size()); + } + } catch (IOException e) { + if (!currentThread.isInterrupted()) { + logger.error("Error while receiving", e); + } else { + logger.trace("Receiver thread was interrupted"); } - logger.debug("Receiver thread ended"); } + logger.debug("Receiver thread ended"); + } - /** - * Notifies all {@link XiaomiSocketListener} on the parent {@link XiaomiSocket}. First checks for any matching - * {@link XiaomiBridgeHandler}, before passing to any {@link XiaomiBridgeDiscoveryService}. - * - * @param listeners - a list of all {@link XiaomiSocketListener} to notify - * @param message - the data message as {@link JsonObject} - */ - synchronized void notifyAll(List listeners, JsonObject message, InetAddress address) { - for (XiaomiSocketListener listener : listeners) { - if (listener instanceof XiaomiBridgeHandler) { - if (((XiaomiBridgeHandler) listener).getHost().equals(address)) { - listener.onDataReceived(message); - } - } else if (listener instanceof XiaomiBridgeDiscoveryService) { + /** + * Notifies all {@link XiaomiSocketListener} on the parent {@link XiaomiSocket}. First checks for any matching + * {@link XiaomiBridgeHandler}, before passing to any {@link XiaomiBridgeDiscoveryService}. + * + * @param message the data message as {@link JsonObject} + * @param address the address from which the message was received + */ + private void notifyListeners(JsonObject message, InetAddress address) { + for (XiaomiSocketListener listener : listeners) { + if (listener instanceof XiaomiBridgeHandler) { + if (((XiaomiBridgeHandler) listener).getHost().equals(address)) { listener.onDataReceived(message); } + } else if (listener instanceof XiaomiBridgeDiscoveryService) { + listener.onDataReceived(message); } } } diff --git a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiSocketListener.java b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiSocketListener.java index 883af9605d6a0..47302e353b1c7 100644 --- a/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiSocketListener.java +++ b/bundles/org.openhab.binding.mihome/src/main/java/org/openhab/binding/mihome/internal/socket/XiaomiSocketListener.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.mihome.internal.socket; +import org.eclipse.jdt.annotation.NonNullByDefault; + import com.google.gson.JsonObject; /** @@ -20,6 +22,7 @@ * * @author Patrick Boos - Initial contribution */ +@NonNullByDefault public interface XiaomiSocketListener { /** * Callback method for the {@link XiaomiSocketListener} diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/binding/binding.xml index 7a6663fb91702..94437f2570fe5 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/binding/binding.xml @@ -4,8 +4,10 @@ xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd"> Xiaomi Mi Smart Home Binding - Connects to Xiaomi Smart Gateway v2 and allows to communicate with Xiaomi Mi Smart Home suite (also called Xiaomi Aqara). - The Gateway connects with a range of Xiaomi Zigbee sensors such as Wireless Switches, Wall Plugs or Temperature Sensors. + Connects to Xiaomi Smart Gateway v2 and allows to communicate with Xiaomi Mi Smart Home suite (also called + Xiaomi Aqara). + The Gateway connects with a range of Xiaomi Zigbee sensors such as Wireless Switches, Wall Plugs or + Temperature Sensors. Patrick Boos diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_86sw1.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_86sw1.xml index 3b7e30c28ae28..04b2b7032b520 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_86sw1.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_86sw1.xml @@ -6,7 +6,7 @@ - + Battery powered Aqara Switch with 1 Channel @@ -15,10 +15,10 @@ The pushbutton on the switch - - + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_86sw2.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_86sw2.xml index a362270fcd4f8..4bf9d687392db 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_86sw2.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_86sw2.xml @@ -6,7 +6,7 @@ - + Battery powered Aqara Switch with 2 channels @@ -23,9 +23,9 @@ Fires when both buttons are pressed simultaneously - - + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_ln1.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_ln1.xml index 41995850ced1e..89b97f80102d3 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_ln1.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_ln1.xml @@ -6,7 +6,7 @@ - + @@ -14,7 +14,7 @@ The pushbutton on the switch. - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_ln2.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_ln2.xml index 03a553fe588dc..63e8402ea9b82 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_ln2.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_ln2.xml @@ -6,7 +6,7 @@ - + @@ -19,6 +19,6 @@ The second pushbutton on the switch. - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_neutral1.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_neutral1.xml index 8acde05cc8810..56738b29c47c1 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_neutral1.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_neutral1.xml @@ -6,7 +6,7 @@ - + Mains powered Aqara Switch with 1 controllable Channel @@ -15,6 +15,6 @@ The pushbutton on the switch. - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_neutral2.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_neutral2.xml index 826b5108b4011..6d54014382ca3 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_neutral2.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/aqara_ctrl_neutral2.xml @@ -6,7 +6,7 @@ - + Mains powered Aqara Switch with 2 controllable Channels @@ -20,6 +20,6 @@ The second pushbutton on the switch. - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/basic.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/basic.xml index c459d0dd106e1..d190a372eb5d5 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/basic.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/basic.xml @@ -6,10 +6,13 @@ - + - This device is not supported by the binding but you can still add it to your OpenHAB configuration. All messages from the device are available as channels providing values to String Items. Please open an issue on the openhab-addons2 github page to get this device added to the binding in the future. Meanwhile you can parse the messages with rules and/or JSONPATH transformations. + This device is not supported by the binding but you can still add it to your OpenHAB configuration. All + messages from the device are available as channels providing values to String Items. Please open an issue on the + openhab-addons2 github page to get this device added to the binding in the future. Meanwhile you can parse the + messages with rules and/or JSONPATH transformations. @@ -36,6 +39,6 @@ Channel to write command parameters - Example: \"join_permission\":\"yes\" - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/bridge.xml index 18daf74779d3d..bdbd0451346d3 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/bridge.xml @@ -12,6 +12,6 @@ Xiaomi - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/channel.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/channel.xml index 675990311fdd8..6328658a3dc11 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/channel.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/channel.xml @@ -60,7 +60,7 @@ ColorTemperature - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/curtain.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/curtain.xml index 3f8454ab37dde..21dc4103d9108 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/curtain.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/curtain.xml @@ -6,14 +6,14 @@ - + Smart curtain controller for drawing back and forth fabric curtains. It has manual and remote operation modes. - + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/gateway.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/gateway.xml index c6e1d40953863..138a12c165306 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/gateway.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/gateway.xml @@ -6,19 +6,19 @@ - + Multifunctional Gateway with a built in light, ambient light sensor and capability to play sounds. - - - - - - - + + + + + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_cube.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_cube.xml index ddfbbe5979331..79406e101775e 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_cube.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_cube.xml @@ -6,7 +6,7 @@ - + Multifunctional controller equipped with an accelerometer and a gyroscope. Triggers the following @@ -16,10 +16,10 @@ - - + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_gas.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_gas.xml index 574f48925dffc..f83442a9f8fa2 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_gas.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_gas.xml @@ -6,15 +6,15 @@ - + - - + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_ht.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_ht.xml index dce443380e355..e755a3ddf8ee1 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_ht.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_ht.xml @@ -6,18 +6,19 @@ - + Reports temperature and humidity. Operating temperature: −20°C to 60°C. Operating humidity: 0 to 100%. - Sensor reports the temperature when there's a difference of around 0.5°C. If there is no significant temperature change then the sensor reports temperature once every 50 minutes. + Sensor reports the temperature when there's a difference of around 0.5°C. If there is no significant temperature + change then the sensor reports temperature once every 50 minutes. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_lock_aq1.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_lock_aq1.xml index 55ced9f17cd46..824ad65957e95 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_lock_aq1.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_lock_aq1.xml @@ -6,7 +6,7 @@ - + Live fingerprint unlock, password unlock, proximity card unlock, key unlock. @@ -20,9 +20,9 @@ - - + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_magnet.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_magnet.xml index 0fc042616a668..cdad5be87ca6d 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_magnet.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_magnet.xml @@ -6,18 +6,18 @@ - + Contact sensor mounted on doors or windows. Detects states: open and closed. - - - - - - + + + + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_magnet_aq2.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_magnet_aq2.xml index fd8499168c42a..344bf0c46db5f 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_magnet_aq2.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_magnet_aq2.xml @@ -6,18 +6,18 @@ - + Contact sensor mounted on doors or windows. Detects states: open and closed. - - - - - - + + + + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_motion.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_motion.xml index 23635add2397e..01bb02e9bfd33 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_motion.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_motion.xml @@ -6,18 +6,18 @@ - + Sensor that detects movement. Also called Occupancy Sensor or Human Body Sensor. After it detects motion, it goes to sleep for 1 minute. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_motion_aq2.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_motion_aq2.xml index 5eaad247195d0..eefe5536b7766 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_motion_aq2.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_motion_aq2.xml @@ -6,19 +6,19 @@ - + Sensor that detects movement. Also called Occupancy Sensor or Human Body Sensor. After it detects motion, it goes to sleep for 1 minute. - - - - - - + + + + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_plug.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_plug.xml index 3cf2ff6061bb0..10949f52791e7 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_plug.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_plug.xml @@ -6,16 +6,16 @@ - + Allows you to enable or disable the socket, read voltage, current and power consumption. - - - - + + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_smoke.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_smoke.xml index af27501d78dd3..2d9f96e3484f4 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_smoke.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_smoke.xml @@ -6,16 +6,16 @@ - + - - + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_switch.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_switch.xml index e9ed8dc74c06f..5b0eed65959d3 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_switch.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_switch.xml @@ -6,16 +6,16 @@ - + Round-shaped mini wireless switch that allows to trigger four types of event: single click, double click, long click press and long click release. - - - + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_switch_aq2.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_switch_aq2.xml index c12685c01cde7..82137cd23c665 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_switch_aq2.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_switch_aq2.xml @@ -6,16 +6,16 @@ - + Square-shaped mini wireless switch that allows to trigger four types of event: single click, double click, long click press and long click release. - - - + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_vibration.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_vibration.xml index 30adb1c70879b..6dea38090fe50 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_vibration.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_vibration.xml @@ -6,10 +6,13 @@ - + - Incorporates high-precision six-axis acceleration and gyroscopes, used for collecting external vibration and motion data. Used to monitor the door and windows with status, important items alarmed, and can also monitor user's bed activity, to help determine the quality of sleep. Installation: Click the reset button on the sensor in the selected sensor installation location. + Incorporates high-precision six-axis acceleration and gyroscopes, used for collecting external vibration + and motion data. Used to monitor the door and windows with status, important items alarmed, and can also monitor + user's bed activity, to help determine the quality of sleep. Installation: Click the reset button on the sensor in + the selected sensor installation location. @@ -18,10 +21,10 @@ - - + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_weather_v1.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_weather_v1.xml index dd0e3cefe8d9b..896b4d6a19f2c 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_weather_v1.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_weather_v1.xml @@ -6,19 +6,20 @@ - + Reports temperature and humidity. Operating temperature: −20°C to 60°C. Operating humidity: 0 to 100%. - Sensor reports the temperature when there's a difference of around 0.5°C. If there is no significant temperature change then the sensor reports temperature once every 50 minutes. + Sensor reports the temperature when there's a difference of around 0.5°C. If there is no significant temperature + change then the sensor reports temperature once every 50 minutes. - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_wleak_aq1.xml b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_wleak_aq1.xml index 1899fb8783720..a9e8404e49a0d 100644 --- a/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_wleak_aq1.xml +++ b/bundles/org.openhab.binding.mihome/src/main/resources/ESH-INF/thing/sensor_wleak_aq1.xml @@ -6,15 +6,14 @@ - + - - + + - + - diff --git a/bundles/org.openhab.binding.miio/README.md b/bundles/org.openhab.binding.miio/README.md index b0955db282854..51944dedc10a2 100644 --- a/bundles/org.openhab.binding.miio/README.md +++ b/bundles/org.openhab.binding.miio/README.md @@ -105,6 +105,7 @@ However, for devices that are unsupported, you may override the value and try to | Mi Fresh Air Ventilator A1 | miio:basic | [dmaker.airfresh.a1](#dmaker-airfresh-a1) | Yes | | | Xiao AI Smart Alarm Clock | miio:unsupported | zimi.clock.myk01 | No | | | Yeelight Smart Bath Heater | miio:unsupported | yeelight.bhf_light.v2 | No | | +| Gosund Plug | miio:basic | [cuco.plug.cp1](#cuco-plug-cp1) | Yes | | | XIAOMI MIJIA WIDETECH WDH318EFW1 Dehumidifier | miio:unsupported | nwt.derh.wdh318efw1 | No | | | Mi Air Purifier mb1 | miio:basic | [zhimi.airpurifier.mb1](#zhimi-airpurifier-mb1) | Yes | | | Mi Air Purifier 2S | miio:basic | [zhimi.airpurifier.mc1](#zhimi-airpurifier-mc1) | Yes | | @@ -175,6 +176,7 @@ However, for devices that are unsupported, you may override the value and try to | Rockrobo Xiaowa Vacuum v2 | miio:unsupported | roborock.vacuum.e2 | No | | | Xiaomi Mijia vacuum V-RVCLM21B | miio:unsupported | viomi.vacuum.v6 | No | | | Xiaomi Mijia vacuum STYJ02YM | miio:unsupported | viomi.vacuum.v7 | No | | +| Vacuum 1C STYTJ01ZHM | miio:basic | [dreame.vacuum.mc1808](#dreame-vacuum-mc1808) | Yes | | | roborock.vacuum.c1 | miio:unsupported | roborock.vacuum.c1 | No | | | Rockrobo Xiaowa Sweeper v2 | miio:unsupported | roborock.sweeper.e2v2 | No | | | Rockrobo Xiaowa Sweeper v3 | miio:unsupported | roborock.sweeper.e2v3 | No | | @@ -763,6 +765,16 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena | airFreshFilterDays | Number | Filter Days Remaining | | airFreshResetFilterA1 | String | Reset Filter | +### Gosund Plug (cuco.plug.cp1) Channels + +| Channel | Type | Description | +|------------------|---------|-------------------------------------| +| FirmwareRevision | String | Device Information-CurrentFirmware Version | +| Manufacturer | String | Device Information-Device Manufacturer | +| Model | String | Device Information-Device Model | +| SerialNumber | String | Device Information-Device Serial Number | +| On | Switch | Switch-Switch Status | + ### Mi Air Purifier mb1 (zhimi.airpurifier.mb1) Channels | Channel | Type | Description | @@ -1131,6 +1143,45 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena | current | Number | Current | | temperature | Number | Temperature | +### Vacuum 1C STYTJ01ZHM (dreame.vacuum.mc1808) Channels + +| Channel | Type | Description | +|------------------|---------|-------------------------------------| +| BatteryLevel | Number | Battery-Battery Level | +| ChargingState | Number | Battery-Charging State | +| FirmwareRevision | String | Device Information-Current Firmware Version | +| Manufacturer | String | Device Information-Device Manufacturer | +| Model | String | Device Information-Device Model | +| SerialNumber | String | Device Information-Device Serial Number | +| Fault | Number | Robot Cleaner-Device Fault | +| Status | Number | Robot Cleaner-Status | +| BrushLeftTime | String | Main Cleaning Brush-Brush Left Time | +| BrushLifeLevel | Number | Main Cleaning Brush-Brush Life Level | +| FilterLifeLevel | Number | Filter-Filter Life Level | +| FilterLeftTime | String | Filter-Filter Left Time | +| BrushLeftTime1 | String | Side Cleaning Brush-Brush Left Time | +| BrushLifeLevel1 | Number | Side Cleaning Brush-Brush Life Level | +| WorkMode | Number | clean-workmode | +| Area | String | clean-area | +| Timer | String | clean-timer | +| Mode | Number | clean-mode | +| TotalCleanTime | String | clean-total time | +| TotalCleanTimes | String | clean-total times | +| TotalCleanArea | String | clean-Total area | +| CleanLogStartTime | String | clean-Start Time | +| ButtonLed | String | clean-led | +| TaskDone | Number | clean-task done | +| LifeSieve | String | consumable-life-sieve | +| LifeBrushSide | String | consumable-life-brush-side | +| LifeBrushMain | String | consumable-life-brush-main | +| Enable | Switch | annoy-enable | +| StartTime | String | annoy-start-time | +| StopTime | String | annoy-stop-time | +| MapView | String | map-map-view | +| Volume | Number | audio-volume | +| VoicePackets | String | audio-voiceId | +| TimeZone | String | timezone | + ### Mijia 1 Gang Wall Smart Switch (WIFI) - PTX switch (090615.switch.xswitch01) Channels | Channel | Type | Description | @@ -1206,7 +1257,7 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena |------------------|---------|-------------------------------------| | power | Switch | Power | | brightness | Dimmer | Brightness | -| delayoff | String | Shutdown Timer | +| delayoff | Number | Shutdown Timer | | colorTemperature | Number | Color Temperature | | colorMode | String | Color Mode | | toggle | Switch | toggle | @@ -1219,7 +1270,7 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena |------------------|---------|-------------------------------------| | power | Switch | Power | | brightness | Dimmer | Brightness | -| delayoff | String | Shutdown Timer | +| delayoff | Number | Shutdown Timer | | colorTemperature | Number | Color Temperature | | colorMode | String | Color Mode | | toggle | Switch | toggle | @@ -1495,7 +1546,7 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena |------------------|---------|-------------------------------------| | power | Switch | Power | | brightness | Dimmer | Brightness | -| delayoff | String | Shutdown Timer | +| delayoff | Number | Shutdown Timer | | colorTemperature | Number | Color Temperature | | colorMode | String | Color Mode | | toggle | Switch | toggle | @@ -1508,7 +1559,7 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena |------------------|---------|-------------------------------------| | power | Switch | Power | | brightness | Dimmer | Brightness | -| delayoff | String | Shutdown Timer | +| delayoff | Number | Shutdown Timer | | colorTemperature | Number | Color Temperature | | colorMode | String | Color Mode | | toggle | Switch | toggle | @@ -1532,7 +1583,7 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena |------------------|---------|-------------------------------------| | power | Switch | Power | | brightness | Dimmer | Brightness | -| delayoff | String | Shutdown Timer | +| delayoff | Number | Shutdown Timer | | colorTemperature | Number | Color Temperature | | colorMode | String | Color Mode | | toggle | Switch | toggle | @@ -1545,7 +1596,7 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena |------------------|---------|-------------------------------------| | power | Switch | Power | | brightness | Dimmer | Brightness | -| delayoff | String | Shutdown Timer | +| delayoff | Number | Shutdown Timer | | colorTemperature | Number | Color Temperature | | colorMode | String | Color Mode | | toggle | Switch | toggle | @@ -1558,7 +1609,7 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena |------------------|---------|-------------------------------------| | power | Switch | Power | | brightness | Dimmer | Brightness | -| delayoff | String | Shutdown Timer | +| delayoff | Number | Shutdown Timer | | colorTemperature | Number | Color Temperature | | colorMode | String | Color Mode | | toggle | Switch | toggle | @@ -1571,7 +1622,7 @@ e.g. `smarthome:send actionCommand 'upd_timer["1498595904821", "on"]'` would ena |------------------|---------|-------------------------------------| | power | Switch | Power | | brightness | Dimmer | Brightness | -| delayoff | String | Shutdown Timer | +| delayoff | Number | Shutdown Timer | | colorTemperature | Number | Color Temperature | | colorMode | String | Color Mode | | toggle | Switch | toggle | @@ -2200,6 +2251,19 @@ Number airFreshFilterDays "Filter Days Remaining" (G_airfresh) {channel="miio:ba String airFreshResetFilterA1 "Reset Filter" (G_airfresh) {channel="miio:basic:airfresh:airFreshResetFilterA1"} ``` +### Gosund Plug (cuco.plug.cp1) item file lines + +note: Autogenerated example. Replace the id (plug) in the channel with your own. Replace `basic` with `generic` in the thing UID depending on how your thing was discovered. + +```java +Group G_plug "Gosund Plug" +String FirmwareRevision "Device Information-CurrentFirmware Version" (G_plug) {channel="miio:basic:plug:FirmwareRevision"} +String Manufacturer "Device Information-Device Manufacturer" (G_plug) {channel="miio:basic:plug:Manufacturer"} +String Model "Device Information-Device Model" (G_plug) {channel="miio:basic:plug:Model"} +String SerialNumber "Device Information-Device Serial Number" (G_plug) {channel="miio:basic:plug:SerialNumber"} +Switch On "Switch-Switch Status" (G_plug) {channel="miio:basic:plug:On"} +``` + ### Mi Air Purifier mb1 (zhimi.airpurifier.mb1) item file lines note: Autogenerated example. Replace the id (airpurifier) in the channel with your own. Replace `basic` with `generic` in the thing UID depending on how your thing was discovered. @@ -2652,6 +2716,48 @@ Number current "Current" (G_powerstrip) {channel="miio:basic:powerstrip:current" Number temperature "Temperature" (G_powerstrip) {channel="miio:basic:powerstrip:temperature"} ``` +### Vacuum 1C STYTJ01ZHM (dreame.vacuum.mc1808) item file lines + +note: Autogenerated example. Replace the id (vacuum) in the channel with your own. Replace `basic` with `generic` in the thing UID depending on how your thing was discovered. + +```java +Group G_vacuum "Vacuum 1C STYTJ01ZHM" +Number BatteryLevel "Battery-Battery Level" (G_vacuum) {channel="miio:basic:vacuum:BatteryLevel"} +Number ChargingState "Battery-Charging State" (G_vacuum) {channel="miio:basic:vacuum:ChargingState"} +String FirmwareRevision "Device Information-Current Firmware Version" (G_vacuum) {channel="miio:basic:vacuum:FirmwareRevision"} +String Manufacturer "Device Information-Device Manufacturer" (G_vacuum) {channel="miio:basic:vacuum:Manufacturer"} +String Model "Device Information-Device Model" (G_vacuum) {channel="miio:basic:vacuum:Model"} +String SerialNumber "Device Information-Device Serial Number" (G_vacuum) {channel="miio:basic:vacuum:SerialNumber"} +Number Fault "Robot Cleaner-Device Fault" (G_vacuum) {channel="miio:basic:vacuum:Fault"} +Number Status "Robot Cleaner-Status" (G_vacuum) {channel="miio:basic:vacuum:Status"} +String BrushLeftTime "Main Cleaning Brush-Brush Left Time" (G_vacuum) {channel="miio:basic:vacuum:BrushLeftTime"} +Number BrushLifeLevel "Main Cleaning Brush-Brush Life Level" (G_vacuum) {channel="miio:basic:vacuum:BrushLifeLevel"} +Number FilterLifeLevel "Filter-Filter Life Level" (G_vacuum) {channel="miio:basic:vacuum:FilterLifeLevel"} +String FilterLeftTime "Filter-Filter Left Time" (G_vacuum) {channel="miio:basic:vacuum:FilterLeftTime"} +String BrushLeftTime1 "Side Cleaning Brush-Brush Left Time" (G_vacuum) {channel="miio:basic:vacuum:BrushLeftTime1"} +Number BrushLifeLevel1 "Side Cleaning Brush-Brush Life Level" (G_vacuum) {channel="miio:basic:vacuum:BrushLifeLevel1"} +Number WorkMode "clean-workmode" (G_vacuum) {channel="miio:basic:vacuum:WorkMode"} +String Area "clean-area" (G_vacuum) {channel="miio:basic:vacuum:Area"} +String Timer "clean-timer" (G_vacuum) {channel="miio:basic:vacuum:Timer"} +Number Mode "clean-mode" (G_vacuum) {channel="miio:basic:vacuum:Mode"} +String TotalCleanTime "clean-total time" (G_vacuum) {channel="miio:basic:vacuum:TotalCleanTime"} +String TotalCleanTimes "clean-total times" (G_vacuum) {channel="miio:basic:vacuum:TotalCleanTimes"} +String TotalCleanArea "clean-Total area" (G_vacuum) {channel="miio:basic:vacuum:TotalCleanArea"} +String CleanLogStartTime "clean-Start Time" (G_vacuum) {channel="miio:basic:vacuum:CleanLogStartTime"} +String ButtonLed "clean-led" (G_vacuum) {channel="miio:basic:vacuum:ButtonLed"} +Number TaskDone "clean-task done" (G_vacuum) {channel="miio:basic:vacuum:TaskDone"} +String LifeSieve "consumable-life-sieve" (G_vacuum) {channel="miio:basic:vacuum:LifeSieve"} +String LifeBrushSide "consumable-life-brush-side" (G_vacuum) {channel="miio:basic:vacuum:LifeBrushSide"} +String LifeBrushMain "consumable-life-brush-main" (G_vacuum) {channel="miio:basic:vacuum:LifeBrushMain"} +Switch Enable "annoy-enable" (G_vacuum) {channel="miio:basic:vacuum:Enable"} +String StartTime "annoy-start-time" (G_vacuum) {channel="miio:basic:vacuum:StartTime"} +String StopTime "annoy-stop-time" (G_vacuum) {channel="miio:basic:vacuum:StopTime"} +String MapView "map-map-view" (G_vacuum) {channel="miio:basic:vacuum:MapView"} +Number Volume "audio-volume" (G_vacuum) {channel="miio:basic:vacuum:Volume"} +String VoicePackets "audio-voiceId" (G_vacuum) {channel="miio:basic:vacuum:VoicePackets"} +String TimeZone "timezone" (G_vacuum) {channel="miio:basic:vacuum:TimeZone"} +``` + ### Mijia 1 Gang Wall Smart Switch (WIFI) - PTX switch (090615.switch.xswitch01) item file lines note: Autogenerated example. Replace the id (switch) in the channel with your own. Replace `basic` with `generic` in the thing UID depending on how your thing was discovered. @@ -2759,7 +2865,7 @@ note: Autogenerated example. Replace the id (light) in the channel with your own Group G_light "Yeelight Lamp" Switch power "Power" (G_light) {channel="miio:basic:light:power"} Dimmer brightness "Brightness" (G_light) {channel="miio:basic:light:brightness"} -String delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} +Number delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} Number colorTemperature "Color Temperature" (G_light) {channel="miio:basic:light:colorTemperature"} String colorMode "Color Mode" (G_light) {channel="miio:basic:light:colorMode"} Switch toggle "toggle" (G_light) {channel="miio:basic:light:toggle"} @@ -2775,7 +2881,7 @@ note: Autogenerated example. Replace the id (light) in the channel with your own Group G_light "Yeelight Lamp" Switch power "Power" (G_light) {channel="miio:basic:light:power"} Dimmer brightness "Brightness" (G_light) {channel="miio:basic:light:brightness"} -String delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} +Number delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} Number colorTemperature "Color Temperature" (G_light) {channel="miio:basic:light:colorTemperature"} String colorMode "Color Mode" (G_light) {channel="miio:basic:light:colorMode"} Switch toggle "toggle" (G_light) {channel="miio:basic:light:toggle"} @@ -3114,7 +3220,7 @@ note: Autogenerated example. Replace the id (light) in the channel with your own Group G_light "Yeelight Strip" Switch power "Power" (G_light) {channel="miio:basic:light:power"} Dimmer brightness "Brightness" (G_light) {channel="miio:basic:light:brightness"} -String delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} +Number delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} Number colorTemperature "Color Temperature" (G_light) {channel="miio:basic:light:colorTemperature"} String colorMode "Color Mode" (G_light) {channel="miio:basic:light:colorMode"} Switch toggle "toggle" (G_light) {channel="miio:basic:light:toggle"} @@ -3130,7 +3236,7 @@ note: Autogenerated example. Replace the id (light) in the channel with your own Group G_light "Yeelight Strip" Switch power "Power" (G_light) {channel="miio:basic:light:power"} Dimmer brightness "Brightness" (G_light) {channel="miio:basic:light:brightness"} -String delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} +Number delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} Number colorTemperature "Color Temperature" (G_light) {channel="miio:basic:light:colorTemperature"} String colorMode "Color Mode" (G_light) {channel="miio:basic:light:colorMode"} Switch toggle "toggle" (G_light) {channel="miio:basic:light:toggle"} @@ -3160,7 +3266,7 @@ note: Autogenerated example. Replace the id (light) in the channel with your own Group G_light "Yeelight Color Bulb" Switch power "Power" (G_light) {channel="miio:basic:light:power"} Dimmer brightness "Brightness" (G_light) {channel="miio:basic:light:brightness"} -String delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} +Number delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} Number colorTemperature "Color Temperature" (G_light) {channel="miio:basic:light:colorTemperature"} String colorMode "Color Mode" (G_light) {channel="miio:basic:light:colorMode"} Switch toggle "toggle" (G_light) {channel="miio:basic:light:toggle"} @@ -3176,7 +3282,7 @@ note: Autogenerated example. Replace the id (light) in the channel with your own Group G_light "Yeelight Color Bulb YLDP06YL 10W" Switch power "Power" (G_light) {channel="miio:basic:light:power"} Dimmer brightness "Brightness" (G_light) {channel="miio:basic:light:brightness"} -String delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} +Number delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} Number colorTemperature "Color Temperature" (G_light) {channel="miio:basic:light:colorTemperature"} String colorMode "Color Mode" (G_light) {channel="miio:basic:light:colorMode"} Switch toggle "toggle" (G_light) {channel="miio:basic:light:toggle"} @@ -3192,7 +3298,7 @@ note: Autogenerated example. Replace the id (light) in the channel with your own Group G_light "Yeelight Color Bulb YLDP02YL 9W" Switch power "Power" (G_light) {channel="miio:basic:light:power"} Dimmer brightness "Brightness" (G_light) {channel="miio:basic:light:brightness"} -String delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} +Number delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} Number colorTemperature "Color Temperature" (G_light) {channel="miio:basic:light:colorTemperature"} String colorMode "Color Mode" (G_light) {channel="miio:basic:light:colorMode"} Switch toggle "toggle" (G_light) {channel="miio:basic:light:toggle"} @@ -3208,7 +3314,7 @@ note: Autogenerated example. Replace the id (light) in the channel with your own Group G_light "Yeelight Bulb YLDP13YL (8,5W)" Switch power "Power" (G_light) {channel="miio:basic:light:power"} Dimmer brightness "Brightness" (G_light) {channel="miio:basic:light:brightness"} -String delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} +Number delayoff "Shutdown Timer" (G_light) {channel="miio:basic:light:delayoff"} Number colorTemperature "Color Temperature" (G_light) {channel="miio:basic:light:colorTemperature"} String colorMode "Color Mode" (G_light) {channel="miio:basic:light:colorMode"} Switch toggle "toggle" (G_light) {channel="miio:basic:light:toggle"} diff --git a/bundles/org.openhab.binding.miio/pom.xml b/bundles/org.openhab.binding.miio/pom.xml index cc41d8bb921b6..4548505002ab1 100644 --- a/bundles/org.openhab.binding.miio/pom.xml +++ b/bundles/org.openhab.binding.miio/pom.xml @@ -1,9 +1,11 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.miio openHAB Add-ons :: Bundles :: Xiaomi Mi IO Binding diff --git a/bundles/org.openhab.binding.miio/src/main/feature/feature.xml b/bundles/org.openhab.binding.miio/src/main/feature/feature.xml index b68528bbb0050..1ab32f26fa245 100644 --- a/bundles/org.openhab.binding.miio/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.miio/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - mvn:org.openhab.addons.bundles/org.openhab.binding.miio/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + mvn:org.openhab.addons.bundles/org.openhab.binding.miio/${project.version} + diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoBindingConstants.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoBindingConstants.java index 66f79d6615fcc..fc2c1b7a59090 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoBindingConstants.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoBindingConstants.java @@ -111,5 +111,4 @@ public final class MiIoBindingConstants { .of("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "00000000000000000000000000000000").collect(Collectors.toSet())); public static final String DATABASE_PATH = "database/"; - } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCommand.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCommand.java index c3103ebe91dbe..cc34395a8c804 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCommand.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCommand.java @@ -35,6 +35,7 @@ public enum MiIoCommand { SET_MODE_BASIC("set_mode"), SET_POWER("set_power"), SET_BRIGHT("set_bright"), + SET_RGB("set_rgb"), SET_WIFI_LET("set_wifi_led"), SET_FAVORITE("set_level_favorite"), ACTION("action"), @@ -103,5 +104,4 @@ public static MiIoCommand getCommand(String commandString) { } return UNKNOWN; } - } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCrypto.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCrypto.java index 428b4b1932e41..18ae3b0383508 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCrypto.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoCrypto.java @@ -40,7 +40,7 @@ public static byte[] md5(byte[] source) throws MiIoCryptoException { MessageDigest m = MessageDigest.getInstance("MD5"); return m.digest(source); } catch (NoSuchAlgorithmException e) { - throw new MiIoCryptoException(e.getMessage(),e); + throw new MiIoCryptoException(e.getMessage(), e); } } @@ -52,7 +52,7 @@ public static byte[] iv(byte[] token) throws MiIoCryptoException { System.arraycopy(token, 0, ivbuf, 16, 16); return m.digest(ivbuf); } catch (NoSuchAlgorithmException e) { - throw new MiIoCryptoException(e.getMessage(),e); + throw new MiIoCryptoException(e.getMessage(), e); } } @@ -66,7 +66,7 @@ public static byte[] encrypt(byte[] cipherText, byte[] key, byte[] iv) throws Mi return encrypted; } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { - throw new MiIoCryptoException(e.getMessage(),e); + throw new MiIoCryptoException(e.getMessage(), e); } } @@ -84,7 +84,7 @@ public static byte[] decrypt(byte[] cipherText, byte[] key, byte[] iv) throws Mi return (crypted); } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { - throw new MiIoCryptoException(e.getMessage(),e); + throw new MiIoCryptoException(e.getMessage(), e); } } @@ -106,7 +106,7 @@ public static String decryptToken(byte[] cipherText) throws MiIoCryptoException } } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException | BadPaddingException e) { - throw new MiIoCryptoException(e.getMessage(),e); + throw new MiIoCryptoException(e.getMessage(), e); } } } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoDevices.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoDevices.java index 95c78cf487403..d5f1330a894ac 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoDevices.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoDevices.java @@ -54,6 +54,7 @@ public enum MiIoDevices { AIRFRESH_A1("dmaker.airfresh.a1", "Mi Fresh Air Ventilator A1", THING_TYPE_BASIC), ALARM_CLOCK_MYK01("zimi.clock.myk01", "Xiao AI Smart Alarm Clock", THING_TYPE_UNSUPPORTED), BATHHEATER_V2("yeelight.bhf_light.v2", "Yeelight Smart Bath Heater", THING_TYPE_UNSUPPORTED), + CUCOPLUG_CP1("cuco.plug.cp1", "Gosund Plug", THING_TYPE_BASIC), DEHUMIDIFIER_FW1("nwt.derh.wdh318efw1", "XIAOMI MIJIA WIDETECH WDH318EFW1 Dehumidifier", THING_TYPE_UNSUPPORTED), ZHIMI_AIRPURIFIER_MB1("zhimi.airpurifier.mb1", "Mi Air Purifier mb1", THING_TYPE_BASIC), ZHIMI_AIRPURIFIER_MC1("zhimi.airpurifier.mc1", "Mi Air Purifier 2S", THING_TYPE_BASIC), @@ -125,6 +126,7 @@ public enum MiIoDevices { VACUUME2("roborock.vacuum.e2", "Rockrobo Xiaowa Vacuum v2", THING_TYPE_UNSUPPORTED), VACUUME_V6("viomi.vacuum.v6", "Xiaomi Mijia vacuum V-RVCLM21B", THING_TYPE_UNSUPPORTED), VACUUME_V7("viomi.vacuum.v7", "Xiaomi Mijia vacuum STYJ02YM", THING_TYPE_UNSUPPORTED), + VACUUM_MC1808("dreame.vacuum.mc1808", "Vacuum 1C STYTJ01ZHM", THING_TYPE_BASIC), ROBOROCK_VACUUM_C1("roborock.vacuum.c1", "roborock.vacuum.c1", THING_TYPE_UNSUPPORTED), SWEEPER2("roborock.sweeper.e2v2", "Rockrobo Xiaowa Sweeper v2", THING_TYPE_UNSUPPORTED), SWEEPER3("roborock.sweeper.e2v3", "Rockrobo Xiaowa Sweeper v3", THING_TYPE_UNSUPPORTED), diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoHandlerFactory.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoHandlerFactory.java index 7fe26799c5bc8..66b282a71187c 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoHandlerFactory.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoHandlerFactory.java @@ -14,7 +14,7 @@ import static org.openhab.binding.miio.internal.MiIoBindingConstants.*; -import java.util.Dictionary; +import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -31,7 +31,6 @@ import org.openhab.binding.miio.internal.handler.MiIoGenericHandler; import org.openhab.binding.miio.internal.handler.MiIoUnsupportedHandler; import org.openhab.binding.miio.internal.handler.MiIoVacuumHandler; -import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -54,15 +53,9 @@ public class MiIoHandlerFactory extends BaseThingHandlerFactory { @Activate public MiIoHandlerFactory(@Reference MiIoDatabaseWatchService miIoDatabaseWatchService, - @Reference CloudConnector cloudConnector) { + @Reference CloudConnector cloudConnector, Map properties) { this.miIoDatabaseWatchService = miIoDatabaseWatchService; this.cloudConnector = cloudConnector; - } - - @Override - protected void activate(ComponentContext componentContext) { - super.activate(componentContext); - Dictionary properties = componentContext.getProperties(); @Nullable String username = (String) properties.get("username"); @Nullable diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoInfoDTO.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoInfoDTO.java index 8da9826bb3576..b3acc48a100dc 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoInfoDTO.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoInfoDTO.java @@ -23,10 +23,10 @@ public class MiIoInfoDTO { @SerializedName("life") @Expose - public Integer life; + public Long life; @SerializedName("cfg_time") @Expose - public Integer cfgTime; + public Long cfgTime; @SerializedName("token") @Expose public String token; @@ -41,7 +41,7 @@ public class MiIoInfoDTO { public String hwVer; @SerializedName("uid") @Expose - public Integer uid; + public Long uid; @SerializedName("model") @Expose public String model; @@ -53,5 +53,5 @@ public class MiIoInfoDTO { public String mcuFwVer; @SerializedName("mmfree") @Expose - public Integer mmfree; + public Long mmfree; } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoMessageListener.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoMessageListener.java index d4e1cdd854388..32b44e6f84044 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoMessageListener.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/MiIoMessageListener.java @@ -38,5 +38,4 @@ public interface MiIoMessageListener { * @param statusDetail Status details text */ void onStatusUpdated(ThingStatus status, ThingStatusDetail statusDetail); - } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/Utils.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/Utils.java index d5d2cc0dda4bd..444b5b1fd9f60 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/Utils.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/Utils.java @@ -79,6 +79,17 @@ public static String getHex(byte[] raw) { return hex.toString(); } + public static String obfuscateToken(String tokenString) { + if (tokenString.length() > 8) { + String tokenText = tokenString.substring(0, 8) + .concat((tokenString.length() < 24) ? tokenString.substring(8).replaceAll(".", "X") + : tokenString.substring(8, 24).replaceAll(".", "X").concat(tokenString.substring(24))); + return tokenText; + } else { + return tokenString; + } + } + public static JsonObject convertFileToJSON(URL fileName) throws JsonIOException, JsonSyntaxException, IOException { JsonObject jsonObject = new JsonObject(); JsonParser parser = new JsonParser(); diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/ActionConditions.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/ActionConditions.java index fdc92223f03b2..fb86a4aadf300 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/ActionConditions.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/ActionConditions.java @@ -16,6 +16,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.HSBType; +import org.eclipse.smarthome.core.types.Command; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,35 +42,33 @@ public class ActionConditions { * @return value in case firmware is matching, return null if not */ private static @Nullable JsonElement firmwareCheck(MiIoDeviceActionCondition condition, - Map deviceVariables, @Nullable JsonElement value) { + @Nullable Map deviceVariables, @Nullable JsonElement value) { // TODO: placeholder for firmware version check to allow for firmware dependent actions return value; } /** - * Check if the value is a valid brightness between 1-99. - * If <1 returns Off, if >99 returns On to activate the power On/Off switch + * Check if the value is a valid brightness for operating power On/Off switch. + * If brightness <1 returns Off, if >=1 returns On * * @param value * @return */ private static @Nullable JsonElement brightness(@Nullable JsonElement value) { if (value != null && value.isJsonPrimitive() && value.getAsJsonPrimitive().isNumber()) { - int intVal = value.getAsInt(); - if (intVal > 99) { - return new JsonPrimitive("on"); - } - if (intVal < 1) { + if (value.getAsInt() < 1) { return new JsonPrimitive("off"); + } else { + return new JsonPrimitive("on"); } } else { LOGGER.debug("Could not parse brightness. Value '{}' is not an int", value); } - return null; + return value; } /** - * Check if the value is a valid brightness between 1-99 which can be send to brightness channel. + * Check if the value is a valid brightness between 1-100 which can be send to brightness channel. * If not returns a null * * @param value @@ -77,17 +77,36 @@ public class ActionConditions { private static @Nullable JsonElement brightnessExists(@Nullable JsonElement value) { if (value != null && value.isJsonPrimitive() && value.getAsJsonPrimitive().isNumber()) { int intVal = value.getAsInt(); - if (intVal > 0 && intVal < 99) { + if (intVal > 0 && intVal <= 100) { return value; + } else if (intVal > 100) { + return new JsonPrimitive(100); } + return null; } else { LOGGER.debug("Could not parse brightness. Value '{}' is not an int", value); } + return value; + } + + /** + * Check if the value is a color which can be send to Color channel. + * If not returns a null + * + * @param command + * + * @param value + * @return + */ + private static @Nullable JsonElement hsbOnly(@Nullable Command command, @Nullable JsonElement value) { + if (command != null && command instanceof HSBType) { + return value; + } return null; } public static @Nullable JsonElement executeAction(MiIoDeviceActionCondition condition, - Map deviceVariables, @Nullable JsonElement value) { + @Nullable Map deviceVariables, @Nullable JsonElement value, @Nullable Command command) { switch (condition.getName().toUpperCase()) { case "FIRMWARE": return firmwareCheck(condition, deviceVariables, value); @@ -95,6 +114,8 @@ public class ActionConditions { return brightnessExists(value); case "BRIGHTNESSONOFF": return brightness(value); + case "HSBONLY": + return hsbOnly(command, value); default: LOGGER.debug("Condition {} not found. Returning '{}'", condition, value != null ? value.toString() : ""); diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/Conversions.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/Conversions.java index d4cc8ef6fed38..557270911446c 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/Conversions.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/Conversions.java @@ -72,5 +72,4 @@ public static JsonElement execute(String transfortmation, JsonElement value) { return value; } } - } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoBasicDevice.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoBasicDevice.java index 065c8c5e78930..0815d622d6d33 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoBasicDevice.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/basic/MiIoBasicDevice.java @@ -36,5 +36,4 @@ public DeviceMapping getDevice() { public void setDevice(DeviceMapping deviceMapping) { this.deviceMapping = deviceMapping; } - } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/CloudConnector.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/CloudConnector.java index b42f504836aae..3d89cf9020666 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/CloudConnector.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/CloudConnector.java @@ -159,7 +159,7 @@ public void setCredentials(@Nullable String username, @Nullable String password, private boolean logon() { if (username.isEmpty() || password.isEmpty()) { - logger.info("No Xiaomi cloud credentials. Cloud connectivity disabled"); + logger.debug("No Xiaomi cloud credentials. Cloud connectivity disabled"); logger.debug("Logon details: username: '{}', pass: '{}', country: '{}'", username, password.replaceAll(".", "*"), country); return connected; diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/MiCloudConnector.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/MiCloudConnector.java index 1b41b669405a4..0e446b6a73c48 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/MiCloudConnector.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/cloud/MiCloudConnector.java @@ -96,7 +96,6 @@ public MiCloudConnector(String username, String password, HttpClient httpClient) } clientId = (new Random().ints(97, 122 + 1).limit(6) .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append).toString()); - } void startClient() throws MiCloudException { diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/discovery/MiIoDiscovery.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/discovery/MiIoDiscovery.java index 6ecf10dec66c8..8508cbca533be 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/discovery/MiIoDiscovery.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/discovery/MiIoDiscovery.java @@ -160,10 +160,11 @@ private void discovered(String ip, byte[] response) { logger.debug( "No token discovered for device {}. For options how to get the token, check the binding readme.", id); - dr = dr.withRepresentationProperty(id).withLabel(label); + dr = dr.withRepresentationProperty(PROPERTY_DID).withLabel(label); } else { logger.debug("Discovered token for device {}: {}", id, token); - dr = dr.withProperty(PROPERTY_TOKEN, token).withRepresentationProperty(id).withLabel(label + " with token"); + dr = dr.withProperty(PROPERTY_TOKEN, token).withRepresentationProperty(PROPERTY_DID) + .withLabel(label + " with token"); } if (!country.isEmpty() && isOnline) { dr = dr.withProperty(PROPERTY_CLOUDSERVER, country); diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/discovery/MiIoDiscoveryParticipant.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/discovery/MiIoDiscoveryParticipant.java index ebc6af9dabeed..f91312f94230c 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/discovery/MiIoDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/discovery/MiIoDiscoveryParticipant.java @@ -66,9 +66,9 @@ public String getServiceType() { logger.trace("mDNS Could not identify Type / Device Id from '{}'", service.getName()); return null; } - int did; + long did; try { - did = Integer.parseUnsignedInt(id[1]); + did = Long.parseUnsignedLong(id[1]); } catch (Exception e) { logger.trace("mDNS Could not identify Device ID from '{}'", id[1]); return null; @@ -107,8 +107,8 @@ public String getServiceType() { String label = "Xiaomi Mi Device " + id + " (" + Long.parseUnsignedLong(id, 16) + ") " + service.getName(); properties.put(PROPERTY_HOST_IP, inetAddress); properties.put(PROPERTY_DID, id); - result = DiscoveryResultBuilder.create(uid).withProperties(properties).withRepresentationProperty(id) - .withLabel(label).build(); + result = DiscoveryResultBuilder.create(uid).withProperties(properties) + .withRepresentationProperty(PROPERTY_DID).withLabel(label).build(); logger.debug("Mi IO mDNS Discovery found {} with address '{}:{}' name '{}'", uid, inetAddress, service.getPort(), label); } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoAbstractHandler.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoAbstractHandler.java index 426e2c5fe4570..98a68ac9281ab 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoAbstractHandler.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoAbstractHandler.java @@ -107,6 +107,11 @@ public void initialize() { getThing().getThingTypeUID()); final MiIoBindingConfiguration configuration = getConfigAs(MiIoBindingConfiguration.class); this.configuration = configuration; + if (configuration.host == null || configuration.host.isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "IP address required. Configure IP address"); + return; + } if (!tokenCheckPass(configuration.token)) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Token required. Configure token"); return; @@ -130,7 +135,10 @@ public void initialize() { updateStatus(ThingStatus.OFFLINE); } - private boolean tokenCheckPass(String tokenSting) { + private boolean tokenCheckPass(@Nullable String tokenSting) { + if (tokenSting == null) { + return false; + } switch (tokenSting.length()) { case 16: token = tokenSting.getBytes(); @@ -282,6 +290,9 @@ protected void disconnected(String message) { return miioCom; } final MiIoBindingConfiguration configuration = getConfigAs(MiIoBindingConfiguration.class); + if (configuration.host == null || configuration.host.isEmpty()) { + return null; + } @Nullable String deviceId = configuration.deviceId; try { @@ -297,6 +308,8 @@ protected void disconnected(String message) { miioCom.registerListener(this); this.miioCom = miioCom; return miioCom; + } else { + miioCom.close(); } } else { logger.debug("No device ID defined. Retrieving Mi device ID"); @@ -317,6 +330,8 @@ protected void disconnected(String message) { miioCom.registerListener(this); this.miioCom = miioCom; return miioCom; + } else { + miioCom.close(); } } logger.debug("Ping response from device {} at {} FAILED", configuration.deviceId, configuration.host); @@ -474,5 +489,4 @@ public void onMessageReceived(MiIoSendCommand response) { logger.debug("Error while handing message {}", response.getResponse(), e); } } - } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java index 43c55131f1414..a82e15713aa6a 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoBasicHandler.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -100,22 +99,6 @@ public void initialize() { refreshList = new ArrayList<>(); } - @Override - public void dispose() { - logger.debug("Disposing Xiaomi Mi IO Basic handler '{}'", getThing().getUID()); - final @Nullable ScheduledFuture pollingJob = this.pollingJob; - if (pollingJob != null) { - pollingJob.cancel(true); - } - this.pollingJob = null; - final @Nullable MiIoAsyncCommunication miioCom = this.miioCom; - if (miioCom != null) { - lastId = miioCom.getId(); - miioCom.close(); - this.miioCom = null; - } - } - @Override public void handleCommand(ChannelUID channelUID, Command command) { if (command == RefreshType.REFRESH) { @@ -130,7 +113,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { if (channelUID.getId().equals(CHANNEL_COMMAND)) { cmds.put(sendCommand(command.toString()), command.toString()); } - logger.debug("Locating action for channel {}: {}", channelUID.getId(), command); + logger.debug("Locating action for channel '{}': '{}'", channelUID.getId(), command); if (!actions.isEmpty()) { if (actions.containsKey(channelUID)) { int valuePos = 0; @@ -156,8 +139,9 @@ public void handleCommand(ChannelUID channelUID, Command command) { (color.getRed() << 16) + (color.getGreen() << 8) + color.getBlue()); } else if (command instanceof DecimalType) { // actually brightness is being set instead of a color - cmd = "set_bright"; value = new JsonPrimitive(((DecimalType) command).toBigDecimal()); + } else if (command instanceof OnOffType) { + value = new JsonPrimitive(command == OnOffType.ON ? 100 : 0); } else { logger.debug("Unsupported command for COLOR: {}", command); } @@ -184,14 +168,15 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else { value = new JsonPrimitive(command.toString().toLowerCase()); } + final MiIoDeviceActionCondition miIoDeviceActionCondition = action.getCondition(); + if (miIoDeviceActionCondition != null) { + value = ActionConditions.executeAction(miIoDeviceActionCondition, deviceVariables, value, + command); + } // Check for miot channel if (miIoBasicChannel.isMiOt()) { value = miotTransform(miIoBasicChannel, value); } - final MiIoDeviceActionCondition miIoDeviceActionCondition = action.getCondition(); - if (miIoDeviceActionCondition != null) { - value = ActionConditions.executeAction(miIoDeviceActionCondition, deviceVariables, value); - } if (paramType != CommandParameterType.NONE && value != null) { if (parameters.size() > 0) { parameters.set(valuePos, value); @@ -357,7 +342,13 @@ private boolean buildChannelStructure(String deviceName) { if (channelUID != null) { actions.put(channelUID, miChannel); channelsAdded++; + } else { + logger.debug("Channel for {} ({}) not loaded", miChannel.getChannel(), + miChannel.getFriendlyName()); } + } else { + logger.debug("Channel {} ({}), not loaded, missing type", miChannel.getChannel(), + miChannel.getFriendlyName()); } } } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoVacuumHandler.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoVacuumHandler.java index 6636e64748678..2b65d18d3b817 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoVacuumHandler.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/handler/MiIoVacuumHandler.java @@ -92,7 +92,6 @@ public MiIoVacuumHandler(Thing thing, MiIoDatabaseWatchService miIoDatabaseWatch super(thing, miIoDatabaseWatchService); this.cloudConnector = cloudConnector; mapChannelUid = new ChannelUID(thing.getUID(), CHANNEL_VACUUM_MAP); - initializeData(); status = new ExpiringCache<>(CACHE_EXPIRY, () -> { try { int ret = sendCommand(MiIoCommand.GET_STATUS); @@ -404,8 +403,7 @@ protected synchronized void updateData() { @Override protected boolean initializeData() { updateState(CHANNEL_CONSUMABLE_RESET, new StringType("none")); - this.miioCom = getConnection(); - return true; + return super.initializeData(); } @Override diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapDraw.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapDraw.java index 9ee93d4e6d950..b61ab7f071147 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapDraw.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapDraw.java @@ -17,6 +17,7 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; import java.awt.Polygon; import java.awt.Stroke; import java.awt.geom.AffineTransform; @@ -331,13 +332,17 @@ private void drawOpenHabRocks(Graphics2D g2d, int width, int height, float scale } catch (IOException e) { logger.debug("Error loading image ohlogo.png:: {}", e.getMessage()); } - Font font = new Font("Helvetica", Font.BOLD, 14); + String fontName = getAvailableFont("Helvetica,Arial,Roboto,Verdana,Times,Serif,Dialog".split(",")); + if (fontName == null) { + return; // no available fonts to draw text + } + Font font = new Font(fontName, Font.BOLD, 14); g2d.setFont(font); String message = "Openhab rocks your Xiaomi vacuum!"; FontMetrics fontMetrics = g2d.getFontMetrics(); int stringWidth = fontMetrics.stringWidth(message); if ((stringWidth + textPos) > rmfp.getImgWidth() * scale) { - font = new Font("Helvetica ", Font.BOLD, + font = new Font(fontName, Font.BOLD, (int) Math.floor(14 * (rmfp.getImgWidth() * scale - textPos - offset * scale) / stringWidth)); g2d.setFont(font); } @@ -346,6 +351,26 @@ private void drawOpenHabRocks(Graphics2D g2d, int width, int height, float scale g2d.drawString(message, textPos, height - offset * scale - stringHeight / 2); } + private @Nullable String getAvailableFont(String[] preferedFonts) { + final GraphicsEnvironment gEv = GraphicsEnvironment.getLocalGraphicsEnvironment(); + if (gEv == null) { + return null; + } + String[] fonts = gEv.getAvailableFontFamilyNames(); + if (fonts.length == 0) { + return null; + } + for (int j = 0; j < preferedFonts.length; j++) { + for (int i = 0; i < fonts.length; i++) { + if (fonts[i].equalsIgnoreCase(preferedFonts[j])) { + return preferedFonts[j]; + } + } + } + // Preferred fonts not available... just go with the first one + return fonts[0]; + } + private @Nullable URL getImageUrl(String image) { if (bundle != null) { return bundle.getEntry("images/" + image); diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapFileParser.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapFileParser.java index 13e8ff22d8621..0e70fe27103a4 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapFileParser.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/robot/RRMapFileParser.java @@ -413,5 +413,4 @@ public ArrayList getObstacles() { public byte[] getBlocks() { return blocks; } - } diff --git a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/transport/MiIoAsyncCommunication.java b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/transport/MiIoAsyncCommunication.java index d9af9abbf2b80..284ec3bd5b2e5 100644 --- a/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/transport/MiIoAsyncCommunication.java +++ b/bundles/org.openhab.binding.miio/src/main/java/org/openhab/binding/miio/internal/transport/MiIoAsyncCommunication.java @@ -147,11 +147,8 @@ public int queueCommand(String command, String params) fullCommand.toString()); concurrentLinkedQueue.add(sendCmd); if (logger.isDebugEnabled()) { - String tokenText = Utils.getHex(token); // Obfuscate part of the token to allow sharing of the logfiles - tokenText = ((tokenText.length() < 8) ? tokenText : tokenText.substring(0, 8)) - .concat((tokenText.length() > 24) ? tokenText.substring(8, 24).replaceAll(".", "X") - : tokenText.substring(8).replaceAll(".", "X")) - .concat(tokenText.substring(24)); + // Obfuscate part of the token to allow sharing of the logfiles + String tokenText = Utils.obfuscateToken(Utils.getHex(token)); logger.debug("Command added to Queue {} -> {} (Device: {} token: {} Queue: {})", fullCommand.toString(), ip, Utils.getHex(deviceId), tokenText, concurrentLinkedQueue.size()); } diff --git a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/basicThing.xml b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/basicThing.xml index 5d933b3bf04f3..18589aadb1cc1 100644 --- a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/basicThing.xml +++ b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/basicThing.xml @@ -8,21 +8,21 @@ - - + + Xiaomi - + - + diff --git a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/commonChannels.xml b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/commonChannels.xml index 496795834082c..c064cef616018 100644 --- a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/commonChannels.xml +++ b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/commonChannels.xml @@ -7,10 +7,10 @@ - - - - + + + + @@ -18,22 +18,22 @@ String - + String - + Number - + Number - + @@ -152,90 +152,90 @@ Number - + Number - + Number Particulate Matter 2.5 - + Number Carbon Dioxide - + Number Total Volatile Organic Compounds - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + Number @@ -256,7 +256,7 @@ Number - + String @@ -271,42 +271,42 @@ Number - + Number - + Number - + Number - + Switch - + String - + Switch - + Switch - + String @@ -334,7 +334,7 @@ Number - + Switch @@ -366,7 +366,7 @@ Switch - + String @@ -382,22 +382,22 @@ Number - + Number - + Number - + Number - + String @@ -421,22 +421,22 @@ Number - + Number - + Number - + Number - + Number diff --git a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/genericThing.xml b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/genericThing.xml index 6f4dcc337224b..80be8cf142add 100644 --- a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/genericThing.xml +++ b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/genericThing.xml @@ -8,15 +8,15 @@ - - + + Xiaomi - + diff --git a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/unsupportedThing.xml b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/unsupportedThing.xml index dcb25d1ca649e..4473a413fea74 100644 --- a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/unsupportedThing.xml +++ b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/unsupportedThing.xml @@ -8,23 +8,23 @@ - - + + Xiaomi - + - - - + + + diff --git a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/vacuumThing.xml b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/vacuumThing.xml index 79572f4eb6ef3..004859b4aa22f 100644 --- a/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/vacuumThing.xml +++ b/bundles/org.openhab.binding.miio/src/main/resources/ESH-INF/thing/vacuumThing.xml @@ -8,89 +8,89 @@ - - - - - - - + + + + + + + Xiaomi - + - - - - + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - + + + - - - - - - - - + + + + + + + + - - - + + + @@ -98,12 +98,12 @@ Number - + Number - + Switch @@ -112,85 +112,85 @@ String - + Number - + Number - + Number - + Number Energy - + Number - + String - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + Number - + @@ -262,17 +262,17 @@ Number Total Cleaning Time in minutes - + Number - + Number - + @@ -281,44 +281,44 @@ Last Cleaning Start Time Date - + DateTime Last Cleaning End Time Date - + Number Cleaning Duration in minutes - + Number - + Number - + Number - + String - + Image - + diff --git a/bundles/org.openhab.binding.miio/src/main/resources/database/cuco.plug.cp1-miot.json b/bundles/org.openhab.binding.miio/src/main/resources/database/cuco.plug.cp1-miot.json new file mode 100644 index 0000000000000..50b3d2a25f00b --- /dev/null +++ b/bundles/org.openhab.binding.miio/src/main/resources/database/cuco.plug.cp1-miot.json @@ -0,0 +1,71 @@ +{ + "deviceMapping": { + "id": [ + "cuco.plug.cp1" + ], + "propertyMethod": "get_properties", + "maxProperties": 2, + "channels": [ + { + "property": "firmware-revision", + "siid": 1, + "piid": 4, + "friendlyName": "Device Information-CurrentFirmware Version", + "channel": "FirmwareRevision", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "manufacturer", + "siid": 1, + "piid": 1, + "friendlyName": "Device Information-Device Manufacturer", + "channel": "Manufacturer", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "model", + "siid": 1, + "piid": 2, + "friendlyName": "Device Information-Device Model", + "channel": "Model", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "serial-number", + "siid": 1, + "piid": 3, + "friendlyName": "Device Information-Device Serial Number", + "channel": "SerialNumber", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "on", + "siid": 2, + "piid": 1, + "friendlyName": "Switch-Switch Status", + "channel": "On", + "channelType": "miot_bool", + "type": "Switch", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "ONOFFBOOL" + } + ] + } + ] + } +} diff --git a/bundles/org.openhab.binding.miio/src/main/resources/database/dreame.vacuum.mc1808-miot.json b/bundles/org.openhab.binding.miio/src/main/resources/database/dreame.vacuum.mc1808-miot.json new file mode 100644 index 0000000000000..6a015e22e314c --- /dev/null +++ b/bundles/org.openhab.binding.miio/src/main/resources/database/dreame.vacuum.mc1808-miot.json @@ -0,0 +1,440 @@ +{ + "deviceMapping": { + "id": [ + "dreame.vacuum.mc1808" + ], + "propertyMethod": "get_properties", + "maxProperties": 2, + "channels": [ + { + "property": "battery-level", + "siid": 2, + "piid": 1, + "friendlyName": "Battery-Battery Level", + "channel": "BatteryLevel", + "channelType": "miot_uint8", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "charging-state", + "siid": 2, + "piid": 2, + "friendlyName": "Battery-Charging State", + "channel": "ChargingState", + "channelType": "miot_uint8", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "firmware-revision", + "siid": 1, + "piid": 4, + "friendlyName": "Device Information-Current Firmware Version", + "channel": "FirmwareRevision", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "manufacturer", + "siid": 1, + "piid": 1, + "friendlyName": "Device Information-Device Manufacturer", + "channel": "Manufacturer", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "model", + "siid": 1, + "piid": 2, + "friendlyName": "Device Information-Device Model", + "channel": "Model", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "serial-number", + "siid": 1, + "piid": 3, + "friendlyName": "Device Information-Device Serial Number", + "channel": "SerialNumber", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "fault", + "siid": 3, + "piid": 1, + "friendlyName": "Robot Cleaner-Device Fault", + "channel": "Fault", + "channelType": "miot_uint8", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "status", + "siid": 3, + "piid": 2, + "friendlyName": "Robot Cleaner-Status", + "channel": "Status", + "channelType": "miot_int8", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "brush-left-time", + "siid": 26, + "piid": 1, + "friendlyName": "Main Cleaning Brush-Brush Left Time", + "channel": "BrushLeftTime", + "channelType": "miot_uint16", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "brush-life-level", + "siid": 26, + "piid": 2, + "friendlyName": "Main Cleaning Brush-Brush Life Level", + "channel": "BrushLifeLevel", + "channelType": "miot_uint8", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "filter-life-level", + "siid": 27, + "piid": 1, + "friendlyName": "Filter-Filter Life Level", + "channel": "FilterLifeLevel", + "channelType": "miot_uint8", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "filter-left-time", + "siid": 27, + "piid": 2, + "friendlyName": "Filter-Filter Left Time", + "channel": "FilterLeftTime", + "channelType": "miot_uint16", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "brush-left-time1", + "siid": 28, + "piid": 1, + "friendlyName": "Side Cleaning Brush-Brush Left Time", + "channel": "BrushLeftTime1", + "channelType": "miot_uint16", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "brush-life-level1", + "siid": 28, + "piid": 2, + "friendlyName": "Side Cleaning Brush-Brush Life Level", + "channel": "BrushLifeLevel1", + "channelType": "miot_uint8", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "work-mode", + "siid": 18, + "piid": 1, + "friendlyName": "clean-workmode", + "channel": "WorkMode", + "channelType": "miot_int32", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "area", + "siid": 18, + "piid": 4, + "friendlyName": "clean-area", + "channel": "Area", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "STRING" + } + ] + }, + { + "property": "timer", + "siid": 18, + "piid": 5, + "friendlyName": "clean-timer", + "channel": "Timer", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "STRING" + } + ] + }, + { + "property": "mode", + "siid": 18, + "piid": 6, + "friendlyName": "clean-mode", + "channel": "Mode", + "channelType": "miot_int32", + "type": "Number", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "NUMBER" + } + ] + }, + { + "property": "total-clean-time", + "siid": 18, + "piid": 13, + "friendlyName": "clean-total time", + "channel": "TotalCleanTime", + "channelType": "miot_uint32", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "total-clean-times", + "siid": 18, + "piid": 14, + "friendlyName": "clean-total times", + "channel": "TotalCleanTimes", + "channelType": "miot_uint32", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "total-clean-area", + "siid": 18, + "piid": 15, + "friendlyName": "clean-Total area", + "channel": "TotalCleanArea", + "channelType": "miot_uint32", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "clean-log-start-time", + "siid": 18, + "piid": 16, + "friendlyName": "clean-Start Time", + "channel": "CleanLogStartTime", + "channelType": "miot_uint32", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "button-led", + "siid": 18, + "piid": 17, + "friendlyName": "clean-led", + "channel": "ButtonLed", + "channelType": "miot_uint16", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "task-done", + "siid": 18, + "piid": 18, + "friendlyName": "clean-task done", + "channel": "TaskDone", + "channelType": "miot_uint8", + "type": "Number", + "refresh": true, + "actions": [] + }, + { + "property": "life-sieve", + "siid": 19, + "piid": 1, + "friendlyName": "consumable-life-sieve", + "channel": "LifeSieve", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "STRING" + } + ] + }, + { + "property": "life-brush-side", + "siid": 19, + "piid": 2, + "friendlyName": "consumable-life-brush-side", + "channel": "LifeBrushSide", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "STRING" + } + ] + }, + { + "property": "life-brush-main", + "siid": 19, + "piid": 3, + "friendlyName": "consumable-life-brush-main", + "channel": "LifeBrushMain", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "STRING" + } + ] + }, + { + "property": "enable", + "siid": 20, + "piid": 1, + "friendlyName": "annoy-enable", + "channel": "Enable", + "channelType": "miot_bool", + "type": "Switch", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "ONOFFBOOL" + } + ] + }, + { + "property": "start-time", + "siid": 20, + "piid": 2, + "friendlyName": "annoy-start-time", + "channel": "StartTime", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "STRING" + } + ] + }, + { + "property": "stop-time", + "siid": 20, + "piid": 3, + "friendlyName": "annoy-stop-time", + "channel": "StopTime", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "STRING" + } + ] + }, + { + "property": "map-view", + "siid": 23, + "piid": 1, + "friendlyName": "map-map-view", + "channel": "MapView", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + }, + { + "property": "volume", + "siid": 24, + "piid": 1, + "friendlyName": "audio-volume", + "channel": "Volume", + "channelType": "miot_int32", + "type": "Number", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "NUMBER" + } + ] + }, + { + "property": "voice-packets", + "siid": 24, + "piid": 3, + "friendlyName": "audio-voiceId", + "channel": "VoicePackets", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [ + { + "command": "set_properties", + "parameterType": "STRING" + } + ] + }, + { + "property": "time-zone", + "siid": 25, + "piid": 1, + "friendlyName": "timezone", + "channel": "TimeZone", + "channelType": "miot_string", + "type": "String", + "refresh": true, + "actions": [] + } + ] + } +} diff --git a/bundles/org.openhab.binding.miio/src/main/resources/database/yeelink.light.color1.json b/bundles/org.openhab.binding.miio/src/main/resources/database/yeelink.light.color1.json index 37c6bfe0d7402..cb8e63dc9941e 100644 --- a/bundles/org.openhab.binding.miio/src/main/resources/database/yeelink.light.color1.json +++ b/bundles/org.openhab.binding.miio/src/main/resources/database/yeelink.light.color1.json @@ -10,6 +10,7 @@ "yeelink.light.bslamp1", "yeelink.light.bslamp2" ], + "maxProperties": 7, "channels": [ { "property": "power", @@ -53,7 +54,7 @@ "property": "delayoff", "friendlyName": "Shutdown Timer", "channel": "delayoff", - "type": "String", + "type": "Number", "refresh": true, "ChannelGroup": "actions", "actions": [ @@ -120,13 +121,28 @@ { "command": "set_rgb", "parameterType": "COLOR", - "parameter1": "\"smooth\"", - "parameter2": "500", + "condition": { + "name": "HSBOnly" + }, "parameters": [ "$value$", "smooth", 500 ] + }, + { + "command": "set_bright", + "parameterType": "NUMBER", + "condition": { + "name": "BrightnessExisting" + } + }, + { + "command": "set_power", + "parameterType": "ONOFF", + "condition": { + "name": "BrightnessOnOff" + } } ] }, diff --git a/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ActionConditionTest.java b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ActionConditionTest.java new file mode 100644 index 0000000000000..8f11fd0f86179 --- /dev/null +++ b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/ActionConditionTest.java @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.miio.internal; + +import static org.junit.Assert.*; + +import java.util.Collections; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Test; +import org.openhab.binding.miio.internal.basic.ActionConditions; +import org.openhab.binding.miio.internal.basic.MiIoDeviceActionCondition; + +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; + +/** + * Test case for {@link ActionConditions} + * + * @author Marcel Verpaalen - Initial contribution + * + */ +@NonNullByDefault +public class ActionConditionTest { + + @Test + public void assertBrightnessExisting() { + MiIoDeviceActionCondition condition = new MiIoDeviceActionCondition(); + condition.setName("BrightnessExisting"); + Map deviceVariables = Collections.emptyMap(); + JsonElement value = new JsonPrimitive(1); + JsonElement resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + // dimmed to 1 + assertNotNull(resp); + assertEquals(new JsonPrimitive(1), resp); + + // fully on + value = new JsonPrimitive(100); + resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + assertNotNull(resp); + assertEquals(new JsonPrimitive(100), resp); + + // >100 + value = new JsonPrimitive(200); + resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + assertNotNull(resp); + assertEquals(new JsonPrimitive(100), resp); + + // switched off = invalid brightness + value = new JsonPrimitive(0); + resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + assertNull(resp); + assertNotEquals(new JsonPrimitive(0), resp); + + value = new JsonPrimitive(-1); + resp = ActionConditions.executeAction(condition, deviceVariables, value, null); + assertNull(resp); + assertNotEquals(new JsonPrimitive(-1), resp); + } +} diff --git a/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/RoboMapViewer.java b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/RoboMapViewer.java index dffa2d00887bd..3c7db4f413e65 100644 --- a/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/RoboMapViewer.java +++ b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/RoboMapViewer.java @@ -39,7 +39,6 @@ import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileSystemView; -//import org.apache.log4j.PropertyConfigurator; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.junit.Ignore; @@ -213,7 +212,6 @@ public void actionPerformed(@Nullable ActionEvent ae) { logger.debug("Error finding next file:{}", e); } } - }); openButton.addActionListener(new ActionListener() { @@ -258,7 +256,6 @@ private void loadFirstFile() { } catch (SecurityException | InvalidPathException e) { logger.debug("Error finding first file:{}", e); } - } private void updateStatusLine() { diff --git a/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/UtilsTest.java b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/UtilsTest.java new file mode 100644 index 0000000000000..7784294ef1093 --- /dev/null +++ b/bundles/org.openhab.binding.miio/src/test/java/org/openhab/binding/miio/internal/UtilsTest.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.miio.internal; + +import static org.junit.Assert.assertEquals; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.Test; + +/** + * Test case for {@link Utils} + * + * @author Marcel Verpaalen - Initial contribution + * + */ +@NonNullByDefault +public class UtilsTest { + + @Test + public void obfuscateTokenTest() { + String tokenString = ""; + assertEquals("", Utils.obfuscateToken(tokenString)); + + tokenString = "6614"; + assertEquals("6614", Utils.obfuscateToken(tokenString)); + + tokenString = "66147986"; + assertEquals("66147986", Utils.obfuscateToken(tokenString)); + + tokenString = "6614798643fe781563c1"; + assertEquals("66147986XXXXXXXXXXXX", Utils.obfuscateToken(tokenString)); + + tokenString = "6614798643fe781563c1eebe"; + assertEquals("66147986XXXXXXXXXXXXXXXX", Utils.obfuscateToken(tokenString)); + + tokenString = "6614798643fe781563c1eebeda22479a"; + assertEquals("66147986XXXXXXXXXXXXXXXXda22479a", Utils.obfuscateToken(tokenString)); + + tokenString = "6614798643fe781563c1eebeda22479a6614798643fe781563c1eebeda22479a"; + assertEquals("66147986XXXXXXXXXXXXXXXXda22479a6614798643fe781563c1eebeda22479a", + Utils.obfuscateToken(tokenString)); + } +} diff --git a/bundles/org.openhab.binding.milight/pom.xml b/bundles/org.openhab.binding.milight/pom.xml index c299fe4ff2930..077b40b58f46f 100644 --- a/bundles/org.openhab.binding.milight/pom.xml +++ b/bundles/org.openhab.binding.milight/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.milight diff --git a/bundles/org.openhab.binding.milight/src/main/feature/feature.xml b/bundles/org.openhab.binding.milight/src/main/feature/feature.xml index 88403aef7212c..c6c942e2b4477 100644 --- a/bundles/org.openhab.binding.milight/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.milight/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.milight/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.milight/${project.version} + diff --git a/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/handler/AbstractLedV6Handler.java b/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/handler/AbstractLedV6Handler.java index 6e52bd8ad5638..b681db35a225a 100644 --- a/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/handler/AbstractLedV6Handler.java +++ b/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/handler/AbstractLedV6Handler.java @@ -221,5 +221,4 @@ protected void sendRepeatable(int... data) { sendQueue.queue(QueueItem.createRepeatable(socket, delayTimeMS, repeatTimes, address, port, session.makeCommand(getAddr(), config.zone, data))); } - } diff --git a/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/handler/MilightV3WhiteHandler.java b/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/handler/MilightV3WhiteHandler.java index 42eb8645cb140..9ed7ae89fe0f9 100644 --- a/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/handler/MilightV3WhiteHandler.java +++ b/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/handler/MilightV3WhiteHandler.java @@ -205,5 +205,4 @@ public void nextAnimationMode(MilightThingState state) { sendQueue.queue(createRepeatable(cOn).addNonRepeatable(NEXT_ANIMATION_MODE)); state.animationMode = Math.min(state.animationMode + 1, MAX_ANIM_MODES); } - } diff --git a/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/protocol/MilightV6SessionManager.java b/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/protocol/MilightV6SessionManager.java index 98cb8b7536bc7..6cbafdeee7a29 100644 --- a/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/protocol/MilightV6SessionManager.java +++ b/bundles/org.openhab.binding.milight/src/main/java/org/openhab/binding/milight/internal/protocol/MilightV6SessionManager.java @@ -113,7 +113,7 @@ public interface ISessionState { * SESSION_VALID_KEEP_ALIVE will be reported in the interval, given to the constructor of * {@link MilightV6SessionManager}. * - * @param state The new state + * @param state The new state * @param address The remote IP address. Only guaranteed to be non null in the SESSION_VALID* states. */ void sessionStateChanged(SessionState state, @Nullable InetAddress address); diff --git a/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/binding/binding.xml index 50080039a262a..9542cf160d2ff 100644 --- a/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Milight Binding A binding for Milight/Easybulb/compatible white, color and color+white bulbs. diff --git a/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v2.xml b/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v2.xml index a10029f827750..9dfed1d7801ad 100644 --- a/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v2.xml +++ b/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v2.xml @@ -6,16 +6,16 @@ - + The oldest produced color bulb. Without a white channel. No saturation support. Lightbulb - - - + + + diff --git a/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v3.xml b/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v3.xml index a7eea8b72c503..471e19d57e012 100644 --- a/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v3.xml +++ b/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v3.xml @@ -41,10 +41,13 @@ The mac address of the bridge in upper case letters without delimiter. - Use this parameter and leave the IP/Hostname empty for DHCP environments where IPs may often change over time. + Use this parameter and leave the + IP/Hostname empty for DHCP environments where IPs may often change over time. - The Bridge ID is also used to check if a given IP corresponds to the right device. - The bridge is set offline if the device does not respond with the correct Bridge ID and a re-detection is started. + The Bridge ID is also used to check if + a given IP corresponds to the right device. + The bridge is set offline if the device does not respond with the + correct Bridge ID and a re-detection is started. true @@ -61,7 +64,7 @@ - + RGB bulb with white channel. No saturation control. If the set saturation is below a threshold of 50%, @@ -69,12 +72,12 @@ Lightbulb - - - - - - + + + + + + @@ -89,17 +92,17 @@ - + White bulb for the older bridge (up to 2016) Lightbulb - - - - + + + + diff --git a/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v6.xml b/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v6.xml index 425bc65a5e93d..f0d12c4b22f8e 100644 --- a/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v6.xml +++ b/bundles/org.openhab.binding.milight/src/main/resources/ESH-INF/thing/v6.xml @@ -82,7 +82,7 @@ - + Integrated bulb of the ibox bridge with no dedicated white channel and therefore no saturation control @@ -90,12 +90,12 @@ Lightbulb - - - - - - + + + + + + @@ -110,22 +110,22 @@ - + Color bulb with white channel for the new Milight/Easybulb system. Lightbulb - - - - - - - - - + + + + + + + + + @@ -140,24 +140,24 @@ - + Color bulb with warm and cold white support for the new Milight/Easybulb system. Lightbulb - - - - - - - - - - - + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.millheat/pom.xml b/bundles/org.openhab.binding.millheat/pom.xml index a21b25cb6c626..ead6bde13cb14 100644 --- a/bundles/org.openhab.binding.millheat/pom.xml +++ b/bundles/org.openhab.binding.millheat/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.millheat diff --git a/bundles/org.openhab.binding.millheat/src/main/feature/feature.xml b/bundles/org.openhab.binding.millheat/src/main/feature/feature.xml index 2a0c86e23d316..259654d87e2b6 100644 --- a/bundles/org.openhab.binding.millheat/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.millheat/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.millheat/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.millheat/${project.version} + diff --git a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/MillheatBindingConstants.java b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/MillheatBindingConstants.java index e7fe0c1035788..1d244d9b15b6e 100644 --- a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/MillheatBindingConstants.java +++ b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/MillheatBindingConstants.java @@ -59,5 +59,4 @@ public class MillheatBindingConstants { CHANNEL_TYPE_MASTER_SWITCH); public static final ChannelTypeUID CHANNEL_TYPE_TARGET_TEMPERATURE_HEATER_UID = new ChannelTypeUID(BINDING_ID, CHANNEL_TYPE_TARGET_TEMPERATURE_HEATER); - } diff --git a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/MillheatHandlerFactory.java b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/MillheatHandlerFactory.java index cc23324d772d3..f59b2707e8d06 100644 --- a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/MillheatHandlerFactory.java +++ b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/MillheatHandlerFactory.java @@ -109,5 +109,4 @@ private void unregisterDeviceDiscoveryService(ThingUID thingUID) { discoveryServiceRegs.remove(thingUID); } } - } diff --git a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/config/MillheatHomeConfiguration.java b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/config/MillheatHomeConfiguration.java index a1e9bf03dbcfe..13b92600708bd 100644 --- a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/config/MillheatHomeConfiguration.java +++ b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/config/MillheatHomeConfiguration.java @@ -25,5 +25,4 @@ public class MillheatHomeConfiguration { public String toString() { return "MillheatHomeConfiguration [homeId=" + homeId + "]"; } - } diff --git a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/handler/MillheatAccountHandler.java b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/handler/MillheatAccountHandler.java index cdcf19c9807d9..eeb3f3173d69e 100644 --- a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/handler/MillheatAccountHandler.java +++ b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/handler/MillheatAccountHandler.java @@ -12,8 +12,8 @@ */ package org.openhab.binding.millheat.internal.handler; -import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.List; import java.util.Optional; @@ -23,8 +23,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; @@ -44,6 +42,7 @@ import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.util.HexUtils; import org.openhab.binding.millheat.internal.MillheatCommunicationException; import org.openhab.binding.millheat.internal.client.BooleanSerializer; import org.openhab.binding.millheat.internal.client.RequestLogger; @@ -88,6 +87,7 @@ */ @NonNullByDefault public class MillheatAccountHandler extends BaseBridgeHandler { + private static final String SHA_1_ALGORITHM = "SHA-1"; private static final int MIN_TIME_BETWEEEN_MODEL_UPDATES_MS = 30_000; private static final int NUM_NONCE_CHARS = 16; private static final String CONTENT_TYPE = "application/x-zc-object"; @@ -155,15 +155,16 @@ public boolean doLogin() { rsp.errorDescription)); } else { // No error provided on login, proceed to find token and userid - token = StringUtils.trimToNull(rsp.token); + String localToken = rsp.token.trim(); userId = rsp.userId == null ? null : rsp.userId.toString(); - if (token == null) { + if (localToken == null || localToken.isEmpty()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "error login in, no token provided"); } else if (userId == null) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "error login in, no userId provided"); } else { + token = localToken; return true; } } @@ -229,7 +230,7 @@ private T sendLoggedInRequest(final AbstractRequest req, final Class resp try { final Request request = buildLoggedInRequest(req); return sendRequest(request, req, responseType); - } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) { + } catch (NoSuchAlgorithmException e) { throw new MillheatCommunicationException("Error building Millheat request: " + e.getMessage(), e); } } @@ -343,12 +344,13 @@ private void updateThingStatuses() { } } - private Request buildLoggedInRequest(final AbstractRequest req) - throws NoSuchAlgorithmException, UnsupportedEncodingException { + private Request buildLoggedInRequest(final AbstractRequest req) throws NoSuchAlgorithmException { final String nonce = getRandomString(NUM_NONCE_CHARS); final String timestamp = String.valueOf(System.currentTimeMillis() / 1000); final String signatureBasis = REQUEST_TIMEOUT + timestamp + nonce + token; - final String signature = DigestUtils.shaHex(signatureBasis); + MessageDigest md = MessageDigest.getInstance(SHA_1_ALGORITHM); + byte[] sha1Hash = md.digest(signatureBasis.getBytes(StandardCharsets.UTF_8)); + final String signature = HexUtils.bytesToHex(sha1Hash).toLowerCase(); final String reqJson = gson.toJson(req); final Request request = httpClient.newRequest(serviceEndpoint + req.getRequestUrl()); diff --git a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/handler/MillheatBaseThingHandler.java b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/handler/MillheatBaseThingHandler.java index b7a08b4911920..0c80a60760cd1 100644 --- a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/handler/MillheatBaseThingHandler.java +++ b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/handler/MillheatBaseThingHandler.java @@ -69,5 +69,4 @@ protected Optional getAccountHandler() { } protected abstract void handleCommand(ChannelUID uid, Command command, MillheatModel model); - } diff --git a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/model/Heater.java b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/model/Heater.java index 97e25c6f3644f..f0951d4c3bbe3 100644 --- a/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/model/Heater.java +++ b/bundles/org.openhab.binding.millheat/src/main/java/org/openhab/binding/millheat/internal/model/Heater.java @@ -146,5 +146,4 @@ public void setFanActive(final boolean fanActive) { public void setPowerStatus(final boolean powerStatus) { this.powerStatus = powerStatus; } - } diff --git a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/account.xml b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/account.xml index 7be0121466040..88e92115971ef 100644 --- a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/account.xml +++ b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/account.xml @@ -7,7 +7,7 @@ This bridge represents the gateway to Mill Heating API - + diff --git a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/channels.xml index 1f77a939ba81c..ab6c02ac89288 100644 --- a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/channels.xml @@ -11,7 +11,7 @@ CurrentTemperature - + Number:Temperature @@ -20,7 +20,7 @@ TargetTemperature - + Number:Temperature @@ -29,7 +29,7 @@ TargetTemperature - + Number:Temperature @@ -39,7 +39,7 @@ TargetTemperature - + Number:Temperature @@ -48,7 +48,7 @@ TargetTemperature - + Number:Temperature @@ -57,20 +57,20 @@ TargetTemperature - + Switch Current state of the heater or heaters in room Energy - + Switch ON if heater is an independent heater and not connected to a room - + Switch @@ -87,7 +87,7 @@ Contact Open window/cold air flow detection - + Number:Power @@ -123,7 +123,7 @@ TargetTemperature - + Switch diff --git a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/heater.xml b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/heater.xml index 9ec2fcdb3def2..13da6f03cb03e 100644 --- a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/heater.xml +++ b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/heater.xml @@ -6,21 +6,21 @@ - + - - - - - - + + + + + + macAddress - + diff --git a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/home.xml b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/home.xml index f6de2c87cce9e..6d5dc3b4d0926 100644 --- a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/home.xml +++ b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/home.xml @@ -6,20 +6,20 @@ - + - - - - - + + + + + homeId - + diff --git a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/room.xml b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/room.xml index be21f67762d79..bbd829cc9da90 100644 --- a/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/room.xml +++ b/bundles/org.openhab.binding.millheat/src/main/resources/ESH-INF/thing/room.xml @@ -6,23 +6,23 @@ - + - - - - - - - - + + + + + + + + roomId - + diff --git a/bundles/org.openhab.binding.minecraft/pom.xml b/bundles/org.openhab.binding.minecraft/pom.xml index e992410a80c5b..c22eaa9c52470 100644 --- a/bundles/org.openhab.binding.minecraft/pom.xml +++ b/bundles/org.openhab.binding.minecraft/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.minecraft diff --git a/bundles/org.openhab.binding.minecraft/src/main/feature/feature.xml b/bundles/org.openhab.binding.minecraft/src/main/feature/feature.xml index a18138eda5803..087315a682c9e 100644 --- a/bundles/org.openhab.binding.minecraft/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.minecraft/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - mvn:org.openhab.addons.bundles/org.openhab.binding.minecraft/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + mvn:org.openhab.addons.bundles/org.openhab.binding.minecraft/${project.version} + diff --git a/bundles/org.openhab.binding.minecraft/src/main/java/org/openhab/binding/minecraft/internal/message/data/PlayerData.java b/bundles/org.openhab.binding.minecraft/src/main/java/org/openhab/binding/minecraft/internal/message/data/PlayerData.java index 13c8468a524d7..e06d08be6e123 100644 --- a/bundles/org.openhab.binding.minecraft/src/main/java/org/openhab/binding/minecraft/internal/message/data/PlayerData.java +++ b/bundles/org.openhab.binding.minecraft/src/main/java/org/openhab/binding/minecraft/internal/message/data/PlayerData.java @@ -139,5 +139,4 @@ public boolean equals(Object obj) { } return true; } - } diff --git a/bundles/org.openhab.binding.minecraft/src/main/java/org/openhab/binding/minecraft/internal/message/data/SignData.java b/bundles/org.openhab.binding.minecraft/src/main/java/org/openhab/binding/minecraft/internal/message/data/SignData.java index 418b7162ff7e5..c9be76e124191 100644 --- a/bundles/org.openhab.binding.minecraft/src/main/java/org/openhab/binding/minecraft/internal/message/data/SignData.java +++ b/bundles/org.openhab.binding.minecraft/src/main/java/org/openhab/binding/minecraft/internal/message/data/SignData.java @@ -80,5 +80,4 @@ public boolean equals(Object obj) { } return true; } - } diff --git a/bundles/org.openhab.binding.minecraft/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.minecraft/src/main/resources/ESH-INF/binding/binding.xml index 4dd829b597a3a..d2f3cc60e7dd9 100644 --- a/bundles/org.openhab.binding.minecraft/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.minecraft/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Minecraft Binding This binding can integrate Minecraft servers. diff --git a/bundles/org.openhab.binding.minecraft/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.minecraft/src/main/resources/ESH-INF/thing/thing-types.xml index 02e7676b258fc..260b937704ada 100644 --- a/bundles/org.openhab.binding.minecraft/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.minecraft/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -8,9 +9,9 @@ Server from which data is being fetched. - - - + + + @@ -30,7 +31,7 @@ - + @@ -41,13 +42,13 @@ Online status of the player. - - - - - - - + + + + + + + @@ -61,14 +62,14 @@ - + A sign with a redstone path under it. - + @@ -83,14 +84,14 @@ Number The number of players on the server. - + Number The maxumum number of players on the server. - + @@ -122,14 +123,14 @@ Number The total experience of the player. - + Number Percentage of the experience bar filled for the next level. - + @@ -142,7 +143,7 @@ Number The speed of player. - + diff --git a/bundles/org.openhab.binding.modbus.sunspec/DEVELOPERS.md b/bundles/org.openhab.binding.modbus.sunspec/DEVELOPERS.md new file mode 100644 index 0000000000000..95cc2d0ae45c6 --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/DEVELOPERS.md @@ -0,0 +1,22 @@ +## For Developers + +SunSpec is a big specification with many different type of devices. +If you own or have access to an appliance that is not supported at the moment then your help is welcome. + +If you want to extend the bundle yourself, you have to do the followings: + + - Define your thing type, channel types and channel groups according to openHAB development practices. + You can look at the meter and inverter types to get ideas how you can avoid repeating the same configuration over and over. + + - Extend the `AbstractSunSpecHandler` and implement the handlePolledData method. + This method will be regularly called with the register data read from the appliance. + The method should parse the data and update the channels with them. + + - The preferred way to parse the raw data is to write a parser for you model block type. + Your class should implement the `SunspecParser` class and it is preferred to extend the `AbstractBaseParser` class. + This base class has methods to accurately extract fields from the register array. + + - The parser should only retrieve the data from the register array and return them in a block descriptor class. + Scaling and other higher level transformation should be done by the handler itself. + + - To include your block type in auto discovery you have to add its id to the `SUPPORTED_THING_TYPES_UIDS` map in `SunSpecConstants`. This is enough for our discovery process to include your thing type in the results. diff --git a/bundles/org.openhab.binding.modbus.sunspec/README.md b/bundles/org.openhab.binding.modbus.sunspec/README.md index 036f9cc5958ff..1d88b8be587b4 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/README.md +++ b/bundles/org.openhab.binding.modbus.sunspec/README.md @@ -1,6 +1,6 @@ -# Modbus SunSpec Bundle +# SunSpec -This bundle is an extension for the Modbus binding to support the SunSpec protocol. +This extension adds support for the SunSpec protocol. SunSpec is a format for inverters and smart meters to communicate over the Modbus protocol. It defines how common parameters like AC/DC voltage and current, lifetime produced energy, device temperature etc can be read from the device. @@ -8,16 +8,6 @@ It defines how common parameters like AC/DC voltage and current, lifetime produc SunSpec is supported by several manufacturers like ABB, Fronius, LG, SMA, SolarEdge, Schneider Electric. For a list of certified products see this page: https://sunspec.org/sunspec-certified-products/ -# IMPORTANT under merge - -** IMPORTANT: this version of this bundle is being merged into openHAB. This will be done in small steps - this means that not everything in this readme is supported at the moment ** - -Currently supported features are: - -* basic values of single phase inverters without auto-discovery - - For the complete version of this bundle please contact me! - ## Supported Things @@ -34,50 +24,37 @@ Note, that the things will show up under the Modbus binding. | meter-wye-phase | Wye connected three phase meters (ABCN) | | meter-delta-phase | Delta connected three phase meters (ABC) | +### Auto Discovery - -## Binding Configuration - -This bundle requires the openHAB 2 compatible Modbus binding to be installed. -Please refer to the Modbus binding configuration. -This addon does not require any additional configuration. - -## Thing Configuration - -You need first to set up either a TCP or a Serial Modbus bridge according to the Modbus documentation. -Things in this bundle will use the selected bridge to connect to the device. - -The preferred way to add new things is by using the discovery feature. -This way the bundle will automatically detect if the Modbus bridge supports the SunSpec protocol and if so what type of models are available. -It will automatically detect the register addresses for each model. - -### Auto discovering things - -This bingind fully supports modbus auto discovery, that means all supported profiles should appear in the inbox once you connect your device. +This extension fully supports modbus auto discovery. +It automatically detects the register addresses for each model. Auto discovery is turned off by default in the modbus binding so you have to enable it manually. -You can add `enableDiscovery=true` attribute to your bridge config, or you can enable it in the paper ui under the modbus tcp|serial slave thing. +You can set the `enableDiscovery=true` parameter in your bridge. -A typical bridge configuration would looke like this: +A typical bridge configuration would look like this: ``` Bridge modbus:tcp:bridge [ host="10.0.0.2", port=502, id=1, enableDiscovery=true ] ``` -### Adding things manually +## Thing Configuration -If you decide to add a thing manually then first you have to find out the start address of the model block and the length of it. -While the length is usually fixed the address isn't. +You need first to set up either a TCP or a Serial Modbus bridge according to the Modbus documentation. +Things in this extension will use the selected bridge to connect to the device. + +For defining a thing textually, you have to find out the start address of the model block and the length of it. +While the length is usually fixed, the address is not. Please refer to your device's vendor documentation how model blocks are laid for your equipment. The following parameters are valid for all thing types: -| Parameter | Type | Required | Default if ommitted | Description | +| Parameter | Type | Required | Default if omitted | Description | |-----------|---------|----------|---------------------|-----------------------------------------| | address | integer | yes | N/A | Start address of the model block. | | length | integer | yes | N/A | Length of the model block. Setting this too short could cause problems during parsing | -| refresh | integer | no | 5 | Poll inteval in seconds. Increase this if you encounter connection errors | +| refresh | integer | no | 5 | Poll interval in seconds. Increase this if you encounter connection errors | | maxTries | integer | no | 3 | Number of retries when before giving up reading from this thing. | @@ -86,7 +63,7 @@ The following parameters are valid for all thing types: Channels are grouped into channel groups. Different things support a subset of the following groups. -### Device information group (deviceInformation) +### Device Information Group (deviceInformation) This group contains general operational information about the device. @@ -100,9 +77,9 @@ This group contains general operational information about the device. Supported by: all inverter things -### AC summary group (acGeneral) +### AC Summary Group (acGeneral) -#### inverters +#### Inverters This group contains summarized values for the AC side of the inverter. Even if the inverter supports multiple phases this group will appear only once. @@ -120,7 +97,7 @@ Even if the inverter supports multiple phases this group will appear only once. Supported by: all inverter things -#### meters +#### Meters This group contains summarized values for the power meter over all phases. @@ -146,9 +123,9 @@ This group contains summarized values for the power meter over all phases. Supported by: all meter things -### AC phase specific group +### AC Phase Specific Group -#### inverters +#### Inverters This group describes values for a single phase of the inverter. There can be a maximum of three of this group named: @@ -167,7 +144,7 @@ acPhaseC: available only for inverter-three-phase type inverters. Supported by: all inverter things -#### meters +#### Meters This group holds values for a given line of the meter. There can be a maximum of three of this group named: @@ -200,7 +177,7 @@ acPhaseC: available only for meter-wye-phase and meter-delta-phase meters type i Supported by: all meter things -### DC general group +### DC General Group This group contains summarized data for the DC side of the inverter. DC information is summarized even if the inverter has multiple strings. @@ -216,27 +193,14 @@ Supported by: all inverter things ## Full Example -To configure a SunSpec inverter you have to set up a Modbus bridge with the connection parameters. -The Modbus binding supports both TCP and Serial connections please choose the one that's appropriate for you. -Please enable discovery on the bridge. - -Textual configuration is optional, you can set up everything using PaperUI. -After adding the Modbus bridge and enabling discovery a scan will be initiated and if the device supports SunSpec then the known models will be added to the inbox with correct address configuration. - ### Thing Configuration -The preferred way to add a SunSpec compatible Thing is through auto-discovery. -Whoever if the auto-discovery would not work, advanced users could set up the thing through the config file. - -Please note that the nested bridge configuration does not work at the moment. -Use the following flat format to set up the bridge and the inverter thing: - ``` Bridge modbus:tcp:bridge [ host="hostname|ip", port=502, id=1, enableDiscovery=true ] Thing modbus:inverter-single-phase:bridge:se4000h "SE4000h" (modbus:tcp:modbusbridge) [ address=40069, length=52, refresh=15 ] ``` -Note: make sure that refresh, port and id values are numerical, without quotes. +Note: Make sure that refresh, port and id values are numerical, without quotes. ### Item Configuration @@ -260,7 +224,7 @@ Number Inverter_AC1_A "AC Current Phase 1 [%0.2f A]" {channel="modbus:inverter-s ``` -## Vendor specific information +## Vendor Specific Information ### SolarEdge @@ -268,30 +232,3 @@ Newer models of SolarEdge inverters can be monitored over TCP, but you need to e Refer to the "Modbus over TCP Configuration" chapter in this documentation: https://www.solaredge.com/sites/default/files/sunspec-implementation-technical-note.pdf Modbus connection is limited to a single client at a time, so make sure no other clients are using the port. - -## For Developers - -SunSpec is a big specification with many different type of devices. -If you own or have access to an appliance that is not supported at the moment then your help is welcome. - -If you want to extend the bundle yourself, you have to do the followings: - - - Define your thing type, channel types and channel groups according to openHAB development practices. - You can look at the meter and inverter types to get ideas how you can avoid repeating the same configuration over and over. - - - Extend the `AbstractSunSpecHandler` and implement the handlePolledData method. - This method will be regularly called with the register data read from the appliance. - The method should parse the data and update the channels with them. - - - The preferred way to parse the raw data is to write a parser for you model block type. - Your class should implement the `SunspecParser` class and it is preferred to extend the `AbstractBaseParser` class. - This base class has methods to accurately extract fields from the register array. - - - The parser should only retrieve the data from the register array and return them in a block descriptor class. - Scaling and other higher level transformation should be done by the handler itself. - - - To include your block type in auto discovery you have to add its id to the `SUPPORTED_THING_TYPES_UIDS` map in `SunSpecConstants`. This is enough for our discovery process to include your thing type in the results. - - -If you have questions or need help don't hesitate to contact us over the OpenHAB community forums and github pages. - diff --git a/bundles/org.openhab.binding.modbus.sunspec/pom.xml b/bundles/org.openhab.binding.modbus.sunspec/pom.xml index f7c1e1c54228c..1cbc06c957183 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/pom.xml +++ b/bundles/org.openhab.binding.modbus.sunspec/pom.xml @@ -1,30 +1,32 @@ - + + - 4.0.0 + 4.0.0 - - org.openhab.addons.bundles - org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT - + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + - org.openhab.binding.modbus.sunspec + org.openhab.binding.modbus.sunspec - openHAB Add-ons :: Bundles :: SunSpec Bundle + openHAB Add-ons :: Bundles :: SunSpec Bundle - - - org.openhab.addons.bundles - org.openhab.binding.modbus - ${project.version} - provided - - - org.openhab.addons.bundles - org.openhab.io.transport.modbus - ${project.version} - provided - - + + + org.openhab.addons.bundles + org.openhab.binding.modbus + ${project.version} + provided + + + org.openhab.addons.bundles + org.openhab.io.transport.modbus + ${project.version} + provided + + diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/feature/feature.xml b/bundles/org.openhab.binding.modbus.sunspec/src/main/feature/feature.xml index 765c7a0e6846d..5eb7e1afd7121 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/feature/feature.xml @@ -1,10 +1,11 @@ - file:${basedirRoot}/bundles/org.openhab.binding.modbus/target/feature/feature.xml + file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml - - openhab-runtime-base - openhab-binding-modbus - mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.sunspec/${project.version} - + + openhab-runtime-base + openhab-transport-modbus + mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.modbus.sunspec/${project.version} + diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/SunSpecConstants.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/SunSpecConstants.java index a0aec53b16569..82588af9ef590 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/SunSpecConstants.java +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/SunSpecConstants.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.modbus.sunspec.internal; -import java.util.Collections; +import java.util.HashMap; import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -33,16 +33,39 @@ public class SunSpecConstants { // List of all Thing Type UIDs public static final ThingTypeUID THING_TYPE_INVERTER_SINGLE_PHASE = new ThingTypeUID(BINDING_ID, "inverter-single-phase"); + public static final ThingTypeUID THING_TYPE_INVERTER_SPLIT_PHASE = new ThingTypeUID(BINDING_ID, + "inverter-split-phase"); + public static final ThingTypeUID THING_TYPE_INVERTER_THREE_PHASE = new ThingTypeUID(BINDING_ID, + "inverter-three-phase"); + public static final ThingTypeUID THING_TYPE_METER_SINGLE_PHASE = new ThingTypeUID(BINDING_ID, "meter-single-phase"); + public static final ThingTypeUID THING_TYPE_METER_SPLIT_PHASE = new ThingTypeUID(BINDING_ID, "meter-split-phase"); + public static final ThingTypeUID THING_TYPE_METER_WYE_PHASE = new ThingTypeUID(BINDING_ID, "meter-wye-phase"); + public static final ThingTypeUID THING_TYPE_METER_DELTA_PHASE = new ThingTypeUID(BINDING_ID, "meter-delta-phase"); // Block types public static final int COMMON_BLOCK = 1; public static final int INVERTER_SINGLE_PHASE = 101; + public static final int INVERTER_SPLIT_PHASE = 102; + public static final int INVERTER_THREE_PHASE = 103; + public static final int METER_SINGLE_PHASE = 201; + public static final int METER_SPLIT_PHASE = 202; + public static final int METER_WYE_PHASE = 203; + public static final int METER_DELTA_PHASE = 204; + public static final int FINAL_BLOCK = 0xffff; /** * Map of the supported thing type uids, with their block type id */ - public static final Map SUPPORTED_THING_TYPES_UIDS = Collections - .singletonMap(INVERTER_SINGLE_PHASE, THING_TYPE_INVERTER_SINGLE_PHASE); + public static final Map SUPPORTED_THING_TYPES_UIDS = new HashMap<>(); + static { + SUPPORTED_THING_TYPES_UIDS.put(INVERTER_SINGLE_PHASE, THING_TYPE_INVERTER_SINGLE_PHASE); + SUPPORTED_THING_TYPES_UIDS.put(INVERTER_SPLIT_PHASE, THING_TYPE_INVERTER_SPLIT_PHASE); + SUPPORTED_THING_TYPES_UIDS.put(INVERTER_THREE_PHASE, THING_TYPE_INVERTER_THREE_PHASE); + SUPPORTED_THING_TYPES_UIDS.put(METER_SINGLE_PHASE, THING_TYPE_METER_SINGLE_PHASE); + SUPPORTED_THING_TYPES_UIDS.put(METER_SPLIT_PHASE, THING_TYPE_METER_SPLIT_PHASE); + SUPPORTED_THING_TYPES_UIDS.put(METER_WYE_PHASE, THING_TYPE_METER_WYE_PHASE); + SUPPORTED_THING_TYPES_UIDS.put(METER_DELTA_PHASE, THING_TYPE_METER_DELTA_PHASE); + } // properties public static final String PROPERTY_VENDOR = "vendor"; @@ -57,6 +80,10 @@ public class SunSpecConstants { // Channel group ids public static final String GROUP_DEVICE_INFO = "deviceInformation"; public static final String GROUP_AC_GENERAL = "acGeneral"; + public static final String GROUP_AC_PHASE_A = "acPhaseA"; + public static final String GROUP_AC_PHASE_B = "acPhaseB"; + public static final String GROUP_AC_PHASE_C = "acPhaseC"; + public static final String GROUP_DC_GENERAL = "dcGeneral"; // List of all Channel ids in device information group public static final String CHANNEL_PHASE_CONFIGURATION = "phase-configuration"; @@ -75,6 +102,43 @@ public class SunSpecConstants { public static final String CHANNEL_AC_POWER_FACTOR = "ac-power-factor"; public static final String CHANNEL_AC_LIFETIME_ENERGY = "ac-lifetime-energy"; + // List of channels ids in AC general group for meter + public static final String CHANNEL_AC_AVERAGE_VOLTAGE_TO_N = "ac-average-voltage-to-n"; + public static final String CHANNEL_AC_AVERAGE_VOLTAGE_TO_NEXT = "ac-average-voltage-to-next"; + public static final String CHANNEL_AC_TOTAL_REAL_POWER = "ac-total-real-power"; + public static final String CHANNEL_AC_TOTAL_APPARENT_POWER = "ac-total-apparent-power"; + public static final String CHANNEL_AC_TOTAL_REACTIVE_POWER = "ac-total-reactive-power"; + public static final String CHANNEL_AC_AVERAGE_POWER_FACTOR = "ac-average-power-factor"; + public static final String CHANNEL_AC_TOTAL_EXPORTED_REAL_ENERGY = "ac-total-exported-real-energy"; + public static final String CHANNEL_AC_TOTAL_IMPORTED_REAL_ENERGY = "ac-total-imported-real-energy"; + public static final String CHANNEL_AC_TOTAL_EXPORTED_APPARENT_ENERGY = "ac-total-exported-apparent-energy"; + public static final String CHANNEL_AC_TOTAL_IMPORTED_APPARENT_ENERGY = "ac-total-imported-apparent-energy"; + public static final String CHANNEL_AC_TOTAL_IMPORTED_REACTIVE_ENERGY_Q1 = "ac-total-imported-reactive-energy-q1"; + public static final String CHANNEL_AC_TOTAL_IMPORTED_REACTIVE_ENERGY_Q2 = "ac-total-imported-reactive-energy-q2"; + public static final String CHANNEL_AC_TOTAL_EXPORTED_REACTIVE_ENERGY_Q3 = "ac-total-exported-reactive-energy-q3"; + public static final String CHANNEL_AC_TOTAL_EXPORTED_REACTIVE_ENERGY_Q4 = "ac-total-exported-reactive-energy-q4"; + + // List of channel ids in AC phase group for inverter + public static final String CHANNEL_AC_PHASE_CURRENT = "ac-phase-current"; + public static final String CHANNEL_AC_VOLTAGE_TO_NEXT = "ac-voltage-to-next"; + public static final String CHANNEL_AC_VOLTAGE_TO_N = "ac-voltage-to-n"; + + // List of channel ids in DC group for inverter + public static final String CHANNEL_DC_CURRENT = "dc-current"; + public static final String CHANNEL_DC_VOLTAGE = "dc-voltage"; + public static final String CHANNEL_DC_POWER = "dc-power"; + + // List of channel ids in AC phase group for meter + public static final String CHANNEL_AC_REAL_POWER = "ac-real-power"; + public static final String CHANNEL_AC_EXPORTED_REAL_ENERGY = "ac-exported-real-energy"; + public static final String CHANNEL_AC_IMPORTED_REAL_ENERGY = "ac-imported-real-energy"; + public static final String CHANNEL_AC_EXPORTED_APPARENT_ENERGY = "ac-exported-apparent-energy"; + public static final String CHANNEL_AC_IMPORTED_APPARENT_ENERGY = "ac-imported-apparent-energy"; + public static final String CHANNEL_AC_IMPORTED_REACTIVE_ENERGY_Q1 = "ac-imported-reactive-energy-q1"; + public static final String CHANNEL_AC_IMPORTED_REACTIVE_ENERGY_Q2 = "ac-imported-reactive-energy-q2"; + public static final String CHANNEL_AC_EXPORTED_REACTIVE_ENERGY_Q3 = "ac-exported-reactive-energy-q3"; + public static final String CHANNEL_AC_EXPORTED_REACTIVE_ENERGY_Q4 = "ac-exported-reactive-energy-q4"; + // Expected SunSpec ID This is a magic constant to distinguish SunSpec compatible // devices from other modbus devices public static final long SUNSPEC_ID = 0x53756e53; diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/SunSpecHandlerFactory.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/SunSpecHandlerFactory.java index 594dfdb02ef1c..db5ea79984427 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/SunSpecHandlerFactory.java +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/SunSpecHandlerFactory.java @@ -12,10 +12,7 @@ */ package org.openhab.binding.modbus.sunspec.internal; -import static org.openhab.binding.modbus.sunspec.internal.SunSpecConstants.THING_TYPE_INVERTER_SINGLE_PHASE; - -import java.util.Collections; -import java.util.Set; +import static org.openhab.binding.modbus.sunspec.internal.SunSpecConstants.*; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -25,6 +22,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.openhab.binding.modbus.sunspec.internal.handler.InverterHandler; +import org.openhab.binding.modbus.sunspec.internal.handler.MeterHandler; import org.openhab.io.transport.modbus.ModbusManager; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; @@ -52,9 +50,6 @@ public class SunSpecHandlerFactory extends BaseThingHandlerFactory { */ private ModbusManager manager; - private static final Set SUPPORTED_THING_TYPES_UIDS = Collections - .singleton(THING_TYPE_INVERTER_SINGLE_PHASE); - /** * This factory needs a reference to the ModbusManager wich is provided * by the org.openhab.io.transport.modbus bundle. Please make @@ -69,16 +64,23 @@ public SunSpecHandlerFactory(@Reference ModbusManager manager) { @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + return SUPPORTED_THING_TYPES_UIDS.containsValue(thingTypeUID); } @Override protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - if (thingTypeUID.equals(THING_TYPE_INVERTER_SINGLE_PHASE)) { + if (thingTypeUID.equals(THING_TYPE_INVERTER_SINGLE_PHASE) + || thingTypeUID.equals(THING_TYPE_INVERTER_SPLIT_PHASE) + || thingTypeUID.equals(THING_TYPE_INVERTER_THREE_PHASE)) { logger.debug("New InverterHandler created"); return new InverterHandler(thing, manager); + } else if (thingTypeUID.equals(THING_TYPE_METER_SINGLE_PHASE) + || thingTypeUID.equals(THING_TYPE_METER_SPLIT_PHASE) || thingTypeUID.equals(THING_TYPE_METER_WYE_PHASE) + || thingTypeUID.equals(THING_TYPE_METER_DELTA_PHASE)) { + logger.debug("New MeterHandler created"); + return new MeterHandler(thing, manager); } return null; diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/discovery/SunspecDiscoveryParticipant.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/discovery/SunspecDiscoveryParticipant.java new file mode 100644 index 0000000000000..0684e71579c69 --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/discovery/SunspecDiscoveryParticipant.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.modbus.sunspec.internal.discovery; + +import static org.openhab.binding.modbus.sunspec.internal.SunSpecConstants.SUPPORTED_THING_TYPES_UIDS; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.openhab.binding.modbus.discovery.ModbusDiscoveryListener; +import org.openhab.binding.modbus.discovery.ModbusDiscoveryParticipant; +import org.openhab.binding.modbus.handler.EndpointNotInitializedException; +import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Discovery service for sunspec + * + * @author Nagy Attila Gabor - initial contribution + * + */ +@Component(immediate = true) +@NonNullByDefault +public class SunspecDiscoveryParticipant implements ModbusDiscoveryParticipant { + + private final Logger logger = LoggerFactory.getLogger(SunspecDiscoveryParticipant.class); + + @Override + public Set getSupportedThingTypeUIDs() { + return new HashSet(SUPPORTED_THING_TYPES_UIDS.values()); + } + + @Override + public void startDiscovery(ModbusEndpointThingHandler handler, ModbusDiscoveryListener listener) { + logger.trace("Starting sunspec discovery"); + try { + new SunspecDiscoveryProcess(handler, listener).detectModel(); + } catch (EndpointNotInitializedException ex) { + logger.debug("Could not start discovery process"); + listener.discoveryFinished(); + } + } +} diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/discovery/SunspecDiscoveryProcess.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/discovery/SunspecDiscoveryProcess.java new file mode 100644 index 0000000000000..a84febdf4d3fa --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/discovery/SunspecDiscoveryProcess.java @@ -0,0 +1,394 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.modbus.sunspec.internal.discovery; + +import static org.openhab.binding.modbus.sunspec.internal.SunSpecConstants.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.modbus.discovery.ModbusDiscoveryListener; +import org.openhab.binding.modbus.handler.EndpointNotInitializedException; +import org.openhab.binding.modbus.handler.ModbusEndpointThingHandler; +import org.openhab.binding.modbus.sunspec.internal.dto.CommonModelBlock; +import org.openhab.binding.modbus.sunspec.internal.dto.ModelBlock; +import org.openhab.binding.modbus.sunspec.internal.parser.CommonModelParser; +import org.openhab.io.transport.modbus.BasicModbusReadRequestBlueprint; +import org.openhab.io.transport.modbus.BasicPollTaskImpl; +import org.openhab.io.transport.modbus.BitArray; +import org.openhab.io.transport.modbus.ModbusBitUtilities; +import org.openhab.io.transport.modbus.ModbusConstants.ValueType; +import org.openhab.io.transport.modbus.ModbusReadCallback; +import org.openhab.io.transport.modbus.ModbusReadFunctionCode; +import org.openhab.io.transport.modbus.ModbusReadRequestBlueprint; +import org.openhab.io.transport.modbus.ModbusRegisterArray; +import org.openhab.io.transport.modbus.ModbusSlaveErrorResponseException; +import org.openhab.io.transport.modbus.PollTask; +import org.openhab.io.transport.modbus.endpoint.ModbusSlaveEndpoint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This class is used by the SunspecDiscoveryParticipant to detect + * the model blocks defined by the given device. + * It scans trough the defined model items and notifies the + * discovery service about the discovered devices + * + * @author Nagy Attila Gabor - Initial contribution + */ +@NonNullByDefault +public class SunspecDiscoveryProcess { + + /** + * Logger instance + */ + private final Logger logger = LoggerFactory.getLogger(SunspecDiscoveryProcess.class); + + /** + * The handler instance for this device + */ + private final ModbusEndpointThingHandler handler; + + /** + * The endpoint where we can reach the device + */ + private final ModbusSlaveEndpoint endpoint; + + /** + * Listener for the discovered devices. We get this + * from the main discovery service, and it is used to + * submit any discovered Sunspec devices + */ + private final ModbusDiscoveryListener listener; + + /** + * The endpoint's slave id + */ + private int slaveId; + + /** + * Number of maximum retries + */ + private static final int maxTries = 3; + + /** + * List of start addresses to try + */ + private Queue possibleAddresses; + + /** + * This is the base address where the next block should be searched for + */ + private int baseAddress = 40000; + + /** + * Count of valid Sunspec blocks found + */ + private int blocksFound = 0; + + /** + * Parser for commonblock + */ + private final CommonModelParser commonBlockParser; + + /** + * The last common block found. This is used + * to get the details of any found devices + */ + private @Nullable CommonModelBlock lastCommonBlock = null; + + /** + * New instances of this class should get a reference to the handler + * + * @throws EndpointNotInitializedException + */ + public SunspecDiscoveryProcess(ModbusEndpointThingHandler handler, ModbusDiscoveryListener listener) + throws EndpointNotInitializedException { + this.handler = handler; + + ModbusSlaveEndpoint endpoint = this.handler.asSlaveEndpoint(); + if (endpoint != null) { + this.endpoint = endpoint; + } else { + throw new EndpointNotInitializedException(); + } + slaveId = handler.getSlaveId(); + this.listener = listener; + commonBlockParser = new CommonModelParser(); + possibleAddresses = new ConcurrentLinkedQueue<>(); + // Preferred and alternate base registers + // @see SunSpec Information Model Overview + possibleAddresses.add(40000); + possibleAddresses.add(50000); + possibleAddresses.add(0); + } + + /** + * Start model detection + * + * @param uid the thing type to look for + * @throws EndpointNotInitializedException + */ + public void detectModel() { + + if (possibleAddresses.isEmpty()) { + parsingFinished(); + return; + } + // Try the next address from the possibles + baseAddress = possibleAddresses.poll(); + logger.trace("Beginning scan for SunSpec device at address {}", baseAddress); + + BasicModbusReadRequestBlueprint request = new BasicModbusReadRequestBlueprint(slaveId, + ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, baseAddress, // Start address + SUNSPEC_ID_SIZE, // number or words to return + maxTries); + + PollTask task = new BasicPollTaskImpl(endpoint, request, new ModbusReadCallback() { + + @Override + public void onRegisters(ModbusReadRequestBlueprint request, ModbusRegisterArray registers) { + headerReceived(registers); + } + + @Override + public void onError(ModbusReadRequestBlueprint request, Exception error) { + handleError(error); + } + + @Override + public void onBits(@Nullable ModbusReadRequestBlueprint request, @Nullable BitArray bits) { + // don't care, we don't expect this result + } + }); + + handler.getManagerRef().get().submitOneTimePoll(task); + } + + /** + * We received the first two words, that should equal to SunS + */ + private void headerReceived(ModbusRegisterArray registers) { + logger.trace("Received response from device {}", registers.toString()); + + Optional id = ModbusBitUtilities.extractStateFromRegisters(registers, 0, ValueType.UINT32); + + if (!id.isPresent() || id.get().longValue() != SUNSPEC_ID) { + logger.debug("Could not find SunSpec DID at address {}, received: {}, expected: {}", baseAddress, id, + SUNSPEC_ID); + detectModel(); + return; + } + + logger.trace("Header looks correct"); + baseAddress += SUNSPEC_ID_SIZE; + + lookForModelBlock(); + } + + /** + * Look for a valid model block at the current base address + */ + private void lookForModelBlock() { + + BasicModbusReadRequestBlueprint request = new BasicModbusReadRequestBlueprint(slaveId, + ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, baseAddress, // Start address + MODEL_HEADER_SIZE, // number or words to return + maxTries); + + PollTask task = new BasicPollTaskImpl(endpoint, request, new ModbusReadCallback() { + + @Override + public void onRegisters(ModbusReadRequestBlueprint request, ModbusRegisterArray registers) { + modelBlockReceived(registers); + } + + @Override + public void onError(ModbusReadRequestBlueprint request, Exception error) { + handleError(error); + } + + @Override + public void onBits(@Nullable ModbusReadRequestBlueprint request, @Nullable BitArray bits) { + // don't care, we don't expect this result + } + }); + + handler.getManagerRef().get().submitOneTimePoll(task); + } + + /** + * We received a model block header + */ + private void modelBlockReceived(ModbusRegisterArray registers) { + logger.debug("Received response from device {}", registers.toString()); + + Optional moduleID = ModbusBitUtilities.extractStateFromRegisters(registers, 0, ValueType.UINT16); + Optional blockLength = ModbusBitUtilities.extractStateFromRegisters(registers, 1, + ValueType.UINT16); + + if (!moduleID.isPresent() || !blockLength.isPresent()) { + logger.info("Could not find valid module id or block length field."); + parsingFinished(); + return; + } + ModelBlock block = new ModelBlock(); + block.address = baseAddress; + block.moduleID = moduleID.get().intValue(); + block.length = blockLength.get().intValue() + MODEL_HEADER_SIZE; + logger.debug("SunSpec detector found block {}", block); + + blocksFound++; + + if (block.moduleID == FINAL_BLOCK) { + parsingFinished(); + } else { + baseAddress += block.length; + if (block.moduleID == COMMON_BLOCK) { + readCommonBlock(block); // This is an asynchronous task + return; + } else { + createDiscoveryResult(block); + lookForModelBlock(); + } + + } + } + + /** + * Start reading common block + * + * @param block + */ + private void readCommonBlock(ModelBlock block) { + BasicModbusReadRequestBlueprint request = new BasicModbusReadRequestBlueprint(slaveId, + ModbusReadFunctionCode.READ_MULTIPLE_REGISTERS, block.address, // Start address + block.length, // number or words to return + maxTries); + + PollTask task = new BasicPollTaskImpl(endpoint, request, new ModbusReadCallback() { + + @Override + public void onRegisters(ModbusReadRequestBlueprint request, ModbusRegisterArray registers) { + parseCommonBlock(registers); + } + + @Override + public void onError(ModbusReadRequestBlueprint request, Exception error) { + handleError(error); + } + + @Override + public void onBits(@Nullable ModbusReadRequestBlueprint request, @Nullable BitArray bits) { + // don't care, we don't expect this result + } + }); + + handler.getManagerRef().get().submitOneTimePoll(task); + } + + /** + * We've read the details of a common block now parse it, and + * store for later use + * + * @param registers + */ + private void parseCommonBlock(ModbusRegisterArray registers) { + logger.trace("Got common block data: {}", registers); + lastCommonBlock = commonBlockParser.parse(registers); + lookForModelBlock(); // Continue parsing + } + + /** + * Create a discovery result from a model block + * + * @param block the block we've found + */ + private void createDiscoveryResult(ModelBlock block) { + if (!SUPPORTED_THING_TYPES_UIDS.containsKey(block.moduleID)) { + logger.debug("ModuleID {} is not supported, skipping this block", block.moduleID); + return; + } + + CommonModelBlock commonBlock = lastCommonBlock; + + if (commonBlock == null) { + logger.warn( + "Found model block without a preceding common block. Can't add device because details are unkown"); + return; + } + + ThingUID thingUID = new ThingUID(SUPPORTED_THING_TYPES_UIDS.get(block.moduleID), handler.getUID(), + Integer.toString(block.address)); + + Map properties = new HashMap<>(); + properties.put(PROPERTY_VENDOR, commonBlock.manufacturer); + properties.put(PROPERTY_MODEL, commonBlock.model); + properties.put(PROPERTY_SERIAL_NUMBER, commonBlock.serialNumber); + properties.put(PROPERTY_VERSION, commonBlock.version); + properties.put(PROPERTY_BLOCK_ADDRESS, block.address); + properties.put(PROPERTY_BLOCK_LENGTH, block.length); + properties.put(PROPERTY_UNIQUE_ADDRESS, handler.getUID().getAsString() + ":" + block.address); + + DiscoveryResult result = DiscoveryResultBuilder.create(thingUID).withProperties(properties) + .withRepresentationProperty(PROPERTY_UNIQUE_ADDRESS).withBridge(handler.getUID()) + .withLabel(commonBlock.manufacturer + " " + commonBlock.model).build(); + + listener.thingDiscovered(result); + } + + /** + * Parsing of model blocks finished + * Now we have to report back to the handler the common block and the block we were looking for + */ + private void parsingFinished() { + listener.discoveryFinished(); + } + + /** + * Handle errors received during communication + */ + private void handleError(Exception error) { + String msg = ""; + String cls = ""; + + if (blocksFound > 1 && error instanceof ModbusSlaveErrorResponseException) { + int code = ((ModbusSlaveErrorResponseException) error).getExceptionCode(); + if (code == ModbusSlaveErrorResponseException.ILLEGAL_DATA_ACCESS + || code == ModbusSlaveErrorResponseException.ILLEGAL_DATA_VALUE) { + // It is very likely that the slave does not report an end block (0xffff) after the main blocks + // so we treat this situation as normal. + logger.debug( + "Seems like slave device does not report an end block. Continouing with the dectected blocks"); + parsingFinished(); + return; + } + } + + cls = error.getClass().getName(); + msg = error.getMessage(); + + logger.warn("Error with read at address {}: {} {}", baseAddress, cls, msg); + + detectModel(); + } +} diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/CommonModelBlock.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/CommonModelBlock.java new file mode 100644 index 0000000000000..b3c9db0c82261 --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/CommonModelBlock.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.modbus.sunspec.internal.dto; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * This class contains information parsed from the Common Model block + * + * @author Nagy Attila Gabor - Initial contribution + * + */ +@NonNullByDefault +public class CommonModelBlock { + + /** + * Value = 0x0001. Uniquely identifies this as a SunSpec Common Model Block + */ + public int sunSpecDID = 0x0001; + + /** + * Length of block in 16-bit registers + */ + public int length = 0; + + /** + * Modbus unit ID - this is a unique identifier of the device + */ + public int deviceAddress = 0; + + // Manufacturer specific values + public String manufacturer = ""; + public String model = ""; + public String version = ""; + public String serialNumber = ""; +} diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/InverterModelBlock.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/InverterModelBlock.java index 2b8ebe260c7ca..9a12bd4bf0d16 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/InverterModelBlock.java +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/InverterModelBlock.java @@ -37,11 +37,61 @@ public class InverterModelBlock { */ public Integer acCurrentTotal; + /** + * AC Phase A Current value + */ + public Integer acCurrentPhaseA; + + /** + * AC Phase B Current value + */ + public Optional acCurrentPhaseB; + + /** + * AC Phase C Current value + */ + public Optional acCurrentPhaseC; + /** * AC Current scale factor */ public Short acCurrentSF; + /** + * AC Voltage Phase AB value + */ + public Optional acVoltageAB; + + /** + * AC Voltage Phase BC value + */ + public Optional acVoltageBC; + + /** + * AC Voltage Phase CA value + */ + public Optional acVoltageCA; + + /** + * AC Voltage Phase A to N value + */ + public Integer acVoltageAtoN; + + /** + * AC Voltage Phase B to N value + */ + public Optional acVoltageBtoN; + + /** + * AC Voltage Phase C to N value + */ + public Optional acVoltageCtoN; + + /** + * AC Voltage scale factor + */ + public Short acVoltageSF; + /** * AC Power value */ @@ -102,6 +152,36 @@ public class InverterModelBlock { */ public Short acEnergyLifetimeSF; + /** + * DC Current value + */ + public Optional dcCurrent; + + /** + * DC Current scale factor + */ + public Optional dcCurrentSF; + + /** + * DC Voltage value + */ + public Optional dcVoltage; + + /** + * DC Voltage scale factor + */ + public Optional dcVoltageSF; + + /** + * DC Power value + */ + public Optional dcPower; + + /** + * DC Power scale factor + */ + public Optional dcPowerSF; + /** * Cabinet temperature */ @@ -136,5 +216,4 @@ public class InverterModelBlock { * Vendor defined operating state or error code */ public Optional statusVendor; - } diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/MeterModelBlock.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/MeterModelBlock.java new file mode 100644 index 0000000000000..c7793d6d7823f --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/dto/MeterModelBlock.java @@ -0,0 +1,261 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.modbus.sunspec.internal.dto; + +import java.util.Optional; + +/** + * + * Data object for the parsed information from a sunspec meter + * + * @author Nagy Attila Gabor - Initial contribution + * + */ +public class MeterModelBlock { + + /** + * Sunspec device type id + */ + public Integer sunspecDID; + + /** + * Block length + */ + public Integer length; + + /** + * AC Total Current value + */ + public Short acCurrentTotal; + + /** + * Descriptors for phase A + */ + public PhaseBlock phaseA = new PhaseBlock(); + + /** + * Descriptors for phase B + */ + public PhaseBlock phaseB = new PhaseBlock(); + + /** + * Descriptors for phase C + */ + public PhaseBlock phaseC = new PhaseBlock(); + + /** + * AC Current scale factor + */ + public Short acCurrentSF; + + /** + * AC Voltage Line to line value + */ + public Optional acVoltageLineToNAverage; + + /** + * AC Voltage Line to N value + */ + public Optional acVoltageLineToLineAverage; + + /** + * AC Voltage scale factor + */ + public Short acVoltageSF; + + /** + * AC Frequency value + */ + public Short acFrequency; + + /** + * AC Frequency scale factor + */ + public Optional acFrequencySF; + + /** + * Total real power + */ + public Short acRealPowerTotal; + + /** + * AC Real Power Scale Factor + */ + public Short acRealPowerSF; + + /** + * Total apparent power + */ + public Optional acApparentPowerTotal; + + /** + * AC Apparent Power Scale Factor + */ + public Optional acApparentPowerSF; + + /** + * Total reactive power + */ + public Optional acReactivePowerTotal; + + /** + * AC Reactive Power Scale Factor + */ + public Optional acReactivePowerSF; + + /** + * Power factor + */ + public Optional acPowerFactor; + + /** + * Power factor scale factor + */ + public Optional acPowerFactorSF; + + /** + * Total exported real energy + */ + public Optional acExportedRealEnergyTotal; + + /** + * Total imported real energy + */ + public Long acImportedRealEnergyTotal; + + /** + * Real Energy Scale Factor + */ + public Short acRealEnergySF; + + /** + * Total exported apparent energy + */ + public Optional acExportedApparentEnergyTotal; + + /** + * Total imported apparent energy + */ + public Optional acImportedApparentEnergyTotal; + + /** + * Apparent Energy Scale Factor + */ + public Optional acApparentEnergySF; + + /** + * Quadrant 1: Total imported reactive energy + */ + public Optional acImportedReactiveEnergyQ1Total; + + /** + * Quadrant 2: Total imported reactive energy + */ + public Optional acImportedReactiveEnergyQ2Total; + + /** + * Quadrant 3: Total exported reactive energy + */ + public Optional acExportedReactiveEnergyQ3Total; + + /** + * Quadrant 4: Total exported reactive energy + */ + public Optional acExportedReactiveEnergyQ4Total; + + /** + * Reactive Energy Scale Factor + */ + public Optional acReactiveEnergySF; + + /** + * This subclass is used to store raw data for a single phase in + * multi phase meters. + */ + public static class PhaseBlock { + /** + * AC Phase A Current value + */ + public Optional acPhaseCurrent; + + /** + * AC Voltage Phase Phase to N value + */ + public Optional acVoltageToN; + + /** + * AC Voltage Phase Line to next Line value + */ + public Optional acVoltageToNext; + + /** + * Phase A AC real power + */ + public Optional acRealPower; + + /** + * Phase A AC apparent power + */ + public Optional acApparentPower; + + /** + * Phase A AC reactive power + */ + public Optional acReactivePower; + + /** + * Phase A Power factor + */ + public Optional acPowerFactor; + + /** + * Phase A exported real energy + */ + public Optional acExportedRealEnergy; + + /** + * Phase A imported real energy + */ + public Optional acImportedRealEnergy; + + /** + * Phase A exported apparent energy + */ + public Optional acExportedApparentEnergy; + + /** + * Phase A imported apparent energy + */ + public Optional acImportedApparentEnergy; + + /** + * Quadrant 1: Phase A imported reactive energy + */ + public Optional acImportedReactiveEnergyQ1; + + /** + * Quadrant 2: Phase A imported reactive energy + */ + public Optional acImportedReactiveEnergyQ2; + + /** + * Quadrant 3: Phase A exported reactive energy + */ + public Optional acExportedReactiveEnergyQ3; + + /** + * Quadrant 4: Phase A exported reactive energy + */ + public Optional acExportedReactiveEnergyQ4; + } +} diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/AbstractSunSpecHandler.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/AbstractSunSpecHandler.java index 6c65059d8b629..b963eec02a6cf 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/AbstractSunSpecHandler.java +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/AbstractSunSpecHandler.java @@ -12,7 +12,7 @@ */ package org.openhab.binding.modbus.sunspec.internal.handler; -import static org.openhab.binding.modbus.sunspec.internal.SunSpecConstants.PROPERTY_UNIQUE_ADDRESS; +import static org.openhab.binding.modbus.sunspec.internal.SunSpecConstants.*; import java.math.BigDecimal; import java.util.Map; @@ -22,7 +22,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -152,11 +151,18 @@ private void startUp() { return; } - Optional mainBlock = getAddressFromConfig(); - if (mainBlock.isPresent()) { - publishUniqueAddress(mainBlock.get()); + // Try properties first + @Nullable + ModelBlock mainBlock = getAddressFromProperties(); + + if (mainBlock == null) { + mainBlock = getAddressFromConfig(); + } + + if (mainBlock != null) { + publishUniqueAddress(mainBlock); updateStatus(ThingStatus.UNKNOWN); - registerPollTask(mainBlock.get()); + registerPollTask(mainBlock); } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "SunSpec item should either have the address and length configuration set or should been created by auto discovery"); @@ -164,19 +170,39 @@ private void startUp() { } } + /** + * Load and parse configuration from the properties + * These will be set by the auto discovery process + */ + private @Nullable ModelBlock getAddressFromProperties() { + Map properties = thing.getProperties(); + if (!properties.containsKey(PROPERTY_BLOCK_ADDRESS) || !properties.containsKey(PROPERTY_BLOCK_LENGTH)) { + return null; + } + try { + ModelBlock block = new ModelBlock(); + block.address = (int) Double.parseDouble(thing.getProperties().get(PROPERTY_BLOCK_ADDRESS)); + block.length = (int) Double.parseDouble(thing.getProperties().get(PROPERTY_BLOCK_LENGTH)); + return block; + } catch (NumberFormatException ex) { + logger.debug("Could not parse address and length properties, error: {}", ex.getMessage()); + return null; + } + } + /** * Load configuration from main configuration */ - private Optional getAddressFromConfig() { + private @Nullable ModelBlock getAddressFromConfig() { @Nullable SunSpecConfiguration myconfig = config; if (myconfig == null) { - return Optional.empty(); + return null; } ModelBlock block = new ModelBlock(); block.address = myconfig.address; block.length = myconfig.length; - return Optional.of(block); + return block; } /** @@ -345,8 +371,9 @@ public void onBits(@Nullable ModbusReadRequestBlueprint request, @Nullable BitAr }); long refreshMillis = myconfig.getRefreshMillis(); - if (pollTask != null) { - PollTask task = pollTask; + @Nullable + PollTask task = pollTask; + if (task != null) { managerRef.registerRegularPoll(task, refreshMillis, 1000); } } @@ -444,25 +471,11 @@ ChannelUID channelUID(String group, String id) { * @param scaleFactor the scale factor to use (may be negative) * @return the scaled value as a DecimalType */ - protected State getScaled(Optional value, Optional scaleFactor) { + protected State getScaled(Optional value, Optional scaleFactor, Unit unit) { if (!value.isPresent() || !scaleFactor.isPresent()) { return UnDefType.UNDEF; } - return getScaled(value.get().longValue(), scaleFactor.get()); - } - - /** - * Returns value multiplied by the 10 on the power of scaleFactory - * - * @param value the value to alter - * @param scaleFactor the scale factor to use (may be negative) - * @return the scaled value as a DecimalType - */ - protected State getScaled(Number value, Short scaleFactor) { - if (scaleFactor == 1) { - return new DecimalType(value.longValue()); - } - return new DecimalType(BigDecimal.valueOf(value.longValue(), scaleFactor * -1)); + return getScaled(value.get().longValue(), scaleFactor.get(), unit); } /** @@ -472,11 +485,8 @@ protected State getScaled(Number value, Short scaleFactor) { * @param scaleFactor the scale factor to use (may be negative) * @return the scaled value as a DecimalType */ - protected State getScaled(Optional value, Optional scaleFactor, Unit unit) { - if (!value.isPresent() || !scaleFactor.isPresent()) { - return UnDefType.UNDEF; - } - return getScaled(value.get().longValue(), scaleFactor.get(), unit); + protected State getScaled(Optional value, Short scaleFactor, Unit unit) { + return getScaled(value, Optional.of(scaleFactor), unit); } /** diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/InverterHandler.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/InverterHandler.java index 7950fe9d38062..25c582553fde7 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/InverterHandler.java +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/InverterHandler.java @@ -20,7 +20,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.modbus.sunspec.internal.InverterStatus; @@ -81,7 +80,7 @@ protected void handlePolledData(ModbusRegisterArray registers) { getScaled(block.temperatureOther, Optional.of(block.temperatureSF), CELSIUS)); InverterStatus status = InverterStatus.getByCode(block.status); - updateState(new ChannelUID(getThing().getUID(), GROUP_DEVICE_INFO, CHANNEL_STATUS), + updateState(channelUID(GROUP_DEVICE_INFO, CHANNEL_STATUS), status == null ? UnDefType.UNDEF : new StringType(status.name())); // AC General group @@ -109,7 +108,45 @@ protected void handlePolledData(ModbusRegisterArray registers) { updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_LIFETIME_ENERGY), getScaled(block.acEnergyLifetime, block.acEnergyLifetimeSF, WATT_HOUR)); + // DC General group + updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_CURRENT), + getScaled(block.dcCurrent, block.dcCurrentSF, AMPERE)); + updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_VOLTAGE), + getScaled(block.dcVoltage, block.dcVoltageSF, VOLT)); + updateState(channelUID(GROUP_DC_GENERAL, CHANNEL_DC_POWER), getScaled(block.dcPower, block.dcPowerSF, WATT)); + + // AC Phase specific groups + // All types of inverters + updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_PHASE_CURRENT), + getScaled(block.acCurrentPhaseA, block.acCurrentSF, AMPERE)); + updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_VOLTAGE_TO_NEXT), + getScaled(block.acVoltageAB, block.acVoltageSF, VOLT)); + updateState(channelUID(GROUP_AC_PHASE_A, CHANNEL_AC_VOLTAGE_TO_N), + getScaled(block.acVoltageAtoN, block.acVoltageSF, VOLT)); + + // Split phase and three phase + if ((thing.getThingTypeUID().equals(THING_TYPE_INVERTER_SPLIT_PHASE) + || thing.getThingTypeUID().equals(THING_TYPE_INVERTER_THREE_PHASE)) + && block.phaseConfiguration >= INVERTER_SPLIT_PHASE) { + updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_PHASE_CURRENT), + getScaled(block.acCurrentPhaseB, block.acCurrentSF, AMPERE)); + updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_VOLTAGE_TO_NEXT), + getScaled(block.acVoltageBC, block.acVoltageSF, VOLT)); + updateState(channelUID(GROUP_AC_PHASE_B, CHANNEL_AC_VOLTAGE_TO_N), + getScaled(block.acVoltageBtoN, block.acVoltageSF, VOLT)); + } + + // Three phase only + if (thing.getThingTypeUID().equals(THING_TYPE_INVERTER_THREE_PHASE) + && block.phaseConfiguration >= INVERTER_THREE_PHASE) { + updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_PHASE_CURRENT), + getScaled(block.acCurrentPhaseC, block.acCurrentSF, AMPERE)); + updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_VOLTAGE_TO_NEXT), + getScaled(block.acVoltageCA, block.acVoltageSF, VOLT)); + updateState(channelUID(GROUP_AC_PHASE_C, CHANNEL_AC_VOLTAGE_TO_N), + getScaled(block.acVoltageCtoN, block.acVoltageSF, VOLT)); + } + resetCommunicationError(); } - } diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/MeterHandler.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/MeterHandler.java new file mode 100644 index 0000000000000..aba27a79140e9 --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/handler/MeterHandler.java @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.modbus.sunspec.internal.handler; + +import static org.eclipse.smarthome.core.library.unit.SmartHomeUnits.*; +import static org.openhab.binding.modbus.sunspec.internal.SunSpecConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.Thing; +import org.openhab.binding.modbus.sunspec.internal.dto.MeterModelBlock; +import org.openhab.binding.modbus.sunspec.internal.parser.MeterModelParser; +import org.openhab.io.transport.modbus.ModbusManager; +import org.openhab.io.transport.modbus.ModbusRegisterArray; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This handler is responsible for handling data recieved from a sunspec meter + * + * @author Nagy Attila Gabor - Initial contribution + * + */ +@NonNullByDefault +public class MeterHandler extends AbstractSunSpecHandler { + + /** + * Parser used to convert incoming raw messages into model blocks + */ + private final MeterModelParser parser = new MeterModelParser(); + + /** + * Logger instance + */ + private final Logger logger = LoggerFactory.getLogger(MeterHandler.class); + + public MeterHandler(Thing thing, ModbusManager managerRef) { + super(thing, managerRef); + } + + /** + * Receive polled data, parse then update states + */ + @Override + protected void handlePolledData(ModbusRegisterArray registers) { + logger.trace("Model block received, size: {}", registers.size()); + + MeterModelBlock block = parser.parse(registers); + + // AC General group + updateTotalValues(block); + + updatePhaseValues(block, block.phaseA, GROUP_AC_PHASE_A); + + // Split phase, wye/delta phase + if (block.sunspecDID >= METER_SPLIT_PHASE && (thing.getThingTypeUID().equals(THING_TYPE_METER_SPLIT_PHASE) + || thing.getThingTypeUID().equals(THING_TYPE_METER_WYE_PHASE) + || thing.getThingTypeUID().equals(THING_TYPE_METER_DELTA_PHASE))) { + updatePhaseValues(block, block.phaseB, GROUP_AC_PHASE_B); + } + + // Three phase (wye/delta) only + if (block.sunspecDID >= INVERTER_THREE_PHASE && (thing.getThingTypeUID().equals(THING_TYPE_METER_WYE_PHASE) + || thing.getThingTypeUID().equals(THING_TYPE_METER_DELTA_PHASE))) { + updatePhaseValues(block, block.phaseC, GROUP_AC_PHASE_C); + } + + resetCommunicationError(); + } + + /** + * Update the total states from the received block + * + * @param block + */ + private void updateTotalValues(MeterModelBlock block) { + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_CURRENT), + getScaled(block.acCurrentTotal, block.acCurrentSF, AMPERE)); + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_AVERAGE_VOLTAGE_TO_N), + getScaled(block.acVoltageLineToNAverage, block.acVoltageSF, VOLT)); + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_AVERAGE_VOLTAGE_TO_NEXT), + getScaled(block.acVoltageLineToLineAverage, block.acVoltageSF, VOLT)); + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_FREQUENCY), + getScaled(block.acFrequency, block.acFrequencySF.orElse((short) 1), HERTZ)); + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_REAL_POWER), + getScaled(block.acRealPowerTotal, block.acRealPowerSF, WATT)); + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_APPARENT_POWER), + getScaled(block.acApparentPowerTotal, block.acApparentPowerSF, WATT)); // TODO: this should be VA + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_REACTIVE_POWER), + getScaled(block.acReactivePowerTotal, block.acReactivePowerSF, WATT)); // TODO: this should be VAR + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_AVERAGE_POWER_FACTOR), + getScaled(block.acPowerFactor, block.acPowerFactorSF, PERCENT)); + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_EXPORTED_REAL_ENERGY), + getScaled(block.acExportedRealEnergyTotal, block.acRealEnergySF, WATT_HOUR)); + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_IMPORTED_REAL_ENERGY), + getScaled(block.acImportedRealEnergyTotal, block.acRealEnergySF, WATT_HOUR)); + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_EXPORTED_APPARENT_ENERGY), + getScaled(block.acExportedApparentEnergyTotal, block.acApparentEnergySF, WATT_HOUR)); // TODO: this + // should be + // VA_HOUR + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_IMPORTED_APPARENT_ENERGY), + getScaled(block.acImportedApparentEnergyTotal, block.acApparentEnergySF, WATT_HOUR)); // TODO: this + // should be + // VA_HOUR + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_IMPORTED_REACTIVE_ENERGY_Q1), + getScaled(block.acImportedReactiveEnergyQ1Total, block.acReactiveEnergySF, WATT_HOUR)); // TODO: this + // should be + // VAR_HOUR + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_IMPORTED_REACTIVE_ENERGY_Q2), + getScaled(block.acImportedReactiveEnergyQ2Total, block.acReactiveEnergySF, WATT_HOUR)); // TODO: this + // should be + // VAR_HOUR + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_EXPORTED_REACTIVE_ENERGY_Q3), + getScaled(block.acExportedReactiveEnergyQ3Total, block.acReactiveEnergySF, WATT_HOUR)); // TODO: this + // should be + // VAR_HOUR + + updateState(channelUID(GROUP_AC_GENERAL, CHANNEL_AC_TOTAL_EXPORTED_REACTIVE_ENERGY_Q4), + getScaled(block.acExportedReactiveEnergyQ4Total, block.acReactiveEnergySF, WATT_HOUR)); // TODO: this + // should be + // VAR_HOUR + } + + /** + * Update phase related channels for the selected phase. + * + * @param block the main block for scale + * @param phaseBlock the block containing the raw values for the selected phase + * @param group channel group id for the output + */ + private void updatePhaseValues(MeterModelBlock block, MeterModelBlock.PhaseBlock phaseBlock, String group) { + updateState(channelUID(group, CHANNEL_AC_PHASE_CURRENT), + getScaled(phaseBlock.acPhaseCurrent, block.acCurrentSF, AMPERE)); + + updateState(channelUID(group, CHANNEL_AC_VOLTAGE_TO_N), + getScaled(phaseBlock.acVoltageToN, block.acVoltageSF, VOLT)); + + updateState(channelUID(group, CHANNEL_AC_VOLTAGE_TO_NEXT), + getScaled(phaseBlock.acVoltageToNext, block.acVoltageSF, VOLT)); + + updateState(channelUID(group, CHANNEL_AC_REAL_POWER), + getScaled(phaseBlock.acRealPower, block.acRealPowerSF, WATT)); + + updateState(channelUID(group, CHANNEL_AC_APPARENT_POWER), + getScaled(phaseBlock.acApparentPower, block.acApparentPowerSF, WATT)); // TODO: this should be VA + + updateState(channelUID(group, CHANNEL_AC_REACTIVE_POWER), + getScaled(phaseBlock.acReactivePower, block.acReactivePowerSF, WATT)); // TODO: this should be VAR + + updateState(channelUID(group, CHANNEL_AC_POWER_FACTOR), + getScaled(phaseBlock.acPowerFactor, block.acPowerFactorSF, PERCENT)); + + updateState(channelUID(group, CHANNEL_AC_EXPORTED_REAL_ENERGY), + getScaled(phaseBlock.acExportedRealEnergy, block.acRealEnergySF, WATT_HOUR)); + + updateState(channelUID(group, CHANNEL_AC_IMPORTED_REAL_ENERGY), + getScaled(phaseBlock.acImportedRealEnergy, block.acRealEnergySF, WATT_HOUR)); + + updateState(channelUID(group, CHANNEL_AC_EXPORTED_APPARENT_ENERGY), + getScaled(phaseBlock.acExportedApparentEnergy, block.acApparentEnergySF, WATT_HOUR)); // TODO: this + // should be + // VA_HOUR + + updateState(channelUID(group, CHANNEL_AC_IMPORTED_APPARENT_ENERGY), + getScaled(phaseBlock.acImportedApparentEnergy, block.acApparentEnergySF, WATT_HOUR)); // TODO: this + // should be + // VA_HOUR + + updateState(channelUID(group, CHANNEL_AC_IMPORTED_REACTIVE_ENERGY_Q1), + getScaled(phaseBlock.acImportedReactiveEnergyQ1, block.acReactiveEnergySF, WATT_HOUR)); // TODO: this + // should be + // VAR_HOUR + + updateState(channelUID(group, CHANNEL_AC_IMPORTED_REACTIVE_ENERGY_Q2), + getScaled(phaseBlock.acImportedReactiveEnergyQ2, block.acReactiveEnergySF, WATT_HOUR)); // TODO: this + // should be + // VAR_HOUR + + updateState(channelUID(group, CHANNEL_AC_EXPORTED_REACTIVE_ENERGY_Q3), + getScaled(phaseBlock.acExportedReactiveEnergyQ3, block.acReactiveEnergySF, WATT_HOUR)); // TODO: this + // should be + // VAR_HOUR + + updateState(channelUID(group, CHANNEL_AC_EXPORTED_REACTIVE_ENERGY_Q4), + getScaled(phaseBlock.acExportedReactiveEnergyQ4, block.acReactiveEnergySF, WATT_HOUR)); // TODO: this + // should be + // VAR_HOUR + } +} diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/CommonModelParser.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/CommonModelParser.java new file mode 100644 index 0000000000000..fb20e82271d2b --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/CommonModelParser.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.modbus.sunspec.internal.parser; + +import java.nio.charset.Charset; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.modbus.sunspec.internal.SunSpecConstants; +import org.openhab.binding.modbus.sunspec.internal.dto.CommonModelBlock; +import org.openhab.io.transport.modbus.ModbusBitUtilities; +import org.openhab.io.transport.modbus.ModbusRegisterArray; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Parser for the Common Message block + * + * @author Nagy Attila Gabor - Initial contribution + * + */ +@NonNullByDefault +public class CommonModelParser extends AbstractBaseParser implements SunspecParser { + + /** + * Logger instance + */ + private final Logger logger = LoggerFactory.getLogger(CommonModelParser.class); + + @Override + public CommonModelBlock parse(ModbusRegisterArray raw) { + + CommonModelBlock block = new CommonModelBlock(); + + block.sunSpecDID = extractUInt16(raw, 0, 0); + + block.length = extractUInt16(raw, 1, raw.size() - SunSpecConstants.MODEL_HEADER_SIZE); + + if (block.length + SunSpecConstants.MODEL_HEADER_SIZE != raw.size()) { + logger.warn("Short read on common block loding. Expected size: {}, got: {}", + block.length + SunSpecConstants.MODEL_HEADER_SIZE, raw.size()); + return block; + } + + // parse manufacturer, model and version + block.manufacturer = ModbusBitUtilities.extractStringFromRegisters(raw, 2, 32, Charset.forName("UTF-8")) + .toString(); + block.model = ModbusBitUtilities.extractStringFromRegisters(raw, 18, 32, Charset.forName("UTF-8")).toString(); + block.version = ModbusBitUtilities.extractStringFromRegisters(raw, 42, 16, Charset.forName("UTF-8")).toString(); + block.serialNumber = ModbusBitUtilities.extractStringFromRegisters(raw, 50, 32, Charset.forName("UTF-8")) + .toString(); + + block.deviceAddress = extractUInt16(raw, 66, 1); + + return block; + } +} diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/InverterModelParser.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/InverterModelParser.java index eedfdbf159704..1350b112fb901 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/InverterModelParser.java +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/InverterModelParser.java @@ -33,7 +33,19 @@ public InverterModelBlock parse(ModbusRegisterArray raw) { block.phaseConfiguration = extractUInt16(raw, 0, SunSpecConstants.INVERTER_SINGLE_PHASE); block.length = extractUInt16(raw, 1, raw.size()); block.acCurrentTotal = extractUInt16(raw, 2, 0); + block.acCurrentPhaseA = extractUInt16(raw, 3, 0); + block.acCurrentPhaseB = extractOptionalUInt16(raw, 4); + block.acCurrentPhaseC = extractOptionalUInt16(raw, 5); block.acCurrentSF = extractSunSSF(raw, 6); + + block.acVoltageAB = extractOptionalUInt16(raw, 7); + block.acVoltageBC = extractOptionalUInt16(raw, 8); + block.acVoltageCA = extractOptionalUInt16(raw, 9); + block.acVoltageAtoN = extractUInt16(raw, 10, 0); + block.acVoltageBtoN = extractOptionalUInt16(raw, 11); + block.acVoltageCtoN = extractOptionalUInt16(raw, 12); + block.acVoltageSF = extractSunSSF(raw, 13); + block.acPower = extractInt16(raw, 14, (short) 0); block.acPowerSF = extractSunSSF(raw, 15); block.acFrequency = extractUInt16(raw, 16, 0); @@ -46,6 +58,14 @@ public InverterModelBlock parse(ModbusRegisterArray raw) { block.acPowerFactorSF = extractOptionalSunSSF(raw, 23); block.acEnergyLifetime = extractAcc32(raw, 24, 0); block.acEnergyLifetimeSF = extractSunSSF(raw, 26); + + block.dcCurrent = extractOptionalUInt16(raw, 27); + block.dcCurrentSF = extractOptionalSunSSF(raw, 28); + block.dcVoltage = extractOptionalUInt16(raw, 29); + block.dcVoltageSF = extractOptionalSunSSF(raw, 30); + block.dcPower = extractOptionalInt16(raw, 31); + block.dcPowerSF = extractOptionalSunSSF(raw, 32); + block.temperatureCabinet = extractInt16(raw, 33, (short) 0); block.temperatureHeatsink = extractOptionalInt16(raw, 34); block.temperatureTransformer = extractOptionalInt16(raw, 35); @@ -56,5 +76,4 @@ public InverterModelBlock parse(ModbusRegisterArray raw) { return block; } - } diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/MeterModelParser.java b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/MeterModelParser.java new file mode 100644 index 0000000000000..f6adb4a4188d6 --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/java/org/openhab/binding/modbus/sunspec/internal/parser/MeterModelParser.java @@ -0,0 +1,118 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.modbus.sunspec.internal.parser; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.modbus.sunspec.internal.SunSpecConstants; +import org.openhab.binding.modbus.sunspec.internal.dto.MeterModelBlock; +import org.openhab.io.transport.modbus.ModbusRegisterArray; + +/** + * Parser for sunspec compatible meters + * + * @author Nagy Attila Gabor - Initial contribution + * + */ +@NonNullByDefault +public class MeterModelParser extends AbstractBaseParser implements SunspecParser { + + @Override + public MeterModelBlock parse(ModbusRegisterArray raw) { + MeterModelBlock block = new MeterModelBlock(); + + block.sunspecDID = extractUInt16(raw, 0, SunSpecConstants.METER_SINGLE_PHASE); + block.length = extractUInt16(raw, 1, raw.size()); + block.acCurrentTotal = extractInt16(raw, 2, (short) 0); + block.phaseA.acPhaseCurrent = extractOptionalInt16(raw, 3); + block.phaseB.acPhaseCurrent = extractOptionalInt16(raw, 4); + block.phaseC.acPhaseCurrent = extractOptionalInt16(raw, 5); + block.acCurrentSF = extractSunSSF(raw, 6); + + block.acVoltageLineToNAverage = extractOptionalInt16(raw, 7); + block.phaseA.acVoltageToN = extractOptionalInt16(raw, 8); + block.phaseB.acVoltageToN = extractOptionalInt16(raw, 9); + block.phaseC.acVoltageToN = extractOptionalInt16(raw, 10); + block.acVoltageLineToLineAverage = extractOptionalInt16(raw, 11); + block.phaseA.acVoltageToNext = extractOptionalInt16(raw, 12); + block.phaseB.acVoltageToNext = extractOptionalInt16(raw, 13); + block.phaseC.acVoltageToNext = extractOptionalInt16(raw, 14); + block.acVoltageSF = extractSunSSF(raw, 15); + + block.acFrequency = extractInt16(raw, 16, (short) 0); + block.acFrequencySF = extractOptionalSunSSF(raw, 17); + + block.acRealPowerTotal = extractInt16(raw, 18, (short) 0); + block.phaseA.acRealPower = extractOptionalInt16(raw, 19); + block.phaseB.acRealPower = extractOptionalInt16(raw, 20); + block.phaseC.acRealPower = extractOptionalInt16(raw, 21); + block.acRealPowerSF = extractSunSSF(raw, 22); + + block.acApparentPowerTotal = extractOptionalInt16(raw, 23); + block.phaseA.acApparentPower = extractOptionalInt16(raw, 24); + block.phaseB.acApparentPower = extractOptionalInt16(raw, 25); + block.phaseC.acApparentPower = extractOptionalInt16(raw, 26); + block.acApparentPowerSF = extractOptionalSunSSF(raw, 27); + + block.acReactivePowerTotal = extractOptionalInt16(raw, 28); + block.phaseA.acReactivePower = extractOptionalInt16(raw, 29); + block.phaseB.acReactivePower = extractOptionalInt16(raw, 30); + block.phaseC.acReactivePower = extractOptionalInt16(raw, 31); + block.acReactivePowerSF = extractOptionalSunSSF(raw, 32); + + block.acPowerFactor = extractOptionalInt16(raw, 33); + block.phaseA.acPowerFactor = extractOptionalInt16(raw, 34); + block.phaseB.acPowerFactor = extractOptionalInt16(raw, 35); + block.phaseC.acPowerFactor = extractOptionalInt16(raw, 36); + block.acPowerFactorSF = extractOptionalSunSSF(raw, 37); + + block.acExportedRealEnergyTotal = extractOptionalAcc32(raw, 38); + block.phaseA.acExportedRealEnergy = extractOptionalAcc32(raw, 40); + block.phaseB.acExportedRealEnergy = extractOptionalAcc32(raw, 42); + block.phaseC.acExportedRealEnergy = extractOptionalAcc32(raw, 44); + block.acImportedRealEnergyTotal = extractAcc32(raw, 46, 0); + block.phaseA.acImportedRealEnergy = extractOptionalAcc32(raw, 48); + block.phaseB.acImportedRealEnergy = extractOptionalAcc32(raw, 50); + block.phaseC.acImportedRealEnergy = extractOptionalAcc32(raw, 52); + block.acRealEnergySF = extractSunSSF(raw, 54); + + block.acExportedApparentEnergyTotal = extractOptionalAcc32(raw, 55); + block.phaseA.acExportedApparentEnergy = extractOptionalAcc32(raw, 57); + block.phaseB.acExportedApparentEnergy = extractOptionalAcc32(raw, 59); + block.phaseC.acExportedApparentEnergy = extractOptionalAcc32(raw, 61); + block.acImportedApparentEnergyTotal = extractOptionalAcc32(raw, 63); + block.phaseA.acImportedApparentEnergy = extractOptionalAcc32(raw, 65); + block.phaseB.acImportedApparentEnergy = extractOptionalAcc32(raw, 67); + block.phaseC.acImportedApparentEnergy = extractOptionalAcc32(raw, 69); + block.acApparentEnergySF = extractOptionalSunSSF(raw, 71); + + block.acImportedReactiveEnergyQ1Total = extractOptionalAcc32(raw, 72); + block.phaseA.acImportedReactiveEnergyQ1 = extractOptionalAcc32(raw, 74); + block.phaseB.acImportedReactiveEnergyQ1 = extractOptionalAcc32(raw, 76); + block.phaseC.acImportedReactiveEnergyQ1 = extractOptionalAcc32(raw, 78); + block.acImportedReactiveEnergyQ2Total = extractOptionalAcc32(raw, 80); + block.phaseA.acImportedReactiveEnergyQ2 = extractOptionalAcc32(raw, 82); + block.phaseB.acImportedReactiveEnergyQ2 = extractOptionalAcc32(raw, 84); + block.phaseC.acImportedReactiveEnergyQ2 = extractOptionalAcc32(raw, 86); + block.acExportedReactiveEnergyQ3Total = extractOptionalAcc32(raw, 88); + block.phaseA.acExportedReactiveEnergyQ3 = extractOptionalAcc32(raw, 90); + block.phaseB.acExportedReactiveEnergyQ3 = extractOptionalAcc32(raw, 92); + block.phaseC.acExportedReactiveEnergyQ3 = extractOptionalAcc32(raw, 94); + block.acExportedReactiveEnergyQ4Total = extractOptionalAcc32(raw, 96); + block.phaseA.acExportedReactiveEnergyQ4 = extractOptionalAcc32(raw, 98); + block.phaseB.acExportedReactiveEnergyQ4 = extractOptionalAcc32(raw, 100); + block.phaseC.acExportedReactiveEnergyQ4 = extractOptionalAcc32(raw, 102); + block.acReactiveEnergySF = extractOptionalSunSSF(raw, 104); + + return block; + } +} diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-channel-groups.xml b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-channel-groups.xml index a6317563160c7..ad7fb5a157b29 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-channel-groups.xml +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-channel-groups.xml @@ -1,5 +1,6 @@ - @@ -13,7 +14,7 @@ - + @@ -27,4 +28,22 @@ + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-channel-types.xml b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-channel-types.xml index 4c1ae82ea905b..fa0506bbc02a8 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-channel-types.xml +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-channel-types.xml @@ -1,5 +1,6 @@ - @@ -8,68 +9,105 @@ - + + + Number:ElectricCurrent + + + + + + Number:ElectricPotential + + This phase's AC voltage relative to the next phase + + + + + Number:ElectricPotential + + This phase's AC voltage relative to N line + + + Number:Power - + Number:Frequency - + Number:Power - + Number:Power - + Number:Dimensionless - + Number:Energy - + + + Number:ElectricCurrent + + + + + + Number:ElectricPotential + + + + + + Number:Power + + + + Number:Temperature - + - + Number:Temperature - + Number:Temperature - + Number:Temperature - String diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-types.xml b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-types.xml index ae5455e8a2439..b084633aef61c 100644 --- a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-types.xml +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/inverter-types.xml @@ -6,8 +6,8 @@ - - + + @@ -15,21 +15,101 @@ Inverter - - + + + + + + - - - - - + + + + + uniqueAddress - + + + + + + + + + + + + Split phase (Japanese grid and 240V grid in North America) inverter supporting SunSpec mapping over tcp + modbus connection + Inverter + + + + + + + + + + + + + + + + + + + + + + uniqueAddress + + + + + + + + + + + + + Three phase inverter supporting SunSpec mapping over tcp modbus connection + Inverter + + + + + + + + + + + + + + + + + + + + + + + + + uniqueAddress + + diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-channel-groups.xml b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-channel-groups.xml new file mode 100644 index 0000000000000..2c2e3f9b3d87f --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-channel-groups.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-channel-types.xml b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-channel-types.xml new file mode 100644 index 0000000000000..2187f9bc8c86e --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-channel-types.xml @@ -0,0 +1,126 @@ + + + + + Number:ElectricPotential + + + + + Number:ElectricPotential + + + + + Number:Power + + + + + Number:Power + + + + + Number:Power + + + + + Number:Power + + + + + Number:Dimensionless + + + + + + Number:Energy + + + + + Number:Energy + + + + + Number:Energy + + + + + Number:Energy + + + + + + Number:Energy + + + + + Number:Energy + + + + + Number:Energy + + + + + Number:Energy + + + + + + Number:Energy + + + + + Number:Energy + + + + + Number:Energy + + + + + Number:Energy + + + + + + Number:Energy + + + + + Number:Energy + + + + + Number:Energy + + + + + Number:Energy + + + + diff --git a/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-types.xml b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-types.xml new file mode 100644 index 0000000000000..b695ae26c2d5f --- /dev/null +++ b/bundles/org.openhab.binding.modbus.sunspec/src/main/resources/ESH-INF/thing/meter-types.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + Single phase (AN or AB) meter supporting SunSpec mapping over modbus connection + Meter + + + + + + + + + + + + + + + + + uniqueAddress + + + + + + + + + + + + Split phase (ABN) meter supporting SunSpec mapping over modbus connection + Meter + + + + + + + + + + + + + + + + + + + + uniqueAddress + + + + + + + + + + + + Wye-connected three phase (ABCN) meter supporting SunSpec mapping over modbus connection + Meter + + + + + + + + + + + + + + + + + + + + + + + uniqueAddress + + + + + + + + + + + + Delta-connected three phase (ABC) meter supporting SunSpec mapping over modbus connection + Meter + + + + + + + + + + + + + + + + + + + + + + + uniqueAddress + + + + diff --git a/bundles/org.openhab.binding.modbus/README.md b/bundles/org.openhab.binding.modbus/README.md index 5ef549152d0c1..9a193e93b44d8 100644 --- a/bundles/org.openhab.binding.modbus/README.md +++ b/bundles/org.openhab.binding.modbus/README.md @@ -1,6 +1,7 @@ # Modbus Binding -This is the binding to access Modbus TCP and serial slaves. RTU, ASCII and BIN variants of Serial Modbus are supported. +This is the binding to access Modbus TCP and serial slaves. +RTU, ASCII and BIN variants of Serial Modbus are supported. Modbus TCP slaves are usually also called as Modbus TCP servers. The binding can act as @@ -11,6 +12,11 @@ The binding can act as The Modbus binding polls the slave data with an configurable poll period. openHAB commands are translated to write requests. +The binding has the following extensions: + + + + ## Main Features The binding polls (or *reads*) Modbus data using function codes (FC) FC01 (Read coils), FC02 (Read discrete inputs), FC03 (Read multiple holding registers) or FC04 (Read input registers). diff --git a/bundles/org.openhab.binding.modbus/pom.xml b/bundles/org.openhab.binding.modbus/pom.xml index 9f60a14f382a8..14321f10feaaa 100644 --- a/bundles/org.openhab.binding.modbus/pom.xml +++ b/bundles/org.openhab.binding.modbus/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.modbus diff --git a/bundles/org.openhab.binding.modbus/src/main/feature/feature.xml b/bundles/org.openhab.binding.modbus/src/main/feature/feature.xml index 5ffca23712e88..de4b6572a86c1 100644 --- a/bundles/org.openhab.binding.modbus/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.modbus/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml + file:${basedirRoot}/bundles/org.openhab.io.transport.modbus/target/feature/feature.xml - - openhab-runtime-base - openhab-transport-modbus - mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version} - + + openhab-runtime-base + openhab-transport-modbus + mvn:org.openhab.addons.bundles/org.openhab.binding.modbus/${project.version} + diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/ModbusBindingConstants.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/ModbusBindingConstants.java index 8a83f0c8eca23..1055b10ceea0d 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/ModbusBindingConstants.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/ModbusBindingConstants.java @@ -25,5 +25,4 @@ public class ModbusBindingConstants { public static final String BINDING_ID = "modbus"; - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/handler/EndpointNotInitializedException.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/handler/EndpointNotInitializedException.java index bf05979a5ef5e..ff15631a2bab5 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/handler/EndpointNotInitializedException.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/handler/EndpointNotInitializedException.java @@ -24,5 +24,4 @@ public class EndpointNotInitializedException extends Exception { private static final long serialVersionUID = -6721646244844348903L; - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/ModbusConfigurationException.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/ModbusConfigurationException.java index eecbfe067cf98..8ee3860c7c96f 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/ModbusConfigurationException.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/ModbusConfigurationException.java @@ -28,5 +28,4 @@ public ModbusConfigurationException(String errmsg) { } private static final long serialVersionUID = -466597103876477780L; - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/ModbusHandlerFactory.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/ModbusHandlerFactory.java index 23f4f5b2494d5..4bb0dbe07e088 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/ModbusHandlerFactory.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/ModbusHandlerFactory.java @@ -94,5 +94,4 @@ public void setModbusManager(ModbusManager manager) { public void unsetModbusManager(ModbusManager manager) { this.manager = null; } - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/config/ModbusPollerConfiguration.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/config/ModbusPollerConfiguration.java index 0c0e74d1174d3..efe2ef444e72d 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/config/ModbusPollerConfiguration.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/config/ModbusPollerConfiguration.java @@ -116,5 +116,4 @@ public long getCacheMillis() { public void setCacheMillis(long cacheMillis) { this.cacheMillis = cacheMillis; } - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/config/ModbusTcpConfiguration.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/config/ModbusTcpConfiguration.java index adcdff3b7754e..1c1f0841f79fc 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/config/ModbusTcpConfiguration.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/config/ModbusTcpConfiguration.java @@ -105,5 +105,4 @@ public boolean isDiscoveryEnabled() { public void setDiscoveryEnabled(boolean enableDiscovery) { this.enableDiscovery = enableDiscovery; } - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusDataThingHandler.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusDataThingHandler.java index 8b9083adbfcfa..f70444ebce4f1 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusDataThingHandler.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusDataThingHandler.java @@ -519,8 +519,8 @@ private void validateAndParseWriteParameters() throws ModbusConfigurationExcepti boolean writeTransformationMissing = StringUtils.isBlank(config.getWriteTransform()); writeTransformation = new Transformation(config.getWriteTransform()); boolean writingCoil = WRITE_TYPE_COIL.equals(config.getWriteType()); - writeParametersHavingTransformationOnly = (writeTypeMissing && writeStartMissing - && writeValueTypeMissing && !writeTransformationMissing); + writeParametersHavingTransformationOnly = (writeTypeMissing && writeStartMissing && writeValueTypeMissing + && !writeTransformationMissing); boolean allMissingOrAllPresentOrOnlyNonDefaultTransform = // // read-only thing, no write specified (writeTypeMissing && writeStartMissing && writeValueTypeMissing) @@ -936,5 +936,4 @@ protected void updateStatus(ThingStatusInfo statusInfo) { } } } - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusPollerThingHandler.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusPollerThingHandler.java index 3dbe887e83c1a..1f765157be84a 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusPollerThingHandler.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusPollerThingHandler.java @@ -48,5 +48,4 @@ public interface ModbusPollerThingHandler { * Refresh data */ public void refresh(); - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusPollerThingHandlerImpl.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusPollerThingHandlerImpl.java index 2de9fcf19df0d..0bb1b09e4cb85 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusPollerThingHandlerImpl.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusPollerThingHandlerImpl.java @@ -453,5 +453,4 @@ public void refresh() { managerRef.get().submitOneTimePoll(pollTask); } } - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusSerialThingHandler.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusSerialThingHandler.java index 57b66b582ceac..6eb3a4cc949c9 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusSerialThingHandler.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusSerialThingHandler.java @@ -112,5 +112,4 @@ public ThingUID getUID() { public Collection> getServices() { return Collections.singleton(ModbusEndpointDiscoveryService.class); } - } diff --git a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusTcpThingHandler.java b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusTcpThingHandler.java index 258ab7198d467..e7432e3fe8590 100644 --- a/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusTcpThingHandler.java +++ b/bundles/org.openhab.binding.modbus/src/main/java/org/openhab/binding/modbus/internal/handler/ModbusTcpThingHandler.java @@ -101,5 +101,4 @@ public boolean isDiscoveryEnabled() { public Collection> getServices() { return Collections.singleton(ModbusEndpointDiscoveryService.class); } - } diff --git a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/binding/binding.xml index d065f34d9fa2b..fa7638c8a9b9e 100644 --- a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Modbus Binding Binding for Modbus diff --git a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-poller.xml b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-poller.xml index 81713385dff9a..f6298b3c8f31e 100644 --- a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-poller.xml +++ b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-poller.xml @@ -1,11 +1,12 @@ - - - + + @@ -18,7 +19,7 @@ -
Input as zero-based index number, e.g. in place of 400001 (first holding register), use the address 0.]]>
0 @@ -45,7 +46,7 @@ 50 -
Use zero to disable the caching.]]>
true diff --git a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-serial.xml b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-serial.xml index 7ff20bff89b4a..021009985c30d 100644 --- a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-serial.xml +++ b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-serial.xml @@ -1,5 +1,6 @@ - @@ -9,8 +10,8 @@ serial-port + false Serial port to use, for example /dev/ttyS0 or COM1 - /dev/ttyS0 @@ -81,14 +82,15 @@ - When enabled we try to find a device specific handler. Turn this on if you're using one of the supported devices. + When enabled we try to find a device specific handler. Turn this on if you're using one of the + supported devices. false -
This controls whether we should try to read back whatever we send on the line, before reading the response. +
This controls whether we should try to read back whatever we send on the line, before reading the response. ]]>
false true diff --git a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-tcp.xml b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-tcp.xml index c9c48809060fb..b1e48f945f608 100644 --- a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-tcp.xml +++ b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/bridge-tcp.xml @@ -1,5 +1,6 @@ - @@ -23,10 +24,11 @@ Slave id. Also known as station address or unit identifier. 1
- + - When enabled we try to find a device specific handler. Turn this on if you're using one of the supported devices. + When enabled we try to find a device specific handler. Turn this on if you're using one of the + supported devices. false diff --git a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/thing-data.xml b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/thing-data.xml index 934f7b65c477c..3e592882e72a1 100644 --- a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/thing-data.xml +++ b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/thing-data.xml @@ -1,27 +1,28 @@ - - - - + + + Data thing extracts values from binary data received from Modbus slave. Similarly, it it responsible of tranlating openHAB commands to Modbus write requests - - - - - - - - - - - + + + + + + + + + + + @@ -32,7 +33,7 @@
Input as zero-based index number, e.g. in place of 400001 (first holding register), use the address 0. Must be between (poller start) and (poller start + poller length - 1) (inclusive).

With registers and value type less than 16 bits, you must use X.Y format where Y specifies the sub-element to read from the 16 bit register: -
    +
    • For example, 3.1 would mean pick second bit from register index 3 with bit value type.
    • With int8 valuetype, it would pick the high byte of register index 3.
    @@ -44,21 +45,21 @@
    Use "default" to communicate that no transformation is done and value should be passed as is.
    Use SERVICENAME(ARG) to use transformation service. -
    Any other value than the above types will be interpreted as static text, in which case the actual content of the polled +
    Any other value than the above types will be interpreted as static text, in which case the actual content of the polled value is ignored.]]>
    default
    With registers all value types are applicable.]]>
    - + @@ -85,7 +86,7 @@ -
    +
    Coil uses function code (FC) FC05 or FC15. Holding register uses FC06 or FC16. See writeMultipleEvenWithSingleRegisterOrCoil parameter.]]>
    @@ -97,7 +98,7 @@
    Use "default" to communicate that no transformation is done and value should be passed as is.
    Use SERVICENAME(ARG) to use transformation service. -
    Any other value than the above types will be interpreted as static text, in which case the actual content of the command +
    Any other value than the above types will be interpreted as static text, in which case the actual content of the command value is ignored.]]>
    default
    @@ -107,7 +108,8 @@ - + @@ -119,7 +121,7 @@ false -
    If false, FC6/FC5 are used with single register and single coil, respectively.]]>
    diff --git a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/thing-types.xml index df02bc8071694..c44d0b4db4675 100644 --- a/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.modbus/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.mqtt.generic/pom.xml b/bundles/org.openhab.binding.mqtt.generic/pom.xml index 7200a361ff39e..6196c943fe999 100644 --- a/bundles/org.openhab.binding.mqtt.generic/pom.xml +++ b/bundles/org.openhab.binding.mqtt.generic/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.mqtt.generic diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AvailabilityTracker.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AvailabilityTracker.java index 7ade7c6ba2302..d59ba2c811e3b 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AvailabilityTracker.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/AvailabilityTracker.java @@ -43,5 +43,4 @@ public interface AvailabilityTracker { * This is used to time out the availability of the device after some time without receiving a message. */ public void resetMessageReceived(); - } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelState.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelState.java index 3a6918b574e38..2774be78f0b48 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelState.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/ChannelState.java @@ -411,5 +411,4 @@ public void setChannelStateUpdateListener(ChannelStateUpdateListener channelStat public void setConnection(MqttBrokerConnection connection) { this.connection = connection; } - } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/internal/MqttBindingConstants.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/internal/MqttBindingConstants.java index c54c2f6c16065..f7eb01bf83b30 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/internal/MqttBindingConstants.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/internal/MqttBindingConstants.java @@ -41,4 +41,5 @@ public class MqttBindingConstants { public static final String LOCATION = "location"; public static final String DATETIME = "datetime"; public static final String ROLLERSHUTTER = "rollershutter"; + public static final String TRIGGER = "trigger"; } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/internal/MqttThingHandlerFactory.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/internal/MqttThingHandlerFactory.java index 3e02d45e50b79..b0bb152aa7b2c 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/internal/MqttThingHandlerFactory.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/internal/MqttThingHandlerFactory.java @@ -87,5 +87,4 @@ protected void unsetStateDescriptionProvider(MqttChannelStateDescriptionProvider public @Nullable TransformationService getTransformationService(String type) { return TransformationHelper.getTransformationService(bundleContext, type); } - } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/AbstractMqttAttributeClass.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/AbstractMqttAttributeClass.java index b1c9de0f4bb3d..dde6157fccec5 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/AbstractMqttAttributeClass.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/mapping/AbstractMqttAttributeClass.java @@ -316,5 +316,4 @@ public void fieldChanged(Field field, Object value) { * Implement this method in your field class and return "this". */ public abstract Object getFieldsOf(); - } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/DelayedBatchProcessing.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/DelayedBatchProcessing.java index e85fec7180d06..d358d329402e4 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/DelayedBatchProcessing.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/DelayedBatchProcessing.java @@ -18,6 +18,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -37,7 +38,7 @@ public class DelayedBatchProcessing implements Consumer { private final Consumer> consumer; private final List queue = Collections.synchronizedList(new ArrayList<>()); private final ScheduledExecutorService executor; - protected @Nullable ScheduledFuture future; + protected final AtomicReference<@Nullable ScheduledFuture> futureRef = new AtomicReference<>(); /** * Creates a {@link DelayedBatchProcessing}. @@ -56,18 +57,15 @@ public DelayedBatchProcessing(int delay, Consumer> consumer, ScheduledEx } /** - * Add new object to the batch process list. If the list was empty, the delay timer - * is armed and all successive objects are accumulated from here on. + * Add new object to the batch process list. Every time a new object is received, + * the delay timer is rescheduled. * * @param t An object */ @Override public void accept(T t) { queue.add(t); - final ScheduledFuture scheduledFuture = this.future; - if (scheduledFuture == null || scheduledFuture.isDone()) { - this.future = executor.schedule(this::run, delay, TimeUnit.MILLISECONDS); - } + cancel(futureRef.getAndSet(executor.schedule(this::run, delay, TimeUnit.MILLISECONDS))); } /** @@ -76,10 +74,7 @@ public void accept(T t) { * @return A list of accumulated objects */ public List join() { - ScheduledFuture scheduledFuture = this.future; - if (scheduledFuture != null && !scheduledFuture.isDone()) { - scheduledFuture.cancel(false); - } + cancel(futureRef.getAndSet(null)); List lqueue = new ArrayList<>(); synchronized (queue) { lqueue.addAll(queue); @@ -92,7 +87,7 @@ public List join() { * Return true if there is a delayed processing going on. */ public boolean isArmed() { - ScheduledFuture scheduledFuture = this.future; + ScheduledFuture scheduledFuture = this.futureRef.get(); return scheduledFuture != null && !scheduledFuture.isDone(); } @@ -100,10 +95,7 @@ public boolean isArmed() { * Deliver queued items now to the target consumer. */ public void forceProcessNow() { - ScheduledFuture scheduledFuture = this.future; - if (scheduledFuture != null && !scheduledFuture.isDone()) { - scheduledFuture.cancel(false); - } + cancel(futureRef.getAndSet(null)); run(); } @@ -118,4 +110,10 @@ private void run() { consumer.accept(lqueue); } } + + private static void cancel(@Nullable ScheduledFuture future) { + if (future != null) { + future.cancel(false); + } + } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/JsonReaderDelegate.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/JsonReaderDelegate.java index aa6376e0d646f..5d4362c01ad16 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/JsonReaderDelegate.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/JsonReaderDelegate.java @@ -147,5 +147,4 @@ public void skipValue() throws IOException { public String toString() { return delegate.toString(); } - } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/WaitForTopicValue.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/WaitForTopicValue.java index c258617cc23df..b90d9c837e31b 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/WaitForTopicValue.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/tools/WaitForTopicValue.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.mqtt.generic.tools; +import java.nio.charset.StandardCharsets; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.ScheduledExecutorService; @@ -24,40 +25,37 @@ import org.eclipse.smarthome.io.transport.mqtt.MqttMessageSubscriber; /** - * Waits for a topic value to appear on a MQTT topic. One-time useable only per instance. + * Waits for a topic value to appear on a MQTT topic. One-time usable only per instance. * * @author David Graeff - Initial contribution */ @NonNullByDefault public class WaitForTopicValue { - private CompletableFuture future = new CompletableFuture<>(); - private final CompletableFuture subscripeFuture; + private final CompletableFuture composeFuture; /** * Creates an a instance. * * @param connection A broker connection. * @param topic The topic - * @throws InterruptedException - * @throws ExecutionException */ - public WaitForTopicValue(MqttBrokerConnection connection, String topic) - throws InterruptedException, ExecutionException { + public WaitForTopicValue(MqttBrokerConnection connection, String topic) { + final CompletableFuture future = new CompletableFuture<>(); final MqttMessageSubscriber mqttMessageSubscriber = (t, payload) -> { - future.complete(new String(payload)); + future.complete(new String(payload, StandardCharsets.UTF_8)); }; - future = future.whenComplete((r, e) -> { + future.whenComplete((r, e) -> { connection.unsubscribe(topic, mqttMessageSubscriber); }); - subscripeFuture = connection.subscribe(topic, mqttMessageSubscriber); + composeFuture = connection.subscribe(topic, mqttMessageSubscriber).thenCompose(b -> future); } /** * Free any resources */ public void stop() { - future.completeExceptionally(new Exception("Stopped")); + composeFuture.completeExceptionally(new Exception("Stopped")); } /** @@ -68,15 +66,15 @@ public void stop() { */ public @Nullable String waitForTopicValue(int timeoutInMS) { try { - return subscripeFuture.thenCompose(b -> future).get(timeoutInMS, TimeUnit.MILLISECONDS); + return composeFuture.get(timeoutInMS, TimeUnit.MILLISECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { return null; } } private void timeout() { - if (!future.isDone()) { - future.completeExceptionally(new TimeoutException()); + if (!composeFuture.isDone()) { + composeFuture.completeExceptionally(new TimeoutException()); } } @@ -89,6 +87,6 @@ private void timeout() { */ public CompletableFuture waitForTopicValueAsync(ScheduledExecutorService scheduler, int timeoutInMS) { scheduler.schedule(this::timeout, timeoutInMS, TimeUnit.MILLISECONDS); - return subscripeFuture.thenCompose(b -> future); + return composeFuture; } } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ValueFactory.java b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ValueFactory.java index 8eff012f6c3a7..7500aecf58b7f 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ValueFactory.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/java/org/openhab/binding/mqtt/generic/values/ValueFactory.java @@ -67,10 +67,13 @@ public static Value createValueState(ChannelConfig config, String channelTypeID) case MqttBindingConstants.ROLLERSHUTTER: value = new RollershutterValue(config.on, config.off, config.stop); break; + case MqttBindingConstants.TRIGGER: + config.trigger = true; + value = new TextValue(); + break; default: throw new IllegalArgumentException("ChannelTypeUID not recognised: " + channelTypeID); } return value; } - } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/config/color-channel-config.xml b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/config/color-channel-config.xml index c17c8f137eb01..d10ccbcec07ff 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/config/color-channel-config.xml +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/config/color-channel-config.xml @@ -96,7 +96,8 @@ If you connect this channel to a Switch item and turn it on, - color and saturation are preserved from the last state, but + color and saturation are preserved from the + last state, but the brightness will be set to this configured initial brightness percentage. 10 true diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/config/trigger-channel-config.xml b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/config/trigger-channel-config.xml new file mode 100644 index 0000000000000..e0c83296549ad --- /dev/null +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/config/trigger-channel-config.xml @@ -0,0 +1,30 @@ + + + + + + + These configuration parameters allow you to alter before a received value is used in the trigger. + true + + + + + An MQTT topic that this thing will subscribe to, to receive the trigger + + + + + true + + + diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/thing/channels.xml index ebf6062fe98ef..d8dca540d9586 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/thing/channels.xml @@ -7,29 +7,29 @@ String - + DateTime Current date and/or time - + Image An image to display. Send a binary bmp, jpg, png or any other supported format to this channel. - - + + Location GPS coordinates as Latitude,Longitude,Altitude - + @@ -76,4 +76,11 @@ + + Trigger + + + + + diff --git a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/thing/generic-thing.xml b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/thing/generic-thing.xml index 4b579b9632c66..6d7a38c76e630 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/thing/generic-thing.xml +++ b/bundles/org.openhab.binding.mqtt.generic/src/main/resources/ESH-INF/thing/generic-thing.xml @@ -5,10 +5,10 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> + extensible="string,number,dimmer,switch,contact,colorRGB,colorHSB,datetime,image,location,rollershutter,trigger"> - - + + You need a configured Broker first. Dynamically add channels of various types to this Thing. Link diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/ThingChannelConstants.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/ThingChannelConstants.java index 81e3e07df9359..648fe40183631 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/ThingChannelConstants.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/internal/handler/ThingChannelConstants.java @@ -125,5 +125,4 @@ private static Configuration onoffConfiguration() { data.put("inverse", true); return new Configuration(data); } - } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopicTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopicTests.java index 39103f439372a..1a7aa582659a5 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopicTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/mapping/SubscribeFieldToMQTTtopicTests.java @@ -152,5 +152,4 @@ public void MessageReceive() future.get(50, TimeUnit.MILLISECONDS); assertThat(attributes.Int, is(10)); } - } diff --git a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java index 74259c4c31260..e7ea19314d5d4 100644 --- a/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java +++ b/bundles/org.openhab.binding.mqtt.generic/src/test/java/org/openhab/binding/mqtt/generic/values/ValueTests.java @@ -230,7 +230,6 @@ public void percentMQTTValue() { v.update(new DecimalType(i)); assertThat(v.getMQTTpublishValue(null), is("" + i)); } - } @Test diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/pom.xml b/bundles/org.openhab.binding.mqtt.homeassistant/pom.xml index 03105c09ded6b..077af82e9ae13 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/pom.xml +++ b/bundles/org.openhab.binding.mqtt.homeassistant/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.mqtt.homeassistant diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/feature/feature.xml b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/feature/feature.xml index d7ad564331dcf..fd50c3169fcff 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/feature/feature.xml @@ -1,13 +1,13 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mqtt - mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.generic/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.homeassistant/${project.version} - + + openhab-runtime-base + openhab-transport-mqtt + mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.generic/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.homeassistant/${project.version} + diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttThingHandlerFactory.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttThingHandlerFactory.java index d2d09a7e577e7..2fd9bdcf32d36 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttThingHandlerFactory.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/generic/internal/MqttThingHandlerFactory.java @@ -93,5 +93,4 @@ protected void unsetChannelProvider(MqttChannelTypeProvider provider) { public @Nullable TransformationService getTransformationService(String type) { return TransformationHelper.getTransformationService(bundleContext, type); } - } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentSensor.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentSensor.java index d3429ebc2d4ca..56b89a739dff4 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentSensor.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ComponentSensor.java @@ -65,5 +65,4 @@ public ComponentSensor(CFactory.ComponentConfiguration componentConfiguration) { .stateTopic(channelConfiguration.state_topic, channelConfiguration.value_template)// .build(); } - } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ConnectionDeserializer.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ConnectionDeserializer.java index 491a072080df0..8d1681010b1f1 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ConnectionDeserializer.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ConnectionDeserializer.java @@ -12,10 +12,10 @@ */ package org.openhab.binding.mqtt.homeassistant.internal; -import com.google.gson.*; - import java.lang.reflect.Type; +import com.google.gson.*; + /** * The {@link ConnectionDeserializer} will de-serialize a connection-list * diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ListOrStringDeserializer.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ListOrStringDeserializer.java index df5aadfa3f410..115ffe1f52ccb 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ListOrStringDeserializer.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/ListOrStringDeserializer.java @@ -88,6 +88,5 @@ public void write(@Nullable JsonWriter out, @Nullable List value) throws in.endArray(); return result; - } } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java index 9af7d85b894f8..cfbd54f85003a 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/java/org/openhab/binding/mqtt/homeassistant/internal/discovery/HomeAssistantDiscovery.java @@ -222,5 +222,4 @@ public void topicVanished(ThingUID connectionBridge, MqttBrokerConnection connec } } } - } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/ESH-INF/thing/homeassistant-thing.xml b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/ESH-INF/thing/homeassistant-thing.xml index fa18f92376844..57331f1783de9 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/ESH-INF/thing/homeassistant-thing.xml +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/main/resources/ESH-INF/thing/homeassistant-thing.xml @@ -6,11 +6,12 @@ - - + + - You need a configured Broker first. This Thing represents a device, that follows the "HomeAssistant MQTT Component" specification. + You need a configured Broker first. This Thing represents a device, that follows the "HomeAssistant MQTT + Component" specification. diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/HaIDTests.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/HaIDTests.java index 161d0965de362..643b590c5cd2e 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/HaIDTests.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/HaIDTests.java @@ -72,5 +72,4 @@ public void testWithNode() { Collection restoreList = HaID.fromConfig(haConfig); assertThat(restoreList, hasItem(new HaID("homeassistant/switch/node/name/config"))); } - } diff --git a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/ThingChannelConstants.java b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/ThingChannelConstants.java index d2261423d567c..0b0d93fdc51ee 100644 --- a/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/ThingChannelConstants.java +++ b/bundles/org.openhab.binding.mqtt.homeassistant/src/test/java/org/openhab/binding/mqtt/homeassistant/internal/handler/ThingChannelConstants.java @@ -57,5 +57,4 @@ static Configuration textConfigurationWithJson() { data.put("transformationPattern", "JSONPATH:" + jsonPathPattern); return new Configuration(data); } - } diff --git a/bundles/org.openhab.binding.mqtt.homie/pom.xml b/bundles/org.openhab.binding.mqtt.homie/pom.xml index df505f2eea19c..8037f1e6cdedd 100644 --- a/bundles/org.openhab.binding.mqtt.homie/pom.xml +++ b/bundles/org.openhab.binding.mqtt.homie/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.mqtt.homie diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/feature/feature.xml b/bundles/org.openhab.binding.mqtt.homie/src/main/feature/feature.xml index f0fccb1c0a4a3..6f59a0c154365 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/feature/feature.xml @@ -1,13 +1,13 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mqtt - mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.generic/${project.version} - mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.homie/${project.version} - + + openhab-runtime-base + openhab-transport-mqtt + mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.generic/${project.version} + mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt.homie/${project.version} + diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/generic/internal/MqttThingHandlerFactory.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/generic/internal/MqttThingHandlerFactory.java index 2004b179755d9..45df573aed3fd 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/generic/internal/MqttThingHandlerFactory.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/generic/internal/MqttThingHandlerFactory.java @@ -28,7 +28,6 @@ import org.openhab.binding.mqtt.generic.MqttChannelStateDescriptionProvider; import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider; import org.openhab.binding.mqtt.generic.TransformationServiceProvider; -import org.openhab.binding.mqtt.homie.generic.internal.MqttBindingConstants; import org.openhab.binding.mqtt.homie.internal.handler.HomieThingHandler; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; @@ -90,7 +89,7 @@ protected void unsetChannelProvider(MqttChannelTypeProvider provider) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(MqttBindingConstants.HOMIE300_MQTT_THING)) { - return new HomieThingHandler(thing, typeProvider, 15000, 2000); + return new HomieThingHandler(thing, typeProvider, 1000, 500); } return null; } @@ -99,5 +98,4 @@ protected void unsetChannelProvider(MqttChannelTypeProvider provider) { public @Nullable TransformationService getTransformationService(String type) { return TransformationHelper.getTransformationService(bundleContext, type); } - } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/discovery/Homie300Discovery.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/discovery/Homie300Discovery.java index ca3e57e7a6c5d..936025a44ce74 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/discovery/Homie300Discovery.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/discovery/Homie300Discovery.java @@ -16,7 +16,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ExecutionException; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -94,15 +93,11 @@ public void receivedMessage(ThingUID connectionBridge, MqttBrokerConnection conn } // Retrieve name and update found discovery - try { - WaitForTopicValue w = new WaitForTopicValue(connection, topic.replace("$homie", "$name")); - w.waitForTopicValueAsync(scheduler, 700).thenAccept(name -> { - publishDevice(connectionBridge, connection, deviceID, topic, name); - }); - } catch (InterruptedException | ExecutionException ignored) { - // The name is nice to have, but not required, use deviceId as fallback - publishDevice(connectionBridge, connection, deviceID, topic, deviceID); - } + WaitForTopicValue w = new WaitForTopicValue(connection, topic.replace("$homie", "$name")); + w.waitForTopicValueAsync(scheduler, 700).whenComplete((name, ex) -> { + String deviceName = ex == null ? name : deviceID; + publishDevice(connectionBridge, connection, deviceID, topic, deviceName); + }); } void publishDevice(ThingUID connectionBridge, MqttBrokerConnection connection, String deviceID, String topic, diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Property.java b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Property.java index c9abb46e83a2f..57bd027d12fd0 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Property.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/java/org/openhab/binding/mqtt/homie/internal/homie300/Property.java @@ -194,7 +194,7 @@ public void createChannelFromAttribute() { if (step != null && !isDecimal && step.intValue() <= 0) { step = new BigDecimal(1); } - if (attributes.unit != null && attributes.unit.contains("%")) { + if (attributes.unit.contains("%") && attributes.settable) { value = new PercentageValue(min, max, step, null, null); } else { value = new NumberValue(min, max, step, attributes.unit); diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/resources/ESH-INF/config/homie-channel-config.xml b/bundles/org.openhab.binding.mqtt.homie/src/main/resources/ESH-INF/config/homie-channel-config.xml index 47d62640cb9f9..741a1369644e3 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/resources/ESH-INF/config/homie-channel-config.xml +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/resources/ESH-INF/config/homie-channel-config.xml @@ -22,7 +22,8 @@ - If set to false, the resulting channel will be a trigger channel (stateless), useful for non-permanent events. This flag corresponds to the retained option for MQTT publish. + If set to false, the resulting channel will be a trigger channel (stateless), useful for non-permanent + events. This flag corresponds to the retained option for MQTT publish. true diff --git a/bundles/org.openhab.binding.mqtt.homie/src/main/resources/ESH-INF/thing/homie-thing.xml b/bundles/org.openhab.binding.mqtt.homie/src/main/resources/ESH-INF/thing/homie-thing.xml index cc3ae1ea45f49..b3d7fe26e5d40 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/main/resources/ESH-INF/thing/homie-thing.xml +++ b/bundles/org.openhab.binding.mqtt.homie/src/main/resources/ESH-INF/thing/homie-thing.xml @@ -6,13 +6,14 @@ - - + + - You need a configured Broker first. This thing represents a device, that follows the "MQTT Homie Convention" (Version 3.x). + You need a configured Broker first. This thing represents a device, that follows the "MQTT Homie + Convention" (Version 3.x). - + diff --git a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/generic/internal/mapping/HomieChildMapTests.java b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/generic/internal/mapping/HomieChildMapTests.java index fc218b0df3980..1443661c0a369 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/generic/internal/mapping/HomieChildMapTests.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/generic/internal/mapping/HomieChildMapTests.java @@ -25,8 +25,8 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mock; -import org.openhab.binding.mqtt.homie.internal.handler.ThingChannelConstants; import org.openhab.binding.mqtt.generic.tools.ChildMap; +import org.openhab.binding.mqtt.homie.internal.handler.ThingChannelConstants; import org.openhab.binding.mqtt.homie.internal.homie300.DeviceCallback; import org.openhab.binding.mqtt.homie.internal.homie300.Node; import org.openhab.binding.mqtt.homie.internal.homie300.NodeAttributes; @@ -88,5 +88,4 @@ public void testArrayToSubtopicCreateAndRemove() { subject.apply(new String[] { "abc" }, addedAction, this::createNode, this::removedNode); verify(callback).nodeRemoved(eq(soonToBeRemoved)); } - } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/ThingChannelConstants.java b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/ThingChannelConstants.java index 202876593107c..493d8a356118e 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/ThingChannelConstants.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/handler/ThingChannelConstants.java @@ -86,5 +86,4 @@ private static Configuration onoffConfiguration() { data.put("inverse", true); return new Configuration(data); } - } diff --git a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/homie300/PropertyHelper.java b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/homie300/PropertyHelper.java index 6bb5070172163..5a97be3ed4ec1 100644 --- a/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/homie300/PropertyHelper.java +++ b/bundles/org.openhab.binding.mqtt.homie/src/test/java/org/openhab/binding/mqtt/homie/internal/homie300/PropertyHelper.java @@ -15,10 +15,9 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.mqtt.generic.ChannelState; -import org.openhab.binding.mqtt.homie.internal.homie300.Property; /** - * Helper to access {@link Property} internals. + * Helper to access {@link org.openhab.binding.mqtt.homie.internal.homie300.Property} internals. * * @author David Graeff - Initial contribution */ diff --git a/bundles/org.openhab.binding.mqtt/pom.xml b/bundles/org.openhab.binding.mqtt/pom.xml index 663a9c9b38b2d..cd6336b2ca2d1 100644 --- a/bundles/org.openhab.binding.mqtt/pom.xml +++ b/bundles/org.openhab.binding.mqtt/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.mqtt diff --git a/bundles/org.openhab.binding.mqtt/src/main/feature/feature.xml b/bundles/org.openhab.binding.mqtt/src/main/feature/feature.xml index 24b80f2b292fb..8ba33b77789bf 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.mqtt/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mqtt - mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt/${project.version} - + + openhab-runtime-base + openhab-transport-mqtt + mvn:org.openhab.addons.bundles/org.openhab.binding.mqtt/${project.version} + diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/action/MQTTActions.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/action/MQTTActions.java index a0d6a7a6d175a..28e34db36299b 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/action/MQTTActions.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/action/MQTTActions.java @@ -91,7 +91,8 @@ public static void publishMQTT(@Nullable ThingActions actions, @Nullable String publishMQTT(actions, topic, value, null); } - public static void publishMQTT(@Nullable ThingActions actions, @Nullable String topic, @Nullable String value, @Nullable Boolean retain) { + public static void publishMQTT(@Nullable ThingActions actions, @Nullable String topic, @Nullable String value, + @Nullable Boolean retain) { if (actions instanceof MQTTActions) { ((MQTTActions) actions).publishMQTT(topic, value, retain); } else { diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/discovery/MQTTTopicDiscoveryService.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/discovery/MQTTTopicDiscoveryService.java index b2ed4e6a6cd05..a6843f46721c7 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/discovery/MQTTTopicDiscoveryService.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/discovery/MQTTTopicDiscoveryService.java @@ -38,4 +38,12 @@ public interface MQTTTopicDiscoveryService { * @param listener A listener that has subscribed before. */ void unsubscribe(MQTTTopicDiscoveryParticipant listener); + + /** + * Publish a message to all connected brokers + * + * @param topic The topic to publish on + * @param payload The message to publish + */ + void publish(String topic, byte[] payload); } diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandler.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandler.java index 42b1bd739f1cb..5b8fe39d3c319 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandler.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandler.java @@ -12,6 +12,13 @@ */ package org.openhab.binding.mqtt.handler; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeoutException; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.*; @@ -28,13 +35,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeoutException; - /** * This base implementation handles connection changes of the {@link MqttBrokerConnection} * and puts the Thing on or offline. It also handles adding/removing notifications of the @@ -217,8 +217,8 @@ public final void registerDiscoveryListener(MQTTTopicDiscoveryParticipant listen * @param topic the topic (as specified during registration) */ public final void unregisterDiscoveryListener(MQTTTopicDiscoveryParticipant listener, String topic) { - Map topicListeners = discoveryTopics - .compute(topic, (k, v) -> { + Map topicListeners = discoveryTopics.compute(topic, + (k, v) -> { if (v == null) { logger.warn( "Tried to unsubscribe {} from discovery topic {} on broker {} but topic not registered at all. Check discovery logic!", diff --git a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttBrokerHandlerFactory.java b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttBrokerHandlerFactory.java index 1cfab3857e164..1ac4ab1df26bd 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttBrokerHandlerFactory.java +++ b/bundles/org.openhab.binding.mqtt/src/main/java/org/openhab/binding/mqtt/internal/MqttBrokerHandlerFactory.java @@ -12,6 +12,10 @@ */ package org.openhab.binding.mqtt.internal; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Bridge; @@ -33,10 +37,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - /** * The {@link MqttBrokerHandlerFactory} is responsible for creating things and thing * handlers. It keeps reference to all handlers and implements the {@link MQTTTopicDiscoveryService} service @@ -108,8 +108,8 @@ protected void createdHandler(AbstractBrokerHandler handler) { */ @Override public void subscribe(MQTTTopicDiscoveryParticipant listener, String topic) { - List listenerList = discoveryTopics - .computeIfAbsent(topic, t -> new ArrayList<>()); + List listenerList = discoveryTopics.computeIfAbsent(topic, + t -> new ArrayList<>()); listenerList.add(listener); handlers.forEach(broker -> broker.registerDiscoveryListener(listener, topic)); } @@ -125,4 +125,13 @@ public void unsubscribe(MQTTTopicDiscoveryParticipant listener) { handlers.forEach(broker -> broker.unregisterDiscoveryListener(listener, topic)); }); } + + @Override + public void publish(String topic, byte[] payload) { + handlers.forEach(handler -> { + handler.getConnectionAsync().thenAccept(connection -> { + connection.publish(topic, payload); + }); + }); + } } diff --git a/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/binding/binding.xml index 764a2adc1bd65..47fe6772032d5 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - MQTT Binding diff --git a/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/thing/thing-types.xml index d4ec5e1431bcc..19ca98f5f8c5f 100644 --- a/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.mqtt/src/main/resources/ESH-INF/thing/thing-types.xml @@ -50,7 +50,8 @@ Reconnect time in ms. If a connection is lost, the - binding will wait this time before it tries to reconnect. + binding will wait this time before it tries to + reconnect. 60000 true @@ -58,7 +59,8 @@ Keep alive / heartbeat timer in s. It can take up to - this time to determine if a server connection is lost. A lower + this time to determine if a server connection is + lost. A lower value may keep the broker unnecessarily busy for no or little additional value. 60 @@ -110,9 +112,11 @@ If this and SSL is set: After the next connection has - been successfully established, the certificate is pinned. The + been successfully established, the certificate is + pinned. The connection will be refused if another certificate is used. Clear - **certificate** to allow a new certificate for the next connection + **certificate** to allow a new + certificate for the next connection attempt. This option can increase security. true true @@ -120,18 +124,22 @@ If **certificatepin** is set this hash is used to - verify the connection. Clear to allow a new certificate pinning on + verify the connection. Clear to allow a new + certificate pinning on the next connection attempt. If empty will be filled automatically - by the next successful connection. An example input would be + by the next successful + connection. An example input would be `SHA-256:83F9171E06A313118889F7D79302BD1B7A2042EE0CFD029ABF8DD06FFA6CD9D3`. true If this and SSL is set: After the next connection has - been successfully established, the public key of the broker is + been successfully established, the public key of + the broker is pinned. The connection will be refused if another public key is - used. Clear **publickey** to allow a new public key for the next + used. Clear **publickey** to allow a + new public key for the next connection attempt. This option can increase security. true true @@ -139,9 +147,11 @@ If **publickeypin** is set this hash is used to verify - the connection. Clear to allow a new public key pinning on the next + the connection. Clear to allow a new public key + pinning on the next connection attempt. If empty will be filled automatically by the - next successful connection. An example input would be + next successful connection. An + example input would be `SHA-256:83F9171E06A313118889F7D79302BD1B7A2042EE0CFD029ABF8DD06FFA6CD9D3` true @@ -151,18 +161,19 @@ A system configured and therefore read-only broker - connection. Properties are reflecting the configuration and internal + connection. Properties are reflecting the configuration + and internal connection status. - - - - - - - - + + + + + + + + @@ -176,12 +187,14 @@ trigger - This channel is triggered when a value is published to the configured MQTT topic on this broker connection. The event payload will be the received MQTT topic value. + This channel is triggered when a value is published to the configured MQTT topic on this broker + connection. The event payload will be the received MQTT topic value. - This channel will trigger on this MQTT topic. This topic can contain wildcards like + and # for example "all/in/#" or "sensors/+/config". + This channel will trigger on this MQTT topic. This topic can contain wildcards like + and # for example + "all/in/#" or "sensors/+/config". @@ -189,7 +202,9 @@ - The trigger channel payload usually only contains the received MQTT topic value. If you define a separator character, for example '#', the topic and received value will be in the trigger channel payload. For example: my_topic#my_received_value. + The trigger channel payload usually only contains the received MQTT topic value. If you define a + separator character, for example '#', the topic and received value will be in the trigger channel payload. For + example: my_topic#my_received_value. diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandlerTest.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandlerTest.java index 982874d9b2d84..03d4f2e429921 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandlerTest.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/AbstractBrokerHandlerTest.java @@ -30,13 +30,11 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.openhab.binding.mqtt.handler.AbstractBrokerHandler; -import org.openhab.binding.mqtt.handler.SystemBrokerHandler; import org.openhab.binding.mqtt.internal.MqttThingID; import org.osgi.service.cm.ConfigurationException; /** - * Tests cases for {@link AbstractBrokerHandler}. + * Tests cases for {@link org.openhab.binding.mqtt.handler.AbstractBrokerHandler}. * * @author David Graeff - Initial contribution */ diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerEx.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerEx.java index 93ba58cd0f12b..4257088fafa47 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerEx.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerEx.java @@ -18,7 +18,6 @@ import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.io.transport.mqtt.MqttBrokerConnection; import org.mockito.Mockito; -import org.openhab.binding.mqtt.handler.BrokerHandler; /** * Overwrite BrokerHandler to return our mocked/extended MqttBrokerConnection in diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerTest.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerTest.java index 19fbb2adeb6a9..1d91f9d063382 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerTest.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/BrokerHandlerTest.java @@ -137,5 +137,4 @@ boolean initializeHandlerWaitForTimeout() verify(handler, times(3)).connectionStateChanged(any(), any()); return true; } - } diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttBrokerConnectionEx.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttBrokerConnectionEx.java index 83c1295c29e46..1b24eb3060e33 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttBrokerConnectionEx.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/handler/MqttBrokerConnectionEx.java @@ -110,5 +110,4 @@ protected MqttAsyncClientWrapper createClient() { public @NonNull MqttConnectionState connectionState() { return connectionStateOverwrite; } - } diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java index c336f2cfb5c2e..6eaf6c3740610 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/MQTTTopicDiscoveryServiceTest.java @@ -151,5 +151,4 @@ public void topicVanished() { .forEach(s -> s.processMessage("topic", bytes)); verify(listener).topicVanished(eq(thing.getUID()), eq(connection), eq("topic")); } - } diff --git a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/discovery/ServiceDiscoveryServiceTest.java b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/discovery/ServiceDiscoveryServiceTest.java index 301925f02aeda..2885a08c4a78a 100644 --- a/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/discovery/ServiceDiscoveryServiceTest.java +++ b/bundles/org.openhab.binding.mqtt/src/test/java/org/openhab/binding/mqtt/internal/discovery/ServiceDiscoveryServiceTest.java @@ -33,10 +33,9 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.openhab.binding.mqtt.MqttBindingConstants; -import org.openhab.binding.mqtt.internal.discovery.MqttServiceDiscoveryService; /** - * Tests cases for {@link MqttServiceDiscoveryService}. + * Tests cases for {@link org.openhab.binding.mqtt.internal.discovery.MqttServiceDiscoveryService}. * * @author David Graeff - Initial contribution */ diff --git a/bundles/org.openhab.binding.nanoleaf/pom.xml b/bundles/org.openhab.binding.nanoleaf/pom.xml index b61764c58ecf2..440b314f1b332 100644 --- a/bundles/org.openhab.binding.nanoleaf/pom.xml +++ b/bundles/org.openhab.binding.nanoleaf/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.nanoleaf diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/OpenAPIUtils.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/OpenAPIUtils.java index d1e640a48ef18..b101a02c091c3 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/OpenAPIUtils.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/OpenAPIUtils.java @@ -87,8 +87,7 @@ public static URI getUri(NanoleafControllerConfig controllerConfig, String apiOp return requestURI; } - public static ContentResponse sendOpenAPIRequest(Request request) - throws NanoleafException { + public static ContentResponse sendOpenAPIRequest(Request request) throws NanoleafException { try { traceSendRequest(request); ContentResponse openAPIResponse; @@ -122,7 +121,7 @@ public static ContentResponse sendOpenAPIRequest(Request request) throw new NanoleafUnauthorizedException("Invalid authorization token"); } throw new NanoleafException("Failed to send OpenAPI request", clientException); - } catch ( InterruptedException interruptedException) { + } catch (InterruptedException interruptedException) { throw new NanoleafInterruptedException("OpenAPI request has been interrupted", interruptedException); } } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/discovery/NanoleafMDNSDiscoveryParticipant.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/discovery/NanoleafMDNSDiscoveryParticipant.java index cab6aa7b0825a..6e7667746a47f 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/discovery/NanoleafMDNSDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/discovery/NanoleafMDNSDiscoveryParticipant.java @@ -39,7 +39,8 @@ * * @author Martin Raepple - Initial contribution * @author Stefan Höhn - further improvements for static defined things - * @see MSDN Discovery + * @see MSDN + * Discovery */ @Component(immediate = true, configurationPid = "discovery.nanoleaf") @NonNullByDefault @@ -76,10 +77,10 @@ public String getServiceType() { String qualifiedName = service.getQualifiedName(); logger.debug("AVR found: {}", qualifiedName); - logger.trace("Discovered nanoleaf host: {} port: {} firmWare: {} modelId: {} qualifiedName: {}", host, port, firmwareVersion, - modelId, qualifiedName); - logger.debug("Adding Nanoleaf controller {} with FW version {} found at {} {} to inbox", qualifiedName, firmwareVersion, host, - port); + logger.trace("Discovered nanoleaf host: {} port: {} firmWare: {} modelId: {} qualifiedName: {}", host, port, + firmwareVersion, modelId, qualifiedName); + logger.debug("Adding Nanoleaf controller {} with FW version {} found at {} {} to inbox", qualifiedName, + firmwareVersion, host, port); if (!OpenAPIUtils.checkRequiredFirmware(service.getPropertyString("md"), firmwareVersion)) { logger.warn("Nanoleaf controller firmware is too old. Must be {} or higher", MODEL_ID_LIGHTPANELS.equals(modelId) ? API_MIN_FW_VER_LIGHTPANELS : API_MIN_FW_VER_CANVAS); diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/handler/NanoleafControllerHandler.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/handler/NanoleafControllerHandler.java index 85e5e6e0cc129..67a7e8b4b9ff0 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/handler/NanoleafControllerHandler.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/handler/NanoleafControllerHandler.java @@ -130,7 +130,7 @@ public void initialize() { stopAllJobs(); } else if (!StringUtils.isEmpty(getThing().getProperties().get(Thing.PROPERTY_FIRMWARE_VERSION)) && !OpenAPIUtils.checkRequiredFirmware(getThing().getProperties().get(Thing.PROPERTY_MODEL_ID), - getThing().getProperties().get(Thing.PROPERTY_FIRMWARE_VERSION))) { + getThing().getProperties().get(Thing.PROPERTY_FIRMWARE_VERSION))) { logger.warn("Nanoleaf controller firmware is too old: {}. Must be equal or higher than {}", getThing().getProperties().get(Thing.PROPERTY_FIRMWARE_VERSION), API_MIN_FW_VER_LIGHTPANELS); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/AuthToken.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/AuthToken.java index c5eedaad2b074..80ec22a062c0e 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/AuthToken.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/AuthToken.java @@ -35,5 +35,4 @@ public class AuthToken { public void setAuthToken(String authToken) { this.authToken = authToken; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Brightness.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Brightness.java index 7cc2413b7b0bf..eb699deffdb14 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Brightness.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Brightness.java @@ -52,5 +52,4 @@ public void setMax(Integer max) { public void setMin(Integer min) { this.min = min; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Command.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Command.java index de7659ea0199c..dd2c999def841 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Command.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Command.java @@ -35,5 +35,4 @@ public class Command { public void setWrite(Write write) { this.write = write; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Effects.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Effects.java index e26f31b2bd13c..9e87a0bdc7994 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Effects.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Effects.java @@ -52,5 +52,4 @@ public void setEffectsList(@Nullable List effectsList) { public void setWrite(@Nullable Write write) { this.write = write; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/GlobalOrientation.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/GlobalOrientation.java index 969ac206c7ce4..a97a2b0aedd91 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/GlobalOrientation.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/GlobalOrientation.java @@ -50,5 +50,4 @@ public void setMax(Integer max) { public void setMin(Integer min) { this.min = min; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Hue.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Hue.java index 6e767ad4f9fae..bcaac6ba5a4cb 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Hue.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Hue.java @@ -52,5 +52,4 @@ public void setMax(Integer max) { public void setMin(Integer min) { this.min = min; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Layout.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Layout.java index d9c6fbe2f5a30..f1fa9d29deb9d 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Layout.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Layout.java @@ -74,7 +74,7 @@ public String getLayoutView() { final int noofDefinedPanels = positionData.size(); for (int index = 0; index < noofDefinedPanels; index++) { - if (positionData != null ) { + if (positionData != null) { @Nullable PositionDatum panel = positionData.get(index); diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/On.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/On.java index 4b654a9e8b4d8..33ba8715a76e4 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/On.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/On.java @@ -33,5 +33,4 @@ public boolean getValue() { public void setValue(boolean value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Palette.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Palette.java index 15c232bdddbcc..d64b3e8d91c73 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Palette.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Palette.java @@ -49,5 +49,4 @@ public int getBrightness() { public void setBrightness(int brightness) { this.brightness = brightness; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/PanelLayout.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/PanelLayout.java index 25aa9438fde22..6736d05a7ff2b 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/PanelLayout.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/PanelLayout.java @@ -41,5 +41,4 @@ public void setLayout(Layout layout) { public void setGlobalOrientation(GlobalOrientation globalOrientation) { this.globalOrientation = globalOrientation; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/PositionDatum.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/PositionDatum.java index 8172fffeea05a..b4802cb18b402 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/PositionDatum.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/PositionDatum.java @@ -63,5 +63,4 @@ public int getOrientation() { public void setOrientation(int o) { this.orientation = o; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Rhythm.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Rhythm.java index 1f740f911a6f5..c9af07675fe0d 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Rhythm.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Rhythm.java @@ -95,5 +95,4 @@ public void setRhythmMode(int rhythmMode) { public void setRhythmPos(RhythmPos rhythmPos) { this.rhythmPos = rhythmPos; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/RhythmPos.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/RhythmPos.java index 366f43e790e3f..d0c1eea47ba8d 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/RhythmPos.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/RhythmPos.java @@ -54,5 +54,4 @@ public float getOrientation() { public void setOrientation(float o) { this.orientation = o; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Sat.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Sat.java index 2a7d82c38d333..8f3e75a532e93 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Sat.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/Sat.java @@ -52,5 +52,4 @@ public void setMax(Integer max) { public void setMin(Integer min) { this.min = min; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/TouchEvents.java b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/TouchEvents.java index b236783ac1820..82da9ba48d889 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/TouchEvents.java +++ b/bundles/org.openhab.binding.nanoleaf/src/main/java/org/openhab/binding/nanoleaf/internal/model/TouchEvents.java @@ -35,5 +35,4 @@ public List getEvents() { public void setEvents(List events) { this.events = events; } - } diff --git a/bundles/org.openhab.binding.nanoleaf/src/main/resources/ESH-INF/thing/lightpanels.xml b/bundles/org.openhab.binding.nanoleaf/src/main/resources/ESH-INF/thing/lightpanels.xml index 5f753ef6b93a3..a8a7f33d80cc9 100644 --- a/bundles/org.openhab.binding.nanoleaf/src/main/resources/ESH-INF/thing/lightpanels.xml +++ b/bundles/org.openhab.binding.nanoleaf/src/main/resources/ESH-INF/thing/lightpanels.xml @@ -9,45 +9,45 @@ @text/thing-type.nanoleaf.controller.description - - - - - - - - - - + + + + + + + + + + - - - - + + + + address - + - + @text/thing-type.nanoleaf.lightpanel.description - - - + + + id - + @@ -67,7 +67,7 @@ Dimmer @text/channel-type.nanoleaf.colorTemperature.description - + @@ -75,7 +75,7 @@ @text/channel-type.nanoleaf.colorTemperatureAbs.description ColorLight - + @@ -107,14 +107,14 @@ Switch @text/channel-type.nanoleaf.rhythmState.description - + Switch @text/channel-type.nanoleaf.rhythmActive.description - + @@ -133,20 +133,20 @@ Switch @text/channel-type.nanoleaf.singleTap.description - + Switch @text/channel-type.nanoleaf.doubleTap.description - + Switch @text/channel-type.nanoleaf.panelLayout.description - + diff --git a/bundles/org.openhab.binding.neato/pom.xml b/bundles/org.openhab.binding.neato/pom.xml index b42ae70729a58..4c2d2ae5adf85 100644 --- a/bundles/org.openhab.binding.neato/pom.xml +++ b/bundles/org.openhab.binding.neato/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.neato diff --git a/bundles/org.openhab.binding.neato/src/main/feature/feature.xml b/bundles/org.openhab.binding.neato/src/main/feature/feature.xml index f9c68b923b907..5c3f784008738 100644 --- a/bundles/org.openhab.binding.neato/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.neato/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.neato/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.neato/${project.version} + diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/NeatoBindingConstants.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/NeatoBindingConstants.java index 8010deeb9175d..0af362a184c87 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/NeatoBindingConstants.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/NeatoBindingConstants.java @@ -50,5 +50,4 @@ public class NeatoBindingConstants { public static final String CONFIG_REFRESHTIME = "refresh"; public static final String PROPERTY_NAME = "robot-name"; - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/NeatoCommunicationException.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/NeatoCommunicationException.java index 41e23b722efb9..f2af0e84df8d0 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/NeatoCommunicationException.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/NeatoCommunicationException.java @@ -28,5 +28,4 @@ public NeatoCommunicationException(Throwable cause) { public NeatoCommunicationException(String message, Throwable cause) { super(message, cause); } - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/AvailableCommands.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/AvailableCommands.java index 9fbd79280b94d..94748f3c69997 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/AvailableCommands.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/AvailableCommands.java @@ -64,5 +64,4 @@ public Boolean getGoToBase() { public void setGoToBase(Boolean goToBase) { this.goToBase = goToBase; } - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/AvailableServices.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/AvailableServices.java index 426b4b65a3822..691cc65246abe 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/AvailableServices.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/AvailableServices.java @@ -73,5 +73,4 @@ public String getSchedule() { public void setSchedule(String schedule) { this.schedule = schedule; } - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/Battery.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/Battery.java index c162763727f82..8ab47060429a2 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/Battery.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/Battery.java @@ -82,5 +82,4 @@ public String getVendor() { public void setVendor(String vendor) { this.vendor = vendor; } - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/BeehiveAuthentication.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/BeehiveAuthentication.java index f5e0f7d4f1c57..aa83b789f00a3 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/BeehiveAuthentication.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/BeehiveAuthentication.java @@ -41,5 +41,4 @@ public String getCurrentTime() { public void setCurrentTime(String currentTime) { this.currentTime = currentTime; } - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/ErrorMessage.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/ErrorMessage.java index 88e9f51188f85..f7fe83ddc1c63 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/ErrorMessage.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/classes/ErrorMessage.java @@ -28,5 +28,4 @@ public String getMessage() { public void setMessage(String message) { this.message = message; } - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/config/NeatoRobotConfig.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/config/NeatoRobotConfig.java index a74a4e473c1c0..a53588e395f71 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/config/NeatoRobotConfig.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/config/NeatoRobotConfig.java @@ -52,5 +52,4 @@ public void setSerial(String serial) { public String toString() { return "NeatoRobotConfig [refresh=" + refresh + ", secret=" + secret + ", serial=" + serial + "]"; } - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/discovery/NeatoAccountDiscoveryService.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/discovery/NeatoAccountDiscoveryService.java index 39279d007b044..7e57d2afd5355 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/discovery/NeatoAccountDiscoveryService.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/discovery/NeatoAccountDiscoveryService.java @@ -96,5 +96,4 @@ private void addThing(Robot robot) { thingDiscovered( DiscoveryResultBuilder.create(thingUID).withBridge(bridgeUID).withProperties(properties).build()); } - } diff --git a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/handler/NeatoAccountHandler.java b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/handler/NeatoAccountHandler.java index 8376fca339575..a1572f0919888 100644 --- a/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/handler/NeatoAccountHandler.java +++ b/bundles/org.openhab.binding.neato/src/main/java/org/openhab/binding/neato/internal/handler/NeatoAccountHandler.java @@ -154,5 +154,4 @@ public String getToken() { return token; } } - } diff --git a/bundles/org.openhab.binding.neato/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.neato/src/main/resources/ESH-INF/binding/binding.xml index b36f1ef481707..623f442696941 100644 --- a/bundles/org.openhab.binding.neato/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.neato/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Neato Binding This is the binding for Neato. diff --git a/bundles/org.openhab.binding.neato/src/main/resources/ESH-INF/thing/vacuumcleaner.xml b/bundles/org.openhab.binding.neato/src/main/resources/ESH-INF/thing/vacuumcleaner.xml index 612bbf8ffd4ec..ec500d4043c06 100644 --- a/bundles/org.openhab.binding.neato/src/main/resources/ESH-INF/thing/vacuumcleaner.xml +++ b/bundles/org.openhab.binding.neato/src/main/resources/ESH-INF/thing/vacuumcleaner.xml @@ -6,7 +6,7 @@ - Access to Neato Account. Used to discover robots tied to account. + Access to Neato Account. Used to discover robots tied to account. @@ -27,7 +27,7 @@ - + @@ -35,19 +35,19 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -114,35 +114,35 @@ Switch True or False value if the dock has been seen - + Switch Is the vacuum cleaner in the docking station? - + Switch True or False value if the vacuum cleaner is scheduled for cleaning. - + Switch Is the vacuum cleaner currently charging? - + String Last error message in system. - + @@ -203,13 +203,13 @@ Number Current or Last cleaning, width of spot. 100-400cm. - + Number Current or Last cleaning, height of spot. 100-400cm. - + diff --git a/bundles/org.openhab.binding.neeo/.classpath b/bundles/org.openhab.binding.neeo/.classpath index a5d95095ccaaf..f2513389b0443 100644 --- a/bundles/org.openhab.binding.neeo/.classpath +++ b/bundles/org.openhab.binding.neeo/.classpath @@ -18,6 +18,7 @@ + diff --git a/bundles/org.openhab.binding.neeo/NOTICE b/bundles/org.openhab.binding.neeo/NOTICE index 38d625e349232..1b52e85062af0 100644 --- a/bundles/org.openhab.binding.neeo/NOTICE +++ b/bundles/org.openhab.binding.neeo/NOTICE @@ -11,3 +11,9 @@ https://www.eclipse.org/legal/epl-2.0/. == Source Code https://github.com/openhab/openhab-addons + +== Third-party Content + +This binding includes a class from Jersey in the src/3rdparty/java folder. +* License: CDDL License +* Project: https://eclipse-ee4j.github.io/jersey/ diff --git a/bundles/org.openhab.binding.neeo/pom.xml b/bundles/org.openhab.binding.neeo/pom.xml index 6010261cfca81..76ff35251b899 100644 --- a/bundles/org.openhab.binding.neeo/pom.xml +++ b/bundles/org.openhab.binding.neeo/pom.xml @@ -1,15 +1,38 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.neeo openHAB Add-ons :: Bundles :: Neeo Binding + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + add-source + + generate-sources + + + src/3rdparty/java + + + + + + + diff --git a/bundles/org.openhab.binding.neeo/src/3rdparty/java/org/glassfish/jersey/filter/LoggingFilter.java b/bundles/org.openhab.binding.neeo/src/3rdparty/java/org/glassfish/jersey/filter/LoggingFilter.java new file mode 100644 index 0000000000000..4457671c5cde2 --- /dev/null +++ b/bundles/org.openhab.binding.neeo/src/3rdparty/java/org/glassfish/jersey/filter/LoggingFilter.java @@ -0,0 +1,355 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2011-2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package org.glassfish.jersey.filter; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Logger; + +import javax.annotation.Priority; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; + +/** + * Universal logging filter. + *

    + * Can be used on client or server side. Has the highest priority. + * + * @author Pavel Bucek (pavel.bucek at oracle.com) + * @author Martin Matula + */ +@PreMatching +@Priority(Integer.MIN_VALUE) +public final class LoggingFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, + ClientResponseFilter, WriterInterceptor { + + public static final Charset UTF8 = Charset.forName("UTF-8"); + + private static final Logger LOGGER = Logger.getLogger(LoggingFilter.class.getName()); + private static final String NOTIFICATION_PREFIX = "* "; + private static final String REQUEST_PREFIX = "> "; + private static final String RESPONSE_PREFIX = "< "; + private static final String ENTITY_LOGGER_PROPERTY = LoggingFilter.class.getName() + ".entityLogger"; + private static final String LOGGING_ID_PROPERTY = LoggingFilter.class.getName() + ".id"; + + private static final Comparator>> COMPARATOR = new Comparator>>() { + + @Override + public int compare(final Map.Entry> o1, final Map.Entry> o2) { + return o1.getKey().compareToIgnoreCase(o2.getKey()); + } + }; + + private static final int DEFAULT_MAX_ENTITY_SIZE = 8 * 1024; + + // + private final Logger logger; + private final AtomicLong _id = new AtomicLong(0); + private final boolean printEntity; + private final int maxEntitySize; + + /** + * Create a logging filter logging the request and response to a default JDK + * logger, named as the fully qualified class name of this class. Entity + * logging is turned off by default. + */ + public LoggingFilter() { + this(LOGGER, false); + } + + /** + * Create a logging filter with custom logger and custom settings of entity + * logging. + * + * @param logger the logger to log requests and responses. + * @param printEntity if true, entity will be logged as well up to the default maxEntitySize, which is 8KB + */ + public LoggingFilter(final Logger logger, final boolean printEntity) { + this.logger = logger; + this.printEntity = printEntity; + this.maxEntitySize = DEFAULT_MAX_ENTITY_SIZE; + } + + /** + * Creates a logging filter with custom logger and entity logging turned on, but potentially limiting the size + * of entity to be buffered and logged. + * + * @param logger the logger to log requests and responses. + * @param maxEntitySize maximum number of entity bytes to be logged (and buffered) - if the entity is larger, + * logging filter will print (and buffer in memory) only the specified number of bytes + * and print "...more..." string at the end. Negative values are interpreted as zero. + */ + public LoggingFilter(final Logger logger, final int maxEntitySize) { + this.logger = logger; + this.printEntity = true; + this.maxEntitySize = Math.max(0, maxEntitySize); + } + + private void log(final StringBuilder b) { + if (logger != null) { + logger.info(b.toString()); + } + } + + private StringBuilder prefixId(final StringBuilder b, final long id) { + b.append(Long.toString(id)).append(" "); + return b; + } + + private void printRequestLine(final StringBuilder b, final String note, final long id, final String method, + final URI uri) { + prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") + .append(Thread.currentThread().getName()).append("\n"); + prefixId(b, id).append(REQUEST_PREFIX).append(method).append(" ").append(uri.toASCIIString()).append("\n"); + } + + private void printResponseLine(final StringBuilder b, final String note, final long id, final int status) { + prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") + .append(Thread.currentThread().getName()).append("\n"); + prefixId(b, id).append(RESPONSE_PREFIX).append(Integer.toString(status)).append("\n"); + } + + private void printPrefixedHeaders(final StringBuilder b, final long id, final String prefix, + final MultivaluedMap headers) { + for (final Map.Entry> headerEntry : getSortedHeaders(headers.entrySet())) { + final List val = headerEntry.getValue(); + final String header = headerEntry.getKey(); + + if (val.size() == 1) { + prefixId(b, id).append(prefix).append(header).append(": ").append(val.get(0)).append("\n"); + } else { + final StringBuilder sb = new StringBuilder(); + boolean add = false; + for (final Object s : val) { + if (add) { + sb.append(','); + } + add = true; + sb.append(s); + } + prefixId(b, id).append(prefix).append(header).append(": ").append(sb.toString()).append("\n"); + } + } + } + + private Set>> getSortedHeaders(final Set>> headers) { + final TreeSet>> sortedHeaders = new TreeSet>>( + COMPARATOR); + sortedHeaders.addAll(headers); + return sortedHeaders; + } + + private InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) + throws IOException { + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + stream.mark(maxEntitySize + 1); + final byte[] entity = new byte[maxEntitySize + 1]; + final int entitySize = stream.read(entity); + b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); + if (entitySize > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + stream.reset(); + return stream; + } + + @Override + public void filter(final ClientRequestContext context) throws IOException { + final long id = _id.incrementAndGet(); + context.setProperty(LOGGING_ID_PROPERTY, id); + + final StringBuilder b = new StringBuilder(); + + printRequestLine(b, "Sending client request", id, context.getMethod(), context.getUri()); + printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getStringHeaders()); + + if (printEntity && context.hasEntity()) { + final OutputStream stream = new LoggingStream(b, context.getEntityStream()); + context.setEntityStream(stream); + context.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) + throws IOException { + final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); + final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); + + final StringBuilder b = new StringBuilder(); + + printResponseLine(b, "Client response received", id, responseContext.getStatus()); + printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getHeaders()); + + if (printEntity && responseContext.hasEntity()) { + responseContext.setEntityStream( + logInboundEntity(b, responseContext.getEntityStream(), getCharset(responseContext.getMediaType()))); + } + + log(b); + } + + @Override + public void filter(final ContainerRequestContext context) throws IOException { + final long id = _id.incrementAndGet(); + context.setProperty(LOGGING_ID_PROPERTY, id); + + final StringBuilder b = new StringBuilder(); + + printRequestLine(b, "Server has received a request", id, context.getMethod(), + context.getUriInfo().getRequestUri()); + printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getHeaders()); + + if (printEntity && context.hasEntity()) { + context.setEntityStream(logInboundEntity(b, context.getEntityStream(), getCharset(context.getMediaType()))); + } + + log(b); + } + + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) + throws IOException { + final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); + final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); + + final StringBuilder b = new StringBuilder(); + + printResponseLine(b, "Server responded with a response", id, responseContext.getStatus()); + printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getStringHeaders()); + + if (printEntity && responseContext.hasEntity()) { + final OutputStream stream = new LoggingStream(b, responseContext.getEntityStream()); + responseContext.setEntityStream(stream); + requestContext.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void aroundWriteTo(final WriterInterceptorContext writerInterceptorContext) + throws IOException, WebApplicationException { + final LoggingStream stream = (LoggingStream) writerInterceptorContext.getProperty(ENTITY_LOGGER_PROPERTY); + writerInterceptorContext.proceed(); + if (stream != null) { + log(stream.getStringBuilder(getCharset(writerInterceptorContext.getMediaType()))); + } + } + + private class LoggingStream extends FilterOutputStream { + + private final StringBuilder b; + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + LoggingStream(final StringBuilder b, final OutputStream inner) { + super(inner); + + this.b = b; + } + + StringBuilder getStringBuilder(final Charset charset) { + // write entity to the builder + final byte[] entity = baos.toByteArray(); + + b.append(new String(entity, 0, Math.min(entity.length, maxEntitySize), charset)); + if (entity.length > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + + return b; + } + + @Override + public void write(final int i) throws IOException { + if (baos.size() <= maxEntitySize) { + baos.write(i); + } + out.write(i); + } + } + + /** + * Get the character set from a media type. + *

    + * The character set is obtained from the media type parameter "charset". + * If the parameter is not present the {@link #UTF8} charset is utilized. + * + * @param m the media type. + * @return the character set. + */ + public static Charset getCharset(MediaType m) { + String name = (m == null) ? null : m.getParameters().get(MediaType.CHARSET_PARAMETER); + return (name == null) ? UTF8 : Charset.forName(name); + } + +} diff --git a/bundles/org.openhab.binding.neeo/src/main/feature/feature.xml b/bundles/org.openhab.binding.neeo/src/main/feature/feature.xml index 3ec1eb20e490f..62c65c0c3f4aa 100644 --- a/bundles/org.openhab.binding.neeo/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.neeo/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.neeo/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.neeo/${project.version} + diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/discovery/NeeoBrainDiscovery.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/discovery/NeeoBrainDiscovery.java index dbb8be70845ae..7eb817431bd7f 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/discovery/NeeoBrainDiscovery.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/discovery/NeeoBrainDiscovery.java @@ -158,5 +158,4 @@ private InetAddress getIpAddress(ServiceInfo service) { } return null; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/handler/NeeoBrainHandler.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/handler/NeeoBrainHandler.java index 53a6efbe0cd51..d3f29e6f119da 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/handler/NeeoBrainHandler.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/handler/NeeoBrainHandler.java @@ -199,7 +199,6 @@ public void post(String json) { } } } - }, config.getForwardChain()); NeeoUtil.checkInterrupt(); diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/ExecuteResult.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/ExecuteResult.java index 1e13926497f38..e96f4427261c5 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/ExecuteResult.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/ExecuteResult.java @@ -95,5 +95,4 @@ public String toString() { return "ExecuteResult [estimatedDuration=" + estimatedDuration + ", name=" + name + ", startTime=" + startTime + ", steps=" + Arrays.toString(steps) + ", type=" + type + "]"; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoAction.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoAction.java index 6ff02c2a916ba..f4acbf1810c7e 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoAction.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoAction.java @@ -101,5 +101,4 @@ public String toString() { return "NeeoAction [action=" + action + ", actionParameter=" + actionParameter + ", recipe=" + recipe + ", device=" + device + ", room=" + room + "]"; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoBrain.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoBrain.java index a4a1cab1fad5d..8cb8b425b63f1 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoBrain.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoBrain.java @@ -136,5 +136,4 @@ public String toString() { return "NeeoBrain [name=" + name + ", version=" + version + ", label=" + label + ", configured=" + configured + ", key=" + key + ", airkey=" + airkey + ", lastchange=" + lastchange + ", rooms=" + rooms + "]"; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoDeviceDetails.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoDeviceDetails.java index b5b38593596d7..78f40143a13fe 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoDeviceDetails.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoDeviceDetails.java @@ -127,5 +127,4 @@ public String toString() { + ", manufacturer=" + manufacturer + ", name=" + name + ", timing=" + timing + ", deviceCapabilities=" + StringUtils.join(deviceCapabilities, ',') + "]"; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoDeviceDetailsTiming.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoDeviceDetailsTiming.java index d40391bfdbe2c..c09a2e377117b 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoDeviceDetailsTiming.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoDeviceDetailsTiming.java @@ -70,5 +70,4 @@ public String toString() { return "NeeoDeviceDetailsTiming [standbyCommandDelay=" + standbyCommandDelay + ", sourceSwitchDelay=" + sourceSwitchDelay + ", shutdownDelay=" + shutdownDelay + "]"; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoMacro.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoMacro.java index 06dfe633ca60d..0c6a75113d7a3 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoMacro.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoMacro.java @@ -112,5 +112,4 @@ public String toString() { return "NeeoMacro [key=" + key + ", componentType=" + componentType + ", name=" + name + ", label=" + label + ", deviceName=" + deviceName + ", roomName=" + roomName + "]"; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoMacrosDeserializer.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoMacrosDeserializer.java index cc8606f0cd39f..51ea0332f8470 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoMacrosDeserializer.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoMacrosDeserializer.java @@ -52,5 +52,4 @@ public NeeoMacros deserialize(@Nullable JsonElement jsonElement, @Nullable Type } return null; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRecipesDeserializer.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRecipesDeserializer.java index 7d4eb000467a4..a976f2484bf0e 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRecipesDeserializer.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRecipesDeserializer.java @@ -52,5 +52,4 @@ public NeeoRecipes deserialize(@Nullable JsonElement jsonElement, @Nullable Type } return null; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRoom.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRoom.java index ecbe21df39bb6..60196dfbe22a0 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRoom.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRoom.java @@ -98,5 +98,4 @@ public String toString() { return "NeeoRoom [name=" + name + ", key=" + key + ", scenarios=" + scenarios + ", devices=" + devices + ", recipes=" + recipes + "]"; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRoomsDeserializer.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRoomsDeserializer.java index dc6f6e5ace7bf..a04ff9f7b90f0 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRoomsDeserializer.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoRoomsDeserializer.java @@ -51,5 +51,4 @@ public NeeoRooms deserialize(@Nullable JsonElement jsonElement, @Nullable Type t } return null; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoScenariosDeserializer.java b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoScenariosDeserializer.java index 37f0e47ef643e..926c61bb93242 100644 --- a/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoScenariosDeserializer.java +++ b/bundles/org.openhab.binding.neeo/src/main/java/org/openhab/binding/neeo/internal/models/NeeoScenariosDeserializer.java @@ -51,5 +51,4 @@ public NeeoScenarios deserialize(@Nullable JsonElement jsonElement, @Nullable Ty } return null; } - } diff --git a/bundles/org.openhab.binding.neeo/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.neeo/src/main/resources/ESH-INF/binding/binding.xml index 2fdc30b7fb80f..d7dc8f2c56ed5 100644 --- a/bundles/org.openhab.binding.neeo/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.neeo/src/main/resources/ESH-INF/binding/binding.xml @@ -1,10 +1,11 @@ - + Neeo Binding - This binding allows you to discover NEEO Brain(s), discover the Rooms within and the Devices within those Rooms. The binding then will expose that information to openHAB and allow you to execute Recipes/Scenarios and Macros on the Devices + This binding allows you to discover NEEO Brain(s), discover the Rooms within and the Devices within those + Rooms. The binding then will expose that information to openHAB and allow you to execute Recipes/Scenarios and Macros + on the Devices Tim Roberts diff --git a/bundles/org.openhab.binding.neeo/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.neeo/src/main/resources/ESH-INF/thing/thing-types.xml index f1bc5369f78db..6a4d92ad2c7c9 100644 --- a/bundles/org.openhab.binding.neeo/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.neeo/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,7 +9,7 @@ The NEEO Brain - + @@ -43,14 +43,14 @@ - + Neeo Room - - - + + + @@ -73,12 +73,12 @@ - + Neeo Device - + @@ -100,7 +100,7 @@ The room's state - + @@ -114,29 +114,29 @@ The room recipes - - - - + + + + String The recipe name - + String The type of recipe - + Switch Whether the recipe is enabled or not. - + Switch @@ -147,22 +147,22 @@ The room scenarios - - - + + + String The scenario name - + Switch Whether the scenario is configured or not - + Switch @@ -173,7 +173,7 @@ Executable macros - + diff --git a/bundles/org.openhab.binding.neohub/README.md b/bundles/org.openhab.binding.neohub/README.md index 1f652e74859b2..7e4b20d108efd 100644 --- a/bundles/org.openhab.binding.neohub/README.md +++ b/bundles/org.openhab.binding.neohub/README.md @@ -9,11 +9,13 @@ See the manufacturers web site for more details: https://www.heatmiser.com The binding supports three types of Thing as follows.. -| Thing Type | Description | -|------------|-------------------------------------------------------------------------------------------| -| NeoHub | The Heatmiser NeoHub bridge which is used to communicate with NeoStat and NeoPlug devices | -| NeoStat | Heatmiser Neostat Smart Thermostat | -| NeoPlug | Heatmiser NeoPlug Smart Plug | +| Thing Type | Description | +|----------------------|-------------------------------------------------------------------------------------------| +| NeoHub | The Heatmiser NeoHub bridge which is used to communicate with NeoStat and NeoPlug devices | +| NeoStat | Heatmiser Neostat Smart Thermostat | +| NeoPlug | Heatmiser NeoPlug Smart Plug | +| NeoContact | Heatmiser (wireless) door or window contact | +| NeoTemperatureSensor | Heatmiser (wireless) temperature sensor | ## Discovery @@ -21,11 +23,11 @@ You have to manually create a single (Bridge) Thing for the NeoHub, and enter th If the Configuration Parameters are all valid, then the NeoHub Thing will automatically attempt to connect and sign on to the hub. If the sign on succeeds, the Thing will indicate its status as Online, otherwise it will show an error status. -Once the NeoHub Thing has been created and it has successfully signed on, it will automatically interrogate the server to discover all the respective NeoStat and NeoPlug Things that are connected to the hub. +Once the NeoHub Thing has been created and it has successfully signed on, it will automatically interrogate the server to discover all the respective NeoXxx Things that are connected to the hub. ## Thing Configuration for "NeoHub" -The NeoHub Thing connects to the hub (bridge) to communicate with any respective connected NeoStat and NeoPlug Things. +The NeoHub Thing connects to the hub (bridge) to communicate with any respective connected NeoXxx Things. It signs on to the hub using the supplied connection parameters, and it polls the hub at regular intervals to read and write the data for each NeoXxx device. Before it can connect to the hub, the following Configuration Parameters must be entered. @@ -56,6 +58,7 @@ The following Channels, and their associated channel types are shown below. | floorTemperature | Number:Temperature | Actual floor temperature | | thermostatOutputState | String | Status of whether the thermostat is Off, or calling for Heat | | occupancyModePresent | Switch | The Thermostat is in the Present Occupancy Mode (Off=Absent, On=Present) | +| batteryLowAlarm | Switch | The battery is low (only applies to battery thermostats) (Off=Ok, On=Alarm) | ## Channels for "NeoPlug" @@ -66,6 +69,23 @@ The following Channels, and their associated channel types are shown below. | plugOutputState | Switch | The output state of the Plug switch (Off, On) | | plugAutoMode | Switch | The Plug is in Automatic Mode (Off=Manual, On=Automatic) | +## Channels for "NeoContact" + +The following Channels, and their associated channel types are shown below. + +| Channel | Data Type | Description | +|-------------------|-----------|----------------------------------------------------------| +| contactState | Switch | The state of the contact (Off, On) (Read-Only) | +| batteryLowAlarm | Switch | The battery is low (Off=Ok, On=Alarm) | + +## Channels for "NeoTemperatureSensor" + +The following Channels, and their associated channel types are shown below. + +| Channel | Data Type | Description | +|-------------------|--------------------|-------------------------------------------------| +| sensorTemperature | Number:Temperature | Actual measured temperature | +| batteryLowAlarm | Switch | The battery is low (Off=Ok, On=Alarm) | ## Full Example @@ -75,6 +95,8 @@ The following Channels, and their associated channel types are shown below. Bridge neohub:neohub:myhubname "Heatmiser NeoHub" [ hostName="192.168.1.123", portNumber=4242, pollingInterval=60 ] { Thing neoplug mydownstairs "Downstairs Plug" @ "Hall" [ deviceNameInHub="Hall Plug" ] Thing neostat myupstairs "Upstairs Thermostat" @ "Landing" [ deviceNameInHub="Landing Thermostat" ] + Thing neocontact mycontact "Window Contact" @ "Bedroom" [ deviceNameInHub="Bedroom Window Contact" ] + Thing neotemperaturesensor mysensor "Kitchen Temperature" @ "Kitchen" [ deviceNameInHub="Kitchen Temperature Sensor" ] } ``` @@ -89,6 +111,11 @@ Switch Upstairs_OccupancyModePresent "Occupancy Mode Present" { channel="neohub: Switch Downstairs_PlugAutoMode "Plug Auto Mode" { channel="neohub:neoplug:myhubname:mydownstairs:plugAutoMode" } Switch Downstairs_PlugOutputState "Plug Output State" { channel="neohub:neoplug:myhubname:mydownstairs:plugOutputState" } + +Switch Window_Contact_State "Window Contact State" { channel="neohub:neocontact:myhubname:mycontact:contactState" } +Switch Window_Contact_Battery_Low "Window Contact Battery Low" { channel="neohub:neocontact:myhubname:mycontact:batteryLowAlarm" } + +Number:Temperature Kitchen_Temperature "Kitchen Temperature" { channel="neohub:neotemperaturesensor:myhubname:mysensor:sensorTemperature" } ``` ### `demo.sitemap` File @@ -96,7 +123,7 @@ Switch Downstairs_PlugOutputState "Plug Output State" { channel="neohub:neoplug: ``` sitemap neohub label="Heatmiser NeoHub" { - Frame label="Heating" { + Frame label="Thermostat" { Text item=Upstairs_RoomTemperature Setpoint item=Upstairs_TargetTemperature minValue=15 maxValue=30 step=1 Text item=Upstairs_ThermostatOutputState @@ -108,5 +135,14 @@ sitemap neohub label="Heatmiser NeoHub" Switch item=Downstairs_PlugOutputState Switch item=Downstairs_PlugAutoMode } + + Frame label="Contact" { + Switch item=Window_Contact_State + Switch item=Window_Contact_Battery_Low + } + + Frame label="Sensor" { + Text item=Kitchen_Temperature + } } ``` diff --git a/bundles/org.openhab.binding.neohub/pom.xml b/bundles/org.openhab.binding.neohub/pom.xml index 8e40d5aa55a57..eb1609b309c56 100644 --- a/bundles/org.openhab.binding.neohub/pom.xml +++ b/bundles/org.openhab.binding.neohub/pom.xml @@ -1,14 +1,16 @@ - + + - 4.0.0 + 4.0.0 - - org.openhab.addons.bundles - org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT - + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + - org.openhab.binding.neohub - openHAB Add-ons :: Bundles :: NeoHub Binding + org.openhab.binding.neohub + openHAB Add-ons :: Bundles :: NeoHub Binding diff --git a/bundles/org.openhab.binding.neohub/src/main/feature/feature.xml b/bundles/org.openhab.binding.neohub/src/main/feature/feature.xml index 460a41af31659..d05bcd6ada5ed 100644 --- a/bundles/org.openhab.binding.neohub/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.neohub/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.neohub/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.neohub/${project.version} + diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoBaseConfiguration.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoBaseConfiguration.java index 35e6a14bb370a..bc6bd222bf0a9 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoBaseConfiguration.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoBaseConfiguration.java @@ -21,5 +21,4 @@ public class NeoBaseConfiguration { public String deviceNameInHub; - } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoBaseHandler.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoBaseHandler.java index eb51752c4e427..95bd81bf3f0cb 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoBaseHandler.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoBaseHandler.java @@ -14,7 +14,8 @@ import static org.openhab.binding.neohub.internal.NeoHubBindingConstants.*; -import org.eclipse.jdt.annotation.NonNull; +import javax.measure.Unit; + import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.thing.Bridge; @@ -100,15 +101,16 @@ public void initialize() { * this method is called back by the NeoHub handler to inform this handler about * polling results from the hub handler */ - public void toBaseSendPollResponse(@NonNull NeoHubInfoResponse infoResponse) { - NeoHubInfoResponse.DeviceInfo myInfo = infoResponse.getDeviceInfo(config.deviceNameInHub); - if (myInfo == null) { + public void toBaseSendPollResponse(NeoHubInfoResponse infoResponse, Unit temperatureUnit) { + NeoHubInfoResponse.DeviceInfo deviceInfo = infoResponse.getDeviceInfo(config.deviceNameInHub); + + if (deviceInfo == null) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR); logger.warn(MSG_FMT_DEVICE_CONFIG, getThing().getLabel()); return; } - - if (myInfo.isOffline()) { + + if (deviceInfo.isOffline()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); logger.debug(MSG_FMT_DEVICE_COMM, getThing().getLabel()); return; @@ -117,8 +119,8 @@ public void toBaseSendPollResponse(@NonNull NeoHubInfoResponse infoResponse) { if (getThing().getStatus() != ThingStatus.ONLINE) { updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); } - - toOpenHabSendChannelValues(myInfo); + + toOpenHabSendChannelValues(deviceInfo, temperatureUnit); } /* @@ -146,27 +148,27 @@ protected void toNeoHubSendCommand(String channelId, Command command) { * issue command, check result, and update status accordingly */ switch (hub.toNeoHubSendChannelValue(cmdStr)) { - case SUCCEEDED: - logger.debug(MSG_FMT_COMMAND_OK, getThing().getLabel()); + case SUCCEEDED: + logger.debug(MSG_FMT_COMMAND_OK, getThing().getLabel()); - if (getThing().getStatus() != ThingStatus.ONLINE) { - updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); - } + if (getThing().getStatus() != ThingStatus.ONLINE) { + updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); + } - // initialize the de-bouncer for this channel - debouncer.initialize(channelId); + // initialize the de-bouncer for this channel + debouncer.initialize(channelId); - break; + break; - case ERR_COMMUNICATION: - logger.debug(MSG_HUB_COMM); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); - break; + case ERR_COMMUNICATION: + logger.debug(MSG_HUB_COMM); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); + break; - case ERR_INITIALIZATION: - logger.warn(MSG_HUB_CONFIG); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); - break; + case ERR_INITIALIZATION: + logger.warn(MSG_HUB_CONFIG); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + break; } } else { logger.debug(MSG_HUB_CONFIG); @@ -217,7 +219,7 @@ protected void toNeoHubSendCommandSet(String channelId, Command command) { * NOTE: descendant classes MUST override this method method by which the * handler informs openHAB about channel state changes */ - protected void toOpenHabSendChannelValues(NeoHubInfoResponse.DeviceInfo deviceInfo) { + protected void toOpenHabSendChannelValues(NeoHubInfoResponse.DeviceInfo deviceInfo, Unit temperatureUnit) { } protected OnOffType invert(OnOffType value) { diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoContactHandler.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoContactHandler.java new file mode 100644 index 0000000000000..a3afe67f25d94 --- /dev/null +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoContactHandler.java @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.neohub.internal; + +import static org.openhab.binding.neohub.internal.NeoHubBindingConstants.*; + +import javax.measure.Unit; + +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Thing; + +/** + * The {@link NeoContactHandler} is the OpenHAB Handler for NeoContact devices + * + * Note: inherits almost all the functionality of a {@link NeoBaseHandler} + * + * @author Andrew Fiddian-Green - Initial contribution + * + */ +public class NeoContactHandler extends NeoBaseHandler { + + public NeoContactHandler(Thing thing) { + super(thing); + } + + // =========== methods of NeoBaseHandler that are overridden ================ + + @Override + protected void toOpenHabSendChannelValues(NeoHubInfoResponse.DeviceInfo deviceInfo, Unit temperatureUnit) { + toOpenHabSendValueDebounced(CHAN_CONTACT_STATE, OnOffType.from(deviceInfo.isCoolInputOn())); + + toOpenHabSendValueDebounced(CHAN_BATTERY_LOW_ALARM, OnOffType.from(deviceInfo.isBatteryLow())); + } +} diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubBindingConstants.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubBindingConstants.java index 371fbeeda9209..46ac9698802b5 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubBindingConstants.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubBindingConstants.java @@ -35,6 +35,8 @@ public class NeoHubBindingConstants { public static final String DEVICE_ID_NEOHUB = "neohub"; public static final String DEVICE_ID_NEOSTAT = "neostat"; public static final String DEVICE_ID_NEOPLUG = "neoplug"; + public static final String DEVICE_ID_NEOCONTACT = "neocontact"; + public static final String DEVICE_ID_NEOTEMPERATURESENSOR = "neotemperaturesensor"; /* * Thing Type UIDs @@ -42,9 +44,17 @@ public class NeoHubBindingConstants { public static final ThingTypeUID THING_TYPE_NEOHUB = new ThingTypeUID(BINDING_ID, DEVICE_ID_NEOHUB); public static final ThingTypeUID THING_TYPE_NEOSTAT = new ThingTypeUID(BINDING_ID, DEVICE_ID_NEOSTAT); public static final ThingTypeUID THING_TYPE_NEOPLUG = new ThingTypeUID(BINDING_ID, DEVICE_ID_NEOPLUG); + public static final ThingTypeUID THING_TYPE_NEOCONTACT = new ThingTypeUID(BINDING_ID, DEVICE_ID_NEOCONTACT); + public static final ThingTypeUID THING_TYPE_NEOTEMPERATURESENSOR = new ThingTypeUID(BINDING_ID, + DEVICE_ID_NEOTEMPERATURESENSOR); /* - * Channel IDs for NeoStats + * Channel IDs common for several device types + */ + public static final String CHAN_BATTERY_LOW_ALARM = "batteryLowAlarm"; + + /* + * Channel IDs for NeoStat thermostats */ public static final String CHAN_ROOM_TEMP = "roomTemperature"; public static final String CHAN_TARGET_TEMP = "targetTemperature"; @@ -53,16 +63,28 @@ public class NeoHubBindingConstants { public static final String CHAN_STAT_OUTPUT_STATE = "thermostatOutputState"; /* - * Channel IDs for NeoPlugs + * Channel IDs for NeoPlug smart plugs */ public static final String CHAN_PLUG_OUTPUT_STATE = "plugOutputState"; public static final String CHAN_PLUG_AUTO_MODE = "plugAutoMode"; + /* + * Channel IDs for NeoContact (wireless) contact sensors + */ + public static final String CHAN_CONTACT_STATE = "contactState"; + + /* + * Channel IDs for NeoTemperatureSensor (wireless) temperature sensors + */ + public static final String CHAN_TEMPERATURE_SENSOR = "sensorTemperature"; + /* * enumerator for results of method calls */ public static enum NeoHubReturnResult { - SUCCEEDED, ERR_COMMUNICATION, ERR_INITIALIZATION + SUCCEEDED, + ERR_COMMUNICATION, + ERR_INITIALIZATION } /* @@ -110,19 +132,21 @@ public static enum NeoHubReturnResult { public static final String CMD_CODE_AWAY = "{\"FROST_%s\":\"%s\"}"; public static final String CMD_CODE_TIMER = "{\"TIMER_%s\":\"%s\"}"; public static final String CMD_CODE_MANUAL = "{\"MANUAL_%s\":\"%s\"}"; + public static final String CMD_CODE_READ_DCB = "{\"READ_DCB\":100}"; /* * openHAB status strings */ public static final String VAL_OFF = "Off"; public static final String VAL_HEATING = "Heating"; - + /* * logger message strings */ public static final String PLEASE_REPORT_BUG = "Unexpected situation - please report a bug: "; public static final String MSG_HUB_CONFIG = PLEASE_REPORT_BUG + "hub needs to be initialized!"; public static final String MSG_HUB_COMM = PLEASE_REPORT_BUG + "error communicating with the hub!"; - public static final String MSG_FMT_POLL_ERR = "Polling error: {}"; - + public static final String MSG_FMT_INFO_POLL_ERR = "INFO polling error: {}"; + public static final String MSG_FMT_DCB_POLL_ERR = "READ_DCB polling error: {}"; + public static final String MSG_FMT_SET_VALUE_ERR = "{} set value error: {}"; } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubConfiguration.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubConfiguration.java index 8dee34554eafd..17d5ef155b687 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubConfiguration.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubConfiguration.java @@ -23,5 +23,4 @@ public class NeoHubConfiguration { public String hostName; public int portNumber; public int pollingInterval; - } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubDebouncer.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubDebouncer.java index 309217d09a508..dca2917835125 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubDebouncer.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubDebouncer.java @@ -53,5 +53,4 @@ public void initialize(String channelId) { public Boolean timeExpired(String channelId) { return (channels.containsKey(channelId) ? channels.get(channelId).timeExpired() : true); } - } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubDiscoveryService.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubDiscoveryService.java index d59d846829a51..33cb1a91a8516 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubDiscoveryService.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubDiscoveryService.java @@ -13,7 +13,6 @@ package org.openhab.binding.neohub.internal; import static org.openhab.binding.neohub.internal.NeoHubBindingConstants.*; -import org.openhab.binding.neohub.internal.NeoHubInfoResponse.DeviceInfo; import java.util.Collections; import java.util.List; @@ -29,7 +28,7 @@ import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; - +import org.openhab.binding.neohub.internal.NeoHubInfoResponse.DeviceInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,8 +45,9 @@ public class NeoHubDiscoveryService extends AbstractDiscoveryService { private ScheduledFuture discoveryScheduler; private NeoHubHandler hub; - public static final Set DISCOVERABLE_THING_TYPES_UIDS = Collections - .unmodifiableSet(Stream.of(THING_TYPE_NEOSTAT, THING_TYPE_NEOPLUG).collect(Collectors.toSet())); + public static final Set DISCOVERABLE_THING_TYPES_UIDS = Collections.unmodifiableSet( + Stream.of(THING_TYPE_NEOSTAT, THING_TYPE_NEOPLUG, THING_TYPE_NEOCONTACT, THING_TYPE_NEOTEMPERATURESENSOR) + .collect(Collectors.toSet())); public NeoHubDiscoveryService(NeoHubHandler hub) { // note: background discovery is enabled in the super method @@ -92,7 +92,7 @@ protected void stopBackgroundDiscovery() { private void discoverDevices() { NeoHubInfoResponse infoResponse; - if ((infoResponse = hub.fromNeoHubFetchPollingResponse()) != null) { + if ((infoResponse = hub.fromNeoHubReadInfoResponse()) != null) { List devices; if ((devices = infoResponse.getDevices()) != null) { for (DeviceInfo device : devices) { @@ -113,12 +113,31 @@ private void publishDevice(DeviceInfo deviceInfo) { bridgeUID = hub.getThing().getUID(); - if (deviceInfo.getDeviceType().intValue() == 6) { - deviceType = DEVICE_ID_NEOPLUG; - deviceTypeUID = THING_TYPE_NEOPLUG; - } else { - deviceType = DEVICE_ID_NEOSTAT; - deviceTypeUID = THING_TYPE_NEOSTAT; + int deviceId = deviceInfo.getDeviceType().intValue(); + switch (deviceId) { + // device type 6 is a smart plug + case 6: { + deviceType = DEVICE_ID_NEOPLUG; + deviceTypeUID = THING_TYPE_NEOPLUG; + break; + } + // device type 14 is a (wireless) temperature sensor + case 14: { + deviceType = DEVICE_ID_NEOTEMPERATURESENSOR; + deviceTypeUID = THING_TYPE_NEOTEMPERATURESENSOR; + break; + } + // device type 5 is a (wireless) door/window contact + case 5: { + deviceType = DEVICE_ID_NEOCONTACT; + deviceTypeUID = THING_TYPE_NEOCONTACT; + break; + } + // all other device types are assumed to be thermostats + default: { + deviceType = DEVICE_ID_NEOSTAT; + deviceTypeUID = THING_TYPE_NEOSTAT; + } } deviceNeohubName = deviceInfo.getDeviceName(); @@ -130,7 +149,6 @@ private void publishDevice(DeviceInfo deviceInfo) { thingDiscovered(device); - logger.debug("discovered device={}, name={} ..", deviceType, deviceOpenHabId); + logger.debug("discovered device={}, type={}, name={} ..", deviceType, deviceId, deviceOpenHabId); } - } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubHandler.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubHandler.java index 7be9729e189c8..856cf863ca3f2 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubHandler.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubHandler.java @@ -19,7 +19,10 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import javax.measure.Unit; + import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.unit.SIUnits; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; @@ -167,7 +170,7 @@ public synchronized NeoHubReturnResult toNeoHubSendChannelValue(String commandSt return NeoHubReturnResult.SUCCEEDED; } catch (Exception e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); - logger.warn("set value error \"{}\"", e.getMessage()); + logger.warn(MSG_FMT_SET_VALUE_ERR, commandStr, e.getMessage()); return NeoHubReturnResult.ERR_COMMUNICATION; } } @@ -178,7 +181,7 @@ public synchronized NeoHubReturnResult toNeoHubSendChannelValue(String commandSt * @return a class that contains the full status of all devices * */ - protected NeoHubInfoResponse fromNeoHubFetchPollingResponse() { + protected NeoHubInfoResponse fromNeoHubReadInfoResponse() { if (socket == null || config == null) { logger.warn(MSG_HUB_CONFIG); return null; @@ -191,13 +194,13 @@ protected NeoHubInfoResponse fromNeoHubFetchPollingResponse() { NeoHubInfoResponse newInfoResponse = NeoHubInfoResponse.createInfoResponse(response); if (newInfoResponse == null) { - logger.warn(MSG_FMT_POLL_ERR, "failed to create InfoResponse"); + logger.warn(MSG_FMT_INFO_POLL_ERR, "failed to create INFO Response"); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); return null; } if (newInfoResponse.getDevices() == null) { - logger.warn(MSG_FMT_POLL_ERR, "no devices found"); + logger.warn(MSG_FMT_INFO_POLL_ERR, "no devices found"); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); return null; } @@ -208,28 +211,56 @@ protected NeoHubInfoResponse fromNeoHubFetchPollingResponse() { return newInfoResponse; } catch (Exception e) { - logger.warn(MSG_FMT_POLL_ERR, e.getMessage()); + logger.warn(MSG_FMT_INFO_POLL_ERR, e.getMessage()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); return null; } } + /** + * sends a JSON "READ_DCB" request to the NeoHub + * + * @return a class that contains the full status of all devices + * + */ + protected NeoHubReadDcbResponse fromNeoHubReadDcbResponse() { + try { + @Nullable + String response = socket.sendMessage(CMD_CODE_READ_DCB); + + NeoHubReadDcbResponse dcbResponse = NeoHubReadDcbResponse.createReadDcbResponse(response); + + if (dcbResponse == null) { + logger.warn(MSG_FMT_DCB_POLL_ERR, "failed to create DCB Response"); + return null; + } + + return dcbResponse; + } catch (Exception e) { + logger.warn(MSG_FMT_DCB_POLL_ERR, e.getMessage()); + return null; + } + } + /* * this is the callback used by the lazy polling scheduler.. fetches the info * for all devices from the NeoHub, and passes the results the respective device * handlers */ private synchronized void lazyPollingSchedulerExecute() { - NeoHubInfoResponse infoResponse = fromNeoHubFetchPollingResponse(); + NeoHubInfoResponse infoResponse = fromNeoHubReadInfoResponse(); if (infoResponse != null) { - List children = getThing().getThings(); + // determine temperatureUnit + NeoHubReadDcbResponse dcbResponse = fromNeoHubReadDcbResponse(); + Unit temperatureUnit = (dcbResponse != null) ? dcbResponse.getTemperatureUnit() : SIUnits.CELSIUS; - // dispatch myInfoResponse to each of the hub's owned devices .. + // dispatch infoResponse to each of the hub's owned devices .. + List children = getThing().getThings(); for (Thing child : children) { ThingHandler device = child.getHandler(); if (device instanceof NeoBaseHandler) { - ((NeoBaseHandler) device).toBaseSendPollResponse(infoResponse); + ((NeoBaseHandler) device).toBaseSendPollResponse(infoResponse, temperatureUnit); } } } @@ -248,5 +279,4 @@ private void fastPollingSchedulerExecute() { lazyPollingSchedulerExecute(); } } - } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubHandlerFactory.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubHandlerFactory.java index 3d0d62aa407a1..109172fc0ed2c 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubHandlerFactory.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubHandlerFactory.java @@ -43,7 +43,8 @@ public class NeoHubHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = Collections - .unmodifiableSet(new HashSet<>(Arrays.asList(THING_TYPE_NEOHUB, THING_TYPE_NEOSTAT, THING_TYPE_NEOPLUG))); + .unmodifiableSet(new HashSet<>(Arrays.asList(THING_TYPE_NEOHUB, THING_TYPE_NEOSTAT, THING_TYPE_NEOPLUG, + THING_TYPE_NEOCONTACT, THING_TYPE_NEOTEMPERATURESENSOR))); private final Map> discoServices = new HashMap<>(); @@ -70,6 +71,14 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return new NeoPlugHandler(thing); } + if (thingTypeUID.equals(THING_TYPE_NEOCONTACT)) { + return new NeoContactHandler(thing); + } + + if (thingTypeUID.equals(THING_TYPE_NEOTEMPERATURESENSOR)) { + return new NeoTemperatureSensorHandler(thing); + } + return null; } @@ -122,5 +131,4 @@ private synchronized void destroyDiscoveryService(NeoHubHandler handler) { } } } - } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubInfoResponse.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubInfoResponse.java index dbb850399598c..d0801ba150022 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubInfoResponse.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubInfoResponse.java @@ -62,12 +62,10 @@ public static class DeviceInfo { private BigDecimal currentTemperature; @SerializedName("CURRENT_FLOOR_TEMPERATURE") private BigDecimal currentFloorTemperature; - @SerializedName("AWAY") - private NeohubBool away; - @SerializedName("HOLIDAY") - private NeohubBool holiday; - @SerializedName("HOLIDAY_DAYS") - private BigDecimal holidayDays; + @SerializedName("COOL_INP") + private NeohubBool coolInput; + @SerializedName("LOW_BATTERY") + private NeohubBool batteryLow; @SerializedName("STANDBY") private NeohubBool standby; @SerializedName("HEATING") @@ -107,18 +105,6 @@ public BigDecimal getFloorTemperature() { return safeBigDecimal(currentFloorTemperature); } - public Boolean isAway() { - return safeBoolean(away); - } - - public Boolean isHoliday() { - return safeBoolean(holiday); - } - - public BigDecimal getHolidayDays() { - return safeBigDecimal(holidayDays); - } - public BigDecimal getDeviceType() { return safeBigDecimal(deviceType); } @@ -151,10 +137,13 @@ public Boolean stateAuto() { return (statMode != null && statMode.stateManualOff()); } - public Boolean hasStatMode() { - return statMode != null; + public Boolean isCoolInputOn() { + return safeBoolean(coolInput); } + public Boolean isBatteryLow() { + return safeBoolean(batteryLow); + } } /** diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubReadDcbResponse.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubReadDcbResponse.java new file mode 100644 index 0000000000000..c40c52e43aeaa --- /dev/null +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubReadDcbResponse.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.neohub.internal; + +import javax.measure.Unit; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.unit.ImperialUnits; +import org.eclipse.smarthome.core.library.unit.SIUnits; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.annotations.SerializedName; + +/** + * A wrapper around the JSON response to the JSON READ_DCB 100 request + * + * @author Andrew Fiddian-Green - Initial contribution + * + */ +public class NeoHubReadDcbResponse { + + private static final Gson GSON = new Gson(); + + @SerializedName("CORF") + private String degreesCorF; + + public Unit getTemperatureUnit() { + return "F".equalsIgnoreCase(degreesCorF) ? ImperialUnits.FAHRENHEIT : SIUnits.CELSIUS; + } + + /** + * Create wrapper around the JSON response + * + * @param response the JSON INFO request + * @return a NeoHubReadDcbResponse wrapper around the JSON response + * @throws JsonSyntaxException + * + */ + public static @Nullable NeoHubReadDcbResponse createReadDcbResponse(String response) throws JsonSyntaxException { + return GSON.fromJson(response, NeoHubReadDcbResponse.class); + } +} diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubSocket.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubSocket.java index 50cdb88da099b..43c6869911ab5 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubSocket.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoHubSocket.java @@ -109,5 +109,4 @@ public String sendMessage(final String request) throws IOException, NeoHubExcept } } } - } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoPlugHandler.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoPlugHandler.java index fa63af744a999..326cf012b0bc1 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoPlugHandler.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoPlugHandler.java @@ -14,6 +14,8 @@ import static org.openhab.binding.neohub.internal.NeoHubBindingConstants.*; +import javax.measure.Unit; + import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.Command; @@ -56,7 +58,7 @@ protected void toNeoHubSendCommandSet(String channelId, Command command) { } @Override - protected void toOpenHabSendChannelValues(NeoHubInfoResponse.DeviceInfo deviceInfo) { + protected void toOpenHabSendChannelValues(NeoHubInfoResponse.DeviceInfo deviceInfo, Unit temperatureUnit) { toOpenHabSendValueDebounced(CHAN_PLUG_AUTO_MODE, OnOffType.from(!deviceInfo.stateManual())); toOpenHabSendValueDebounced(CHAN_PLUG_OUTPUT_STATE, OnOffType.from(deviceInfo.isTimerOn())); diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoStatHandler.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoStatHandler.java index ded21d20aa466..3127e38aaed88 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoStatHandler.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoStatHandler.java @@ -14,10 +14,11 @@ import static org.openhab.binding.neohub.internal.NeoHubBindingConstants.*; +import javax.measure.Unit; + import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.library.unit.SIUnits; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.Command; @@ -48,21 +49,22 @@ protected String toNeoHubBuildCommandString(String channelId, Command command) { } @Override - protected void toOpenHabSendChannelValues(NeoHubInfoResponse.DeviceInfo deviceInfo) { + protected void toOpenHabSendChannelValues(NeoHubInfoResponse.DeviceInfo deviceInfo, Unit temperatureUnit) { toOpenHabSendValueDebounced(CHAN_TARGET_TEMP, - new QuantityType<>(deviceInfo.getTargetTemperature(), SIUnits.CELSIUS)); + new QuantityType<>(deviceInfo.getTargetTemperature(), temperatureUnit)); toOpenHabSendValueDebounced(CHAN_ROOM_TEMP, - new QuantityType<>(deviceInfo.getRoomTemperature(), SIUnits.CELSIUS)); + new QuantityType<>(deviceInfo.getRoomTemperature(), temperatureUnit)); toOpenHabSendValueDebounced(CHAN_FLOOR_TEMP, - new QuantityType<>(deviceInfo.getFloorTemperature(), SIUnits.CELSIUS)); + new QuantityType<>(deviceInfo.getFloorTemperature(), temperatureUnit)); toOpenHabSendValueDebounced(CHAN_OCC_MODE_PRESENT, OnOffType.from(!deviceInfo.isStandby())); toOpenHabSendValueDebounced(CHAN_STAT_OUTPUT_STATE, (deviceInfo.isHeating() || deviceInfo.isPreHeating() ? new StringType(VAL_HEATING) : new StringType(VAL_OFF))); - } + toOpenHabSendValueDebounced(CHAN_BATTERY_LOW_ALARM, OnOffType.from(deviceInfo.isBatteryLow())); + } } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoTemperatureSensorHandler.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoTemperatureSensorHandler.java new file mode 100644 index 0000000000000..6370eecd95484 --- /dev/null +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeoTemperatureSensorHandler.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.neohub.internal; + +import static org.openhab.binding.neohub.internal.NeoHubBindingConstants.*; + +import javax.measure.Unit; + +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.thing.Thing; + +/** + * The {@link NeoTemperatureSensorHandler} is the OpenHAB Handler for NeoTemperatureSensor devices + * + * Note: inherits almost all the functionality of a {@link NeoBaseHandler} + * + * @author Andrew Fiddian-Green - Initial contribution + * + */ +public class NeoTemperatureSensorHandler extends NeoBaseHandler { + + public NeoTemperatureSensorHandler(Thing thing) { + super(thing); + } + + // =========== methods of NeoBaseHandler that are overridden ================ + + @Override + protected void toOpenHabSendChannelValues(NeoHubInfoResponse.DeviceInfo deviceInfo, Unit temperatureUnit) { + toOpenHabSendValueDebounced(CHAN_TEMPERATURE_SENSOR, + new QuantityType<>(deviceInfo.getRoomTemperature(), temperatureUnit)); + + toOpenHabSendValueDebounced(CHAN_BATTERY_LOW_ALARM, OnOffType.from(deviceInfo.isBatteryLow())); + } +} diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeohubBool.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeohubBool.java index c81492df82fec..96d942cd30829 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeohubBool.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeohubBool.java @@ -26,5 +26,4 @@ class NeohubBool { public NeohubBool(boolean value) { this.value = value; } - } diff --git a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeohubBoolDeserializer.java b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeohubBoolDeserializer.java index 161d642725d17..8fd0510d61d7b 100644 --- a/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeohubBoolDeserializer.java +++ b/bundles/org.openhab.binding.neohub/src/main/java/org/openhab/binding/neohub/internal/NeohubBoolDeserializer.java @@ -41,5 +41,4 @@ public NeohubBool deserialize(JsonElement json, Type typeOfT, JsonDeserializatio } return new NeohubBool(false); } - } diff --git a/bundles/org.openhab.binding.neohub/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.neohub/src/main/resources/ESH-INF/binding/binding.xml index db04f439fa05e..3a83e92cd7490 100644 --- a/bundles/org.openhab.binding.neohub/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.neohub/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,5 @@ - diff --git a/bundles/org.openhab.binding.neohub/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.neohub/src/main/resources/ESH-INF/thing/thing-types.xml index 5127dbc087940..4a167e932226d 100644 --- a/bundles/org.openhab.binding.neohub/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.neohub/src/main/resources/ESH-INF/thing/thing-types.xml @@ -28,8 +28,7 @@ 4242 - + Time (seconds) between polling the NeoHub (min=4, max/default=60) 60 @@ -42,7 +41,7 @@ - + @@ -69,12 +68,15 @@ Status of whether the thermostat is Off, or calling for Heat - + The Thermostat is in the Present Occupancy Mode (Off=Absent, On=Present) + + + ON if the device has a low battery + @@ -84,8 +86,7 @@ deviceNameInHub - + Device Name that identifies the NeoStat device in the NeoHub and Heatmiser App @@ -96,7 +97,7 @@ - + @@ -121,10 +122,81 @@ deviceNameInHub - + + + Device Name that identifies the NeoPlug device in the NeoHub and Heatmiser App + + + + + + + + + + + + + Heatmiser (wireless) Window or Door Contact + + + + + The state of the contact (Off, On), (Read-Only) + + + + + ON if the device has a low battery + + + + + Heatmiser + NeoContact + + deviceNameInHub + + + + + Device Name that identifies the Contact in the NeoHub and Heatmiser App + + + + + + + + + + + + + Heatmiser (wireless) Temperature Sensor + + + + + Measured temperature value (Read-Only) + + + + + ON if the device has a low battery + + + + + Heatmiser + NeoTemperatureSensor + + deviceNameInHub + + + - Device Name that identifies the NeoPlugt device in the NeoHub and Heatmiser App + Device Name that identifies the Temperature Sensor in the NeoHub and Heatmiser App @@ -135,7 +207,7 @@ Measured temperature value (Read-Only) temperature - + @@ -143,8 +215,7 @@ Target temperature setting temperature - + @@ -152,7 +223,7 @@ Status of whether the thermostat is Off, or calling for Heat fire - + @@ -160,21 +231,29 @@ The Thermostat is in the Present Occupancy Mode (Off=Absent, On=Present) presence - + Switch The Plug is in Automatic Mode (Off=Manual, On=Automatic) - + Switch The state of the Plug switch, Off or On - + + + + + Switch + + The state of the contact, Off or On + window + diff --git a/bundles/org.openhab.binding.neohub/src/test/java/org/openhab/binding/neohub/test/NeoHubTestData.java b/bundles/org.openhab.binding.neohub/src/test/java/org/openhab/binding/neohub/test/NeoHubTestData.java index 8289838497e1d..85434f92272d0 100644 --- a/bundles/org.openhab.binding.neohub/src/test/java/org/openhab/binding/neohub/test/NeoHubTestData.java +++ b/bundles/org.openhab.binding.neohub/src/test/java/org/openhab/binding/neohub/test/NeoHubTestData.java @@ -12,9 +12,6 @@ */ package org.openhab.binding.neohub.test; -import org.openhab.binding.neohub.internal.NeoHubInfoResponse; -import org.openhab.binding.neohub.internal.NeoHubInfoResponse.DeviceInfo; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -23,68 +20,91 @@ import java.math.BigDecimal; +import org.eclipse.smarthome.core.library.unit.ImperialUnits; +import org.eclipse.smarthome.core.library.unit.SIUnits; import org.junit.Test; +import org.openhab.binding.neohub.internal.NeoHubInfoResponse; +import org.openhab.binding.neohub.internal.NeoHubInfoResponse.DeviceInfo; +import org.openhab.binding.neohub.internal.NeoHubReadDcbResponse; /** - * The {@link NeoHubTestData} class defines common constants, which are - * used across the whole binding. + * The {@link NeoHubTestData} class defines common constants, which are used + * across the whole binding. * * @author Andrew Fiddian-Green - Initial contribution */ public class NeoHubTestData { - public static final String NEOHUB_JSON_TEST_STRING = - "{\"devices\":[" + - - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":23,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"22.2\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"22.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"2:42\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Dining Room\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"22.6\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":23,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"24.0\",\"MIN_TEMPERATURE\":\"23.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"REMOTE_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":4,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Shower Room\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":26,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"23.3\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":16,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"25.0\",\"MIN_TEMPERATURE\":\"20.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"3:48\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Conservatory\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":28,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"22.6\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"24.0\",\"MIN_TEMPERATURE\":\"19.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"3:16\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":2,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":23,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"23.6\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"23.0\",\"MIN_TEMPERATURE\":\"20.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"2:08\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":6,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Kitchen\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":17,\"CURRENT_SET_TEMPERATURE\":\"20.0\",\"CURRENT_TEMPERATURE\":\"20.1\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"21.0\",\"MIN_TEMPERATURE\":\"20.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"7 days 00:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Hallway\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"10.0\",\"CURRENT_TEMPERATURE\":\"17.3\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":10,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"19.0\",\"MIN_TEMPERATURE\":\"16.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"7 days 08:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":5,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Shed\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":1,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_ON\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":11,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Plug South\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_ON\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":true,\"TIME_CLOCK_OVERIDE_BIT\":true,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":7,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Plug North\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":1,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":28,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Watering System\"}" + - - "]}"; - - public static final String NEOHUB_JSON_TEST_STRING_NEW_OFFLINE_JSON = - "{\"devices\":["+ - - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":21,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"24.0\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"24.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"3:24\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Dining Room\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"22.9\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":23,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"26.0\",\"MIN_TEMPERATURE\":\"23.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"REMOTE_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Shower Room\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":23,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"25.7\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":16,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"26.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Conservatory\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":27,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"25.7\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"26.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"3:24\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":19,\"CURRENT_SET_TEMPERATURE\":\"21.0\",\"CURRENT_TEMPERATURE\":\"23.0\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"24.0\",\"MIN_TEMPERATURE\":\"20.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Kitchen\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":19,\"CURRENT_SET_TEMPERATURE\":\"20.0\",\"CURRENT_TEMPERATURE\":\"21.7\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"23.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 22:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Hallway\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"9.0\",\"CURRENT_TEMPERATURE\":\"19.4\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":9,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"22.0\",\"MIN_TEMPERATURE\":\"15.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"4 days 08:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":5,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":1,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Shed Heating\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":1,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_ON\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":11,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room South\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_ON\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":true,\"TIME_CLOCK_OVERIDE_BIT\":true,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":192,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room North\"}," + - "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":1,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":57,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Green Wall Watering\"}" + - - "]}"; - + public static final String NEOHUB_JSON_TEST_STRING = "{\"devices\":[" + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":23,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"22.2\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"22.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"2:42\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Dining Room\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"22.6\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":23,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"24.0\",\"MIN_TEMPERATURE\":\"23.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"REMOTE_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":4,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Shower Room\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":26,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"23.3\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":16,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"25.0\",\"MIN_TEMPERATURE\":\"20.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"3:48\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Conservatory\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":28,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"22.6\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"24.0\",\"MIN_TEMPERATURE\":\"19.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"3:16\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":2,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":23,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"23.6\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"23.0\",\"MIN_TEMPERATURE\":\"20.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"6 days 23:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"2:08\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":6,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Kitchen\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":17,\"CURRENT_SET_TEMPERATURE\":\"20.0\",\"CURRENT_TEMPERATURE\":\"20.1\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"21.0\",\"MIN_TEMPERATURE\":\"20.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"7 days 00:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Hallway\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"10.0\",\"CURRENT_TEMPERATURE\":\"17.3\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":10,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"19.0\",\"MIN_TEMPERATURE\":\"16.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"7 days 08:00\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":5,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":20,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Shed\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":1,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_ON\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":11,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Plug South\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_ON\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":true,\"TIME_CLOCK_OVERIDE_BIT\":true,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":7,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Plug North\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":1,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":false,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":28,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Watering System\"}" + + "]}"; + + public static final String NEOHUB_JSON_TEST_STRING_NEW_OFFLINE_JSON = "{\"devices\":[" + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":21,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"24.0\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"24.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"3:24\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Dining Room\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"22.9\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":23,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"26.0\",\"MIN_TEMPERATURE\":\"23.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"REMOTE_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Shower Room\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":23,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"25.7\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":16,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"26.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Conservatory\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":27,\"CURRENT_SET_TEMPERATURE\":\"22.0\",\"CURRENT_TEMPERATURE\":\"25.7\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"26.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"3:24\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":19,\"CURRENT_SET_TEMPERATURE\":\"21.0\",\"CURRENT_TEMPERATURE\":\"23.0\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"24.0\",\"MIN_TEMPERATURE\":\"20.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 23:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Kitchen\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":19,\"CURRENT_SET_TEMPERATURE\":\"20.0\",\"CURRENT_TEMPERATURE\":\"21.7\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":21,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"23.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"3 days 22:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AND_FLOOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Hallway\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":23,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"9.0\",\"CURRENT_TEMPERATURE\":\"19.4\",\"DEMAND\":false,\"DEVICE_TYPE\":12,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":9,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"22.0\",\"MIN_TEMPERATURE\":\"15.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"4 days 08:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":5,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":24,\"WRITE_COUNT\":1,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Shed Heating\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":1,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_ON\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":11,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room South\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_ON\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":true,\"TIME_CLOCK_OVERIDE_BIT\":true,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":192,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room North\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":127,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"255.255\",\"DEMAND\":false,\"DEVICE_TYPE\":6,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":1,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"255.255\",\"MIN_TEMPERATURE\":\"255.255\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"24HOURSFIXED\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":79,\"WRITE_COUNT\":57,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Green Wall Watering\"}" + + "]}"; + + public static final String NEOHUB_JSON_TEST_STRING_READ_DCB_CELSIUS = "{\"AIR_ALT_DELAY\":60,\"AIR_ALT_DELAY_END\":6,\"AIR_ALT_DELAY_START\":23,\"ALT_TIMER_FORMAT\":1,\"AWAY\":false,\"BOOTTIME\":1587842223,\"CLOSE_DELAY\":null,\"COOLBOX\":\"heating\",\"COOLBOX_PRESENT\":0,\"CORF\":\"C\",\"DATE\":\"Apr 30\",\"DEVICE_ID\":\"NeoHub\",\"DSTAUTO\":true,\"DSTON\":true,\"EXTENDED_HISTORY\":\"off\",\"Firmware version\":2134,\"GDEVLIST\":[1,2,3,4,5,6,7,8,9,10],\"GLOBAL_SYSTEM_TYPE\":\"HeatOnly\",\"HEATING_LEVELS\":4,\"HEATORCOOL\":\"HEAT\",\"Homekit\":true,\"LAST_RECONNECT\":191959,\"LAST_RECONNECT_TIME\":1588034182,\"NTP\":\"Running\",\"OPEN_DELAY\":null,\"PARTITION COUNT\":\"4\",\"PROGFORMAT\":1,\"SET_GLOBAL_HC_MODE\":\"heating\",\"TIME\":\"16:24:35\",\"TIMEZONE\":0.0,\"UPTIME\":418052,\"ZIGBEE_CHANNEL\":\"15\"}"; + + public static final String NEOHUB_JSON_TEST_STRING_READ_DCB_FAHRENHEIT = "{\"AIR_ALT_DELAY\":60,\"AIR_ALT_DELAY_END\":6,\"AIR_ALT_DELAY_START\":23,\"ALT_TIMER_FORMAT\":1,\"AWAY\":false,\"BOOTTIME\":1587842223,\"CLOSE_DELAY\":null,\"COOLBOX\":\"heating\",\"COOLBOX_PRESENT\":0,\"CORF\":\"F\",\"DATE\":\"Apr 30\",\"DEVICE_ID\":\"NeoHub\",\"DSTAUTO\":true,\"DSTON\":true,\"EXTENDED_HISTORY\":\"off\",\"Firmware version\":2134,\"GDEVLIST\":[1,2,3,4,5,6,7,8,9,10],\"GLOBAL_SYSTEM_TYPE\":\"HeatOnly\",\"HEATING_LEVELS\":4,\"HEATORCOOL\":\"HEAT\",\"Homekit\":true,\"LAST_RECONNECT\":191959,\"LAST_RECONNECT_TIME\":1588034182,\"NTP\":\"Running\",\"OPEN_DELAY\":null,\"PARTITION COUNT\":\"4\",\"PROGFORMAT\":1,\"SET_GLOBAL_HC_MODE\":\"heating\",\"TIME\":\"16:24:35\",\"TIMEZONE\":0.0,\"UPTIME\":418052,\"ZIGBEE_CHANNEL\":\"15\"}"; + + public static final String NEOHUB_JSON_TEST_STRING_READ_DCB_CORF_MISSING = "{\"AIR_ALT_DELAY\":60,\"AIR_ALT_DELAY_END\":6,\"AIR_ALT_DELAY_START\":23,\"ALT_TIMER_FORMAT\":1,\"AWAY\":false,\"BOOTTIME\":1587842223,\"CLOSE_DELAY\":null,\"COOLBOX\":\"heating\",\"COOLBOX_PRESENT\":0,\"DATE\":\"Apr 30\",\"DEVICE_ID\":\"NeoHub\",\"DSTAUTO\":true,\"DSTON\":true,\"EXTENDED_HISTORY\":\"off\",\"Firmware version\":2134,\"GDEVLIST\":[1,2,3,4,5,6,7,8,9,10],\"GLOBAL_SYSTEM_TYPE\":\"HeatOnly\",\"HEATING_LEVELS\":4,\"HEATORCOOL\":\"HEAT\",\"Homekit\":true,\"LAST_RECONNECT\":191959,\"LAST_RECONNECT_TIME\":1588034182,\"NTP\":\"Running\",\"OPEN_DELAY\":null,\"PARTITION COUNT\":\"4\",\"PROGFORMAT\":1,\"SET_GLOBAL_HC_MODE\":\"heating\",\"TIME\":\"16:24:35\",\"TIMEZONE\":0.0,\"UPTIME\":418052,\"ZIGBEE_CHANNEL\":\"15\"}"; + + public static final String NEOHUB_JSON_TEST_STRING_READ_DCB_CORF_EMPTY = "{\"AIR_ALT_DELAY\":60,\"AIR_ALT_DELAY_END\":6,\"AIR_ALT_DELAY_START\":23,\"ALT_TIMER_FORMAT\":1,\"AWAY\":false,\"BOOTTIME\":1587842223,\"CLOSE_DELAY\":null,\"COOLBOX\":\"heating\",\"COOLBOX_PRESENT\":0,\"CORF\":\"\",\"DATE\":\"Apr 30\",\"DEVICE_ID\":\"NeoHub\",\"DSTAUTO\":true,\"DSTON\":true,\"EXTENDED_HISTORY\":\"off\",\"Firmware version\":2134,\"GDEVLIST\":[1,2,3,4,5,6,7,8,9,10],\"GLOBAL_SYSTEM_TYPE\":\"HeatOnly\",\"HEATING_LEVELS\":4,\"HEATORCOOL\":\"HEAT\",\"Homekit\":true,\"LAST_RECONNECT\":191959,\"LAST_RECONNECT_TIME\":1588034182,\"NTP\":\"Running\",\"OPEN_DELAY\":null,\"PARTITION COUNT\":\"4\",\"PROGFORMAT\":1,\"SET_GLOBAL_HC_MODE\":\"heating\",\"TIME\":\"16:24:35\",\"TIMEZONE\":0.0,\"UPTIME\":418052,\"ZIGBEE_CHANNEL\":\"15\"}"; + + public static final String NEOHUB_JSON_TEST_STRING_INFO_SENSORS_CLOSED = "{\"devices\":[" + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":20,\"CURRENT_SET_TEMPERATURE\":\"20.0\",\"CURRENT_TEMPERATURE\":\"19.8\",\"DEMAND\":false,\"DEVICE_TYPE\":1,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":12,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"20.0\",\"MIN_TEMPERATURE\":\"19.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"5 days 19:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"5:13\",\"PROGRAM_MODE\":\"5DAY/2DAY\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"FLOOR_SENSOR_ONLY\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":108,\"WRITE_COUNT\":89,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room Floor\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":0,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"19.5\",\"DEMAND\":false,\"DEVICE_TYPE\":14,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"0.0\",\"MIN_TEMPERATURE\":\"0.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"0 days 00:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"0:00\",\"PROGRAM_MODE\":\"NONPROGRAMMABLE\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":0,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":false,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Master Bedroom\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":22,\"CURRENT_SET_TEMPERATURE\":\"12.0\",\"CURRENT_TEMPERATURE\":\"21.5\",\"DEMAND\":false,\"DEVICE_TYPE\":1,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":12,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"1717\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"23.0\",\"MIN_TEMPERATURE\":\"22.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"5 days 23:55\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"5DAY/2DAY\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"FLOOR_SENSOR_ONLY\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":108,\"WRITE_COUNT\":26,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Bathroom Floor\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":22,\"CURRENT_SET_TEMPERATURE\":\"12.0\",\"CURRENT_TEMPERATURE\":\"21.6\",\"DEMAND\":false,\"DEVICE_TYPE\":1,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":24,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"23.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"5 days 22:30\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"1:02\",\"PROGRAM_MODE\":\"5DAY/2DAY\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"FLOOR_SENSOR_ONLY\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":108,\"WRITE_COUNT\":27,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Ensuite Floor\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":0,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"20.0\",\"DEMAND\":false,\"DEVICE_TYPE\":14,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"0.0\",\"MIN_TEMPERATURE\":\"0.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"0 days 00:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"0:00\",\"PROGRAM_MODE\":\"NONPROGRAMMABLE\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":0,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":false,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Nursery\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":0,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"0.0\",\"DEMAND\":false,\"DEVICE_TYPE\":5,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"0.0\",\"MIN_TEMPERATURE\":\"0.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"0 days 00:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"0:00\",\"PROGRAM_MODE\":\"NONPROGRAMMABLE\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":0,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":false,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Back Door\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":0,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"0.0\",\"DEMAND\":false,\"DEVICE_TYPE\":5,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"0.0\",\"MIN_TEMPERATURE\":\"0.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"0 days 00:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"0:00\",\"PROGRAM_MODE\":\"NONPROGRAMMABLE\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":0,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":false,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Nursery Window\"}" + + "]}"; + + public static final String NEOHUB_JSON_TEST_STRING_INFO_SENSORS_OPEN = "{\"devices\":[" + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":20,\"CURRENT_SET_TEMPERATURE\":\"7.0\",\"CURRENT_TEMPERATURE\":\"19.8\",\"DEMAND\":false,\"DEVICE_TYPE\":1,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":12,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"20.0\",\"MIN_TEMPERATURE\":\"19.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"255 days 255:255\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"5:13\",\"PROGRAM_MODE\":\"5DAY/2DAY\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"FLOOR_SENSOR_ONLY\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":true,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":108,\"WRITE_COUNT\":90,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Living Room Floor\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":0,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"19.5\",\"DEMAND\":false,\"DEVICE_TYPE\":14,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"0.0\",\"MIN_TEMPERATURE\":\"0.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"0 days 00:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"0:00\",\"PROGRAM_MODE\":\"NONPROGRAMMABLE\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":0,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":false,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Master Bedroom\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":22,\"CURRENT_SET_TEMPERATURE\":\"12.0\",\"CURRENT_TEMPERATURE\":\"21.6\",\"DEMAND\":false,\"DEVICE_TYPE\":1,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":12,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"1717\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"23.0\",\"MIN_TEMPERATURE\":\"22.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"5 days 23:55\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"255:255\",\"PROGRAM_MODE\":\"5DAY/2DAY\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"FLOOR_SENSOR_ONLY\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":108,\"WRITE_COUNT\":26,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Bathroom Floor\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":22,\"CURRENT_SET_TEMPERATURE\":\"12.0\",\"CURRENT_TEMPERATURE\":\"21.6\",\"DEMAND\":false,\"DEVICE_TYPE\":1,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":24,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"23.0\",\"MIN_TEMPERATURE\":\"21.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"5 days 22:30\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"1:02\",\"PROGRAM_MODE\":\"5DAY/2DAY\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"FLOOR_SENSOR_ONLY\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":108,\"WRITE_COUNT\":27,\"ZONE_1PAIRED_TO_MULTILINK\":true,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Ensuite Floor\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":false,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":0,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"20.0\",\"DEMAND\":false,\"DEVICE_TYPE\":14,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":false,\"MAX_TEMPERATURE\":\"0.0\",\"MIN_TEMPERATURE\":\"0.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"0 days 00:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"0:00\",\"PROGRAM_MODE\":\"NONPROGRAMMABLE\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"THERMOSTAT\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":0,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":false,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Nursery\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":true,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":0,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"0.0\",\"DEMAND\":false,\"DEVICE_TYPE\":5,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":true,\"MAX_TEMPERATURE\":\"0.0\",\"MIN_TEMPERATURE\":\"0.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"0 days 00:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"0:00\",\"PROGRAM_MODE\":\"NONPROGRAMMABLE\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":0,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":false,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Back Door\"}," + + "{\"AWAY\":false,\"COOLING\":false,\"COOLING_ENABLED\":false,\"COOLING_TEMPERATURE_IN_WHOLE_DEGREES\":0,\"COOL_INP\":true,\"COUNT_DOWN_TIME\":\"0:00\",\"CRADLE_PAIRED_TO_REMOTE_SENSOR\":false,\"CRADLE_PAIRED_TO_STAT\":false,\"CURRENT_FLOOR_TEMPERATURE\":0,\"CURRENT_SET_TEMPERATURE\":\"0.0\",\"CURRENT_TEMPERATURE\":\"0.0\",\"DEMAND\":false,\"DEVICE_TYPE\":5,\"ENABLE_BOILER\":false,\"ENABLE_COOLING\":false,\"ENABLE_PUMP\":false,\"ENABLE_VALVE\":false,\"ENABLE_ZONE\":false,\"FAILSAFE_STATE\":false,\"FAIL_SAFE_ENABLED\":false,\"FLOOR_LIMIT\":false,\"FULL/PARTIAL_LOCK_AVAILABLE\":false,\"HEAT/COOL_MODE\":false,\"HEATING\":false,\"HOLD_TEMPERATURE\":0,\"HOLD_TIME\":\"0:00\",\"HOLIDAY\":false,\"HOLIDAY_DAYS\":0,\"HUMIDITY\":0,\"LOCK\":false,\"LOCK_PIN_NUMBER\":\"0000\",\"LOW_BATTERY\":true,\"MAX_TEMPERATURE\":\"0.0\",\"MIN_TEMPERATURE\":\"0.0\",\"MODULATION_LEVEL\":0,\"NEXT_ON_TIME\":\"0 days 00:00\",\"OFFLINE\":0,\"OUPUT_DELAY\":false,\"OUTPUT_DELAY\":0,\"PREHEAT\":false,\"PREHEAT_TIME\":\"0:00\",\"PROGRAM_MODE\":\"NONPROGRAMMABLE\",\"PUMP_DELAY\":false,\"RADIATORS_OR_UNDERFLOOR\":false,\"SENSOR_SELECTION\":\"BUILT_IN_AIR_SENSOR\",\"SET_COUNTDOWN_TIME\":0,\"STANDBY\":false,\"STAT_MODE\":{\"4_HEAT_LEVELS\":true,\"MANUAL_OFF\":true,\"TIMECLOCK\":true},\"TEMPERATURE_FORMAT\":false,\"TEMP_HOLD\":false,\"TIMECLOCK_MODE\":false,\"TIMER\":false,\"TIME_CLOCK_OVERIDE_BIT\":false,\"ULTRA_VERSION\":0,\"VERSION_NUMBER\":0,\"WRITE_COUNT\":0,\"ZONE_1PAIRED_TO_MULTILINK\":false,\"ZONE_1_OR_2\":false,\"ZONE_2_PAIRED_TO_MULTILINK\":false,\"device\":\"Nursery Window\"}]}"; + @Test public void test() { // info response (old JSON format) - NeoHubInfoResponse infoResponse = NeoHubInfoResponse.createInfoResponse(NEOHUB_JSON_TEST_STRING); + NeoHubInfoResponse infoResponse = NeoHubInfoResponse.createInfoResponse(NEOHUB_JSON_TEST_STRING); assertNotNull(infoResponse); // missing device DeviceInfo device = infoResponse.getDeviceInfo("Aardvark"); assertNull(device); - // existing device + // existing type 12 thermostat device device = infoResponse.getDeviceInfo("Dining Room"); assertNotNull(device); assertEquals("Dining Room", device.getDeviceName()); assertEquals(new BigDecimal("22.0"), device.getTargetTemperature()); assertEquals(new BigDecimal("22.2"), device.getRoomTemperature()); assertEquals(new BigDecimal("23"), device.getFloorTemperature()); - assertFalse(device.isAway()); - assertFalse(device.isHoliday()); - assertEquals(new BigDecimal("0"), device.getHolidayDays()); assertEquals(new BigDecimal("12"), device.getDeviceType()); assertFalse(device.isStandby()); assertFalse(device.isHeating()); @@ -93,10 +113,35 @@ public void test() { assertFalse(device.isOffline()); assertFalse(device.stateManual()); assertTrue(device.stateAuto()); - assertTrue(device.hasStatMode()); + assertFalse(device.isCoolInputOn()); + assertFalse(device.isBatteryLow()); + + // existing type 6 plug device (MANUAL OFF) + device = infoResponse.getDeviceInfo("Plug South"); + assertNotNull(device); + assertEquals("Plug South", device.getDeviceName()); + assertEquals(new BigDecimal("6"), device.getDeviceType()); + assertFalse(device.isTimerOn()); + assertTrue(device.stateManual()); + + // existing type 6 plug device (MANUAL ON) + device = infoResponse.getDeviceInfo("Plug North"); + assertNotNull(device); + assertEquals("Plug North", device.getDeviceName()); + assertEquals(new BigDecimal("6"), device.getDeviceType()); + assertTrue(device.isTimerOn()); + assertTrue(device.stateManual()); + + // existing type 6 plug device (AUTO OFF) + device = infoResponse.getDeviceInfo("Watering System"); + assertNotNull(device); + assertEquals("Watering System", device.getDeviceName()); + assertEquals(new BigDecimal("6"), device.getDeviceType()); + assertFalse(device.isTimerOn()); + assertFalse(device.stateManual()); // info response (new JSON format) - infoResponse = NeoHubInfoResponse.createInfoResponse(NEOHUB_JSON_TEST_STRING_NEW_OFFLINE_JSON); + infoResponse = NeoHubInfoResponse.createInfoResponse(NEOHUB_JSON_TEST_STRING_NEW_OFFLINE_JSON); assertNotNull(infoResponse); // existing device (new JSON format) @@ -104,7 +149,65 @@ public void test() { assertNotNull(device); assertEquals("Dining Room", device.getDeviceName()); assertFalse(device.isOffline()); + assertFalse(device.isCoolInputOn()); - } + // READ_DCB valid CORF C response + NeoHubReadDcbResponse dcbResponse = NeoHubReadDcbResponse + .createReadDcbResponse(NEOHUB_JSON_TEST_STRING_READ_DCB_CELSIUS); + assertNotNull(dcbResponse); + assertEquals(SIUnits.CELSIUS, dcbResponse.getTemperatureUnit()); + + // READ_DCB valid CORF F response + dcbResponse = NeoHubReadDcbResponse.createReadDcbResponse(NEOHUB_JSON_TEST_STRING_READ_DCB_FAHRENHEIT); + assertNotNull(dcbResponse); + assertEquals(ImperialUnits.FAHRENHEIT, dcbResponse.getTemperatureUnit()); + // READ_DCB missing CORF element + dcbResponse = NeoHubReadDcbResponse.createReadDcbResponse(NEOHUB_JSON_TEST_STRING_READ_DCB_CORF_MISSING); + assertNotNull(dcbResponse); + assertEquals(SIUnits.CELSIUS, dcbResponse.getTemperatureUnit()); + + // READ_DCB CORF element is an empty string + dcbResponse = NeoHubReadDcbResponse.createReadDcbResponse(NEOHUB_JSON_TEST_STRING_READ_DCB_CORF_EMPTY); + assertNotNull(dcbResponse); + assertEquals(SIUnits.CELSIUS, dcbResponse.getTemperatureUnit()); + + // info response (with sensors CLOSED) + infoResponse = NeoHubInfoResponse.createInfoResponse(NEOHUB_JSON_TEST_STRING_INFO_SENSORS_CLOSED); + assertNotNull(infoResponse); + + // existing contact device type 5 (CLOSED) + device = infoResponse.getDeviceInfo("Back Door"); + assertNotNull(device); + assertEquals("Back Door", device.getDeviceName()); + assertEquals(new BigDecimal("5"), device.getDeviceType()); + assertFalse(device.isCoolInputOn()); + assertFalse(device.isBatteryLow()); + + // existing temperature sensor type 14 + device = infoResponse.getDeviceInfo("Master Bedroom"); + assertNotNull(device); + assertEquals("Master Bedroom", device.getDeviceName()); + assertEquals(new BigDecimal("14"), device.getDeviceType()); + assertEquals(new BigDecimal("19.5"), device.getRoomTemperature()); + + // existing thermostat type 1 + device = infoResponse.getDeviceInfo("Living Room Floor"); + assertNotNull(device); + assertEquals("Living Room Floor", device.getDeviceName()); + assertEquals(new BigDecimal("1"), device.getDeviceType()); + assertEquals(new BigDecimal("19.8"), device.getRoomTemperature()); + + // info response (with sensors OPEN) + infoResponse = NeoHubInfoResponse.createInfoResponse(NEOHUB_JSON_TEST_STRING_INFO_SENSORS_OPEN); + assertNotNull(infoResponse); + + // existing contact device type 5 (OPEN) + device = infoResponse.getDeviceInfo("Back Door"); + assertNotNull(device); + assertEquals("Back Door", device.getDeviceName()); + assertEquals(new BigDecimal("5"), device.getDeviceType()); + assertTrue(device.isCoolInputOn()); + assertTrue(device.isBatteryLow()); + } } diff --git a/bundles/org.openhab.binding.nest/pom.xml b/bundles/org.openhab.binding.nest/pom.xml index e2178c90fffff..b5c7c6e4a6f49 100644 --- a/bundles/org.openhab.binding.nest/pom.xml +++ b/bundles/org.openhab.binding.nest/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.nest diff --git a/bundles/org.openhab.binding.nest/src/main/feature/feature.xml b/bundles/org.openhab.binding.nest/src/main/feature/feature.xml index dbb5872b15a80..4da2a00a8dc2b 100644 --- a/bundles/org.openhab.binding.nest/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.nest/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.nest/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.nest/${project.version} + diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/NestUtils.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/NestUtils.java index fd0d4f4005244..e3bca80e52e02 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/NestUtils.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/NestUtils.java @@ -46,5 +46,4 @@ public static T fromJson(Reader reader, Class dataClass) { public static String toJson(Object object) { return GSON.toJson(object); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/AccessTokenData.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/AccessTokenData.java index 78331284dcc7b..fd8eee8586b52 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/AccessTokenData.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/AccessTokenData.java @@ -76,5 +76,4 @@ public String toString() { .append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ActivityZone.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ActivityZone.java index a1ac682559f30..c9cb050ee7444 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ActivityZone.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ActivityZone.java @@ -71,5 +71,4 @@ public String toString() { builder.append("CameraActivityZone [name=").append(name).append(", id=").append(id).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/BaseNestDevice.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/BaseNestDevice.java index 5f6ae14085064..f5853f83be54f 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/BaseNestDevice.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/BaseNestDevice.java @@ -164,5 +164,4 @@ public String toString() { .append(", structureId=").append(structureId).append(", whereId=").append(whereId).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Camera.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Camera.java index ad2e3ed0addc7..90093a1db6367 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Camera.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Camera.java @@ -206,5 +206,4 @@ public String toString() { .append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/CameraEvent.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/CameraEvent.java index 230d0a6600236..e9795fd4c5018 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/CameraEvent.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/CameraEvent.java @@ -200,5 +200,4 @@ public String toString() { .append(animatedImageUrl).append(", activityZoneIds=").append(activityZoneIds).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ETA.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ETA.java index 48cbddf4e78e4..719f963002b5e 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ETA.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ETA.java @@ -105,5 +105,4 @@ public String toString() { .append(estimatedArrivalWindowEnd).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ErrorData.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ErrorData.java index 8cc5269d71894..808553c15cf5f 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ErrorData.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/ErrorData.java @@ -103,5 +103,4 @@ public String toString() { .append(message).append(", instance=").append(instance).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/NestDevices.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/NestDevices.java index 7332cb601001e..63506964140e2 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/NestDevices.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/NestDevices.java @@ -93,5 +93,4 @@ public String toString() { .append(", cameras=").append(cameras).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/NestMetadata.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/NestMetadata.java index 15477bfabae25..e0da860af1cc8 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/NestMetadata.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/NestMetadata.java @@ -76,5 +76,4 @@ public String toString() { .append(clientVersion).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/SmokeDetector.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/SmokeDetector.java index e94ea6e911e7c..2011a0c9d61d1 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/SmokeDetector.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/SmokeDetector.java @@ -150,5 +150,4 @@ public String toString() { .append(getStructureId()).append(", getWhereId()=").append(getWhereId()).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Structure.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Structure.java index 655b57b709e84..2d61fb285e39a 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Structure.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Structure.java @@ -308,5 +308,4 @@ public String toString() { .append(wwnSecurityState).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Thermostat.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Thermostat.java index 99d35dbfaa2ff..ce781af2a911d 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Thermostat.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/Thermostat.java @@ -569,5 +569,4 @@ public String toString() { .append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/TopLevelData.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/TopLevelData.java index 96fe541b831e8..93be10f94ccfe 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/TopLevelData.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/TopLevelData.java @@ -91,5 +91,4 @@ public String toString() { .append(", structures=").append(structures).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/TopLevelStreamingData.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/TopLevelStreamingData.java index bdfb9410ec5bd..740518161dd47 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/TopLevelStreamingData.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/data/TopLevelStreamingData.java @@ -76,5 +76,4 @@ public String toString() { builder.append("TopLevelStreamingData [path=").append(path).append(", data=").append(data).append("]"); return builder.toString(); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestBaseHandler.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestBaseHandler.java index dcb27abc3bada..bde5b2d65d46c 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestBaseHandler.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestBaseHandler.java @@ -200,5 +200,4 @@ public void onMissingData(String nestId) { } protected abstract void update(T oldData, T data); - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestBridgeHandler.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestBridgeHandler.java index 480685cedd018..6d131491f8c38 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestBridgeHandler.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestBridgeHandler.java @@ -373,5 +373,4 @@ private void transmitQueue() { } } } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestSmokeDetectorHandler.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestSmokeDetectorHandler.java index 848d856b180a4..b401624b61b4a 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestSmokeDetectorHandler.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestSmokeDetectorHandler.java @@ -92,5 +92,4 @@ protected void update(SmokeDetector oldSmokeDetector, SmokeDetector smokeDetecto updateStatus(newStatus); } } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestStructureHandler.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestStructureHandler.java index 5e9d845df2c56..4c46993d35150 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestStructureHandler.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestStructureHandler.java @@ -125,5 +125,4 @@ protected void update(Structure oldStructure, Structure structure) { updateStatus(ThingStatus.ONLINE); } } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestThermostatHandler.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestThermostatHandler.java index 4ecde558cea0e..1b959467cefd7 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestThermostatHandler.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/handler/NestThermostatHandler.java @@ -216,5 +216,4 @@ protected void update(Thermostat oldThermostat, Thermostat thermostat) { updateStatus(newStatus); } } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/listener/NestThingDataListener.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/listener/NestThingDataListener.java index a080232fdb370..04963553c2cdc 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/listener/NestThingDataListener.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/listener/NestThingDataListener.java @@ -43,5 +43,4 @@ public interface NestThingDataListener { * @param nestId identifies the Nest thing */ void onMissingData(String nestId); - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/rest/NestAuthorizer.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/rest/NestAuthorizer.java index 8f804ee924b7e..303893dfe7cc6 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/rest/NestAuthorizer.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/rest/NestAuthorizer.java @@ -86,5 +86,4 @@ public String getNewAccessToken() throws InvalidAccessTokenException { throw new InvalidAccessTokenException("Access token request failed", e); } } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/rest/NestStreamingRestClient.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/rest/NestStreamingRestClient.java index e5397fea46e0a..8cbf57addb8cc 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/rest/NestStreamingRestClient.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/rest/NestStreamingRestClient.java @@ -223,5 +223,4 @@ private void onEvent(InboundEvent inboundEvent) { logger.warn("An exception occurred while processing the inbound event", e); } } - } diff --git a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/update/NestCompositeUpdateHandler.java b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/update/NestCompositeUpdateHandler.java index 823703703480d..ad48942547cd3 100644 --- a/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/update/NestCompositeUpdateHandler.java +++ b/bundles/org.openhab.binding.nest/src/main/java/org/openhab/binding/nest/internal/update/NestCompositeUpdateHandler.java @@ -126,5 +126,4 @@ public void resendLastUpdates() { } }); } - } diff --git a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/binding/binding.xml index 899abcf34bbd4..279bc6b8808bb 100644 --- a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Nest Binding Nest connects to the Nest cloud and allows control of the various Nest devices. diff --git a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/config/config.xml index 03aa678a809a7..21c880e10fbae 100644 --- a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - @@ -26,14 +27,16 @@ The single use pincode for obtaining an OAuth access token. - Get the pincode by accepting to the terms shown at the product authorization URL. - This value is automatically reset when the access token has been obtained + Get the pincode by accepting to the terms + shown at the product authorization URL. + This value is automatically reset when the access token has been obtained The access token used for authenticating to the Nest API. - It is automatically obtained from Nest when the value is empty and - a valid pincode parameter is entered + It is automatically obtained from Nest when the + value is empty and + a valid pincode parameter is entered true diff --git a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/bridge.xml index d397eb5a39b4c..60e6e60450793 100644 --- a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,11 +1,12 @@ - An account for using the Nest REST API - + diff --git a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/camera.xml b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/camera.xml index 9d9ce6fc9a6b7..67c11800114a2 100644 --- a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/camera.xml +++ b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/camera.xml @@ -1,18 +1,19 @@ - - + A Nest Cam registered with your account - + Information about the last camera event (requires Nest Aware subscription) @@ -25,6 +26,6 @@ deviceId - + diff --git a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/channels.xml index 9b4250a816110..b3d0346ddcbbc 100644 --- a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/channels.xml @@ -1,13 +1,15 @@ - + DateTime Timestamp of the last successful interaction with Nest - + @@ -45,14 +47,14 @@ DateTime Peak period start for the Rush Hour Rewards program - + DateTime Peak period end for the Rush Hour Rewards program - + @@ -68,7 +70,7 @@ Switch If rush hour rewards system is enabled or not - + @@ -88,15 +90,15 @@ Information about the camera - - - - - - - - - + + + + + + + + + @@ -152,102 +154,102 @@ DateTime Timestamp of the last online status change - + Information about the camera event - - - - - - - - - - - + + + + + + + + + + + - + Switch If sound was detected in the camera event - + Switch If motion was detected in the camera event - + Switch If a person was detected in the camera event - + DateTime Timestamp when the camera event started - + DateTime Timestamp when the camera event ended - + DateTime Timestamp when the camera event URLs expire - + String The web URL for the camera event, allows you to see the camera event in a web page - + String The app URL for the camera event, allows you to see the camera event in an app - + String The URL showing an image for the camera event - + String The URL showing an animated image for the camera event - + String Identifiers for activity zones that detected the event (comma separated) - + @@ -295,14 +297,14 @@ Switch If the manual test is currently active - + DateTime Timestamp of the last successful manual test - + @@ -311,7 +313,7 @@ Current temperature Temperature - + @@ -319,7 +321,7 @@ The set point temperature Temperature - + @@ -327,7 +329,7 @@ The max set point temperature Temperature - + @@ -335,7 +337,7 @@ The min set point temperature Temperature - + @@ -343,7 +345,7 @@ The eco range max set point temperature Temperature - + @@ -351,7 +353,7 @@ The eco range min set point temperature Temperature - + @@ -359,7 +361,7 @@ The locked range max set point temperature Temperature - + @@ -367,14 +369,14 @@ The locked range min set point temperature Temperature - + Switch If the thermostat has the temperature locked to only be within a set range - + @@ -425,35 +427,35 @@ Indicates the current relative humidity Humidity - + Number:Time Time left to the target temperature approximately - + Switch If the thermostat can actually turn on heating - + Switch If the thermostat can actually turn on cooling - + Switch If the fan timer is engaged - + @@ -478,41 +480,41 @@ DateTime Timestamp when the fan stops running - + Switch If the thermostat can control the fan - + Switch If the thermostat is currently in a leaf mode - + Switch If sunlight correction is enabled - + Switch If sunlight correction is active - + Switch If the system is currently using emergency heat - + diff --git a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/smoke-detector.xml b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/smoke-detector.xml index 3b1c430302d5e..d1fc874898931 100644 --- a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/smoke-detector.xml +++ b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/smoke-detector.xml @@ -1,24 +1,25 @@ - - + The smoke detector/Nest Protect for the account - - - - - - - + + + + + + + @@ -27,6 +28,6 @@ deviceId - + diff --git a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/structure.xml b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/structure.xml index 449e420218962..242ea0c316f01 100644 --- a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/structure.xml +++ b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/structure.xml @@ -1,29 +1,31 @@ - - + The Nest structure defines the house the account has setup on Nest. - You will only have more than one structure if you have more than one house + You will only have more than one + structure if you have more than one house - - - - - - - - - - - + + + + + + + + + + + @@ -32,7 +34,7 @@ structureId - + diff --git a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/thermostat.xml b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/thermostat.xml index f040c547c74a0..816e2b3591591 100644 --- a/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/thermostat.xml +++ b/bundles/org.openhab.binding.nest/src/main/resources/ESH-INF/thing/thermostat.xml @@ -1,42 +1,43 @@ - - + A Thermostat to control the various aspects of the house's HVAC system - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -45,6 +46,6 @@ deviceId - + diff --git a/bundles/org.openhab.binding.netatmo/README.md b/bundles/org.openhab.binding.netatmo/README.md index 9c85d3c664680..f4e26dc70f019 100644 --- a/bundles/org.openhab.binding.netatmo/README.md +++ b/bundles/org.openhab.binding.netatmo/README.md @@ -4,7 +4,8 @@ The Netatmo binding integrates the following Netatmo products: - *Personal Weather Station*. Reports temperature, humidity, air pressure, carbon dioxide concentration in the air, as well as the ambient noise level. - *Thermostat*. Reports ambient temperature, allow to check target temperature, consult and change furnace heating status. -- *Welcome Camera*. Reports last event and persons at home, consult picture and video from event/camera. +- *Indoor Camera / Welcome*. Reports last event and persons at home, consult picture and video from event/camera. +- *Outdoor Camera / Presence*. Consult picture and video from camera. The last event is also available, but without content yet, this will get enhanced later. See http://www.netatmo.com/ for details on their product. @@ -33,7 +34,7 @@ Once you will get needed informations from the Netatmo API, you will be able to E.g. ``` -Bridge netatmo:netatmoapi:home [ clientId="", clientSecret="", username = "", password = "", readStation=true|false, readHealthyHomeCoach=true|false, readThermostat=true|false, readWelcome=true|false] { +Bridge netatmo:netatmoapi:home [ clientId="", clientSecret="", username = "", password = "", readStation=true|false, readHealthyHomeCoach=true|false, readThermostat=true|false, readWelcome=true|false, readPresence=true|false] { Thing NAMain inside [ id="aa:aa:aa:aa:aa:aa" ] Thing NAModule1 outside [ id="yy:yy:yy:yy:yy:yy", parentId="aa:aa:aa:aa:aa:aa" ] Thing NHC homecoach [ id="cc:cc:cc:cc:cc:cc", [refreshInterval=60000] ] @@ -469,9 +470,14 @@ All these channels except Sp_Temperature, SetpointMode and Planning are read onl All these channels are read only. -### Welcome Camera +### Welcome and Presence Camera -**Supported channels for the Camera thing:** +All these channels are read only. + +Warning : the URL of the live snapshot is a fixed URL so the value of the channel cameraLivePictureUrl / welcomeCameraLivePictureUrl will never be updated once first set by the binding. +So to get a refreshed picture, you need to use the refresh parameter in your sitemap image element. + +**Supported channels for the Welcome Camera thing:** | Channel ID | Item Type | Description | |-----------------------------|-----------|----------------------------------------------------------| @@ -483,10 +489,17 @@ All these channels are read only. | welcomeCameraLivePictureUrl | String | Url of the live snapshot for this camera | | welcomeCameraLiveStreamUrl | String | Url of the live stream for this camera | -All these channels are read only. +**Supported channels for the Presence Camera thing:** -Warning : the URL of the live snapshot is a fixed URL so the value of the channel welcomeCameraLivePictureUrl will never be updated once first set by the binding. -So to get a refreshed picture, you need to use the refresh parameter in your sitemap image element. +| Channel ID | Item Type | Description | +|-----------------------------|-----------|----------------------------------------------------------| +| cameraStatus | Switch | State of the camera | +| cameraSdStatus | Switch | State of the SD card | +| cameraAlimStatus | Switch | State of the power connector | +| cameraIsLocal | Switch | indicates whether the camera is on the same network than the openHAB Netatmo Binding | +| cameraLivePicture | Image | Camera Live Snapshot | +| cameraLivePictureUrl | String | Url of the live snapshot for this camera | +| cameraLiveStreamUrl | String | Url of the live stream for this camera | ### Welcome Person diff --git a/bundles/org.openhab.binding.netatmo/pom.xml b/bundles/org.openhab.binding.netatmo/pom.xml index e4687c20d49db..01c22b5381bd8 100644 --- a/bundles/org.openhab.binding.netatmo/pom.xml +++ b/bundles/org.openhab.binding.netatmo/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.netatmo diff --git a/bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml b/bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml index 3a31036556a62..fb52bfe4e9a58 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/feature/feature.xml @@ -1,15 +1,15 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.osgiify/org.json.json/20131018 - mvn:org.openhab.osgiify/com.squareup.okhttp.okhttp/2.3.0 - mvn:org.openhab.osgiify/com.squareup.okio.okio-1.3.0/1.3.0 - mvn:org.openhab.osgiify/com.squareup.retrofit.retrofit/1.9.0 - mvn:org.apache.oltu.oauth2/org.apache.oltu.oauth2.client/1.0.0 - mvn:org.apache.oltu.oauth2/org.apache.oltu.oauth2.common/1.0.0 - mvn:org.openhab.addons.bundles/org.openhab.binding.netatmo/${project.version} - + + openhab-runtime-base + mvn:org.openhab.osgiify/org.json.json/20131018 + mvn:org.openhab.osgiify/com.squareup.okhttp.okhttp/2.3.0 + mvn:org.openhab.osgiify/com.squareup.okio.okio-1.3.0/1.3.0 + mvn:org.openhab.osgiify/com.squareup.retrofit.retrofit/1.9.0 + mvn:org.apache.oltu.oauth2/org.apache.oltu.oauth2.client/1.0.0 + mvn:org.apache.oltu.oauth2/org.apache.oltu.oauth2.common/1.0.0 + mvn:org.openhab.addons.bundles/org.openhab.binding.netatmo/${project.version} + diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/ChannelTypeUtils.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/ChannelTypeUtils.java index b27d6e3554365..3217ce919279a 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/ChannelTypeUtils.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/ChannelTypeUtils.java @@ -93,7 +93,11 @@ public static State toOnOffType(@Nullable String yesno) { } public static State toOnOffType(@Nullable Integer value) { - return value != null ? (value == 1 ? OnOffType.ON : OnOffType.OFF) : UnDefType.NULL; + return value != null ? (value == 1 ? OnOffType.ON : OnOffType.OFF) : UnDefType.UNDEF; + } + + public static State toOnOffType(@Nullable Boolean value) { + return value != null ? (value ? OnOffType.ON : OnOffType.OFF) : UnDefType.UNDEF; } public static State toQuantityType(@Nullable Float value, Unit unit) { diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java index 7c31dbe87c36d..dd2b5cd76ca94 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoBindingConstants.java @@ -95,6 +95,8 @@ public class NetatmoBindingConstants { public static final ThingTypeUID WELCOME_HOME_THING_TYPE = new ThingTypeUID(BINDING_ID, "NAWelcomeHome"); public static final ThingTypeUID WELCOME_CAMERA_THING_TYPE = new ThingTypeUID(BINDING_ID, "NACamera"); public static final ThingTypeUID WELCOME_PERSON_THING_TYPE = new ThingTypeUID(BINDING_ID, "NAWelcomePerson"); + // Presence camera + public static final ThingTypeUID PRESENCE_CAMERA_THING_TYPE = new ThingTypeUID(BINDING_ID, "NOC"); // Weather Station Channel ids public static final String CHANNEL_TEMPERATURE = "Temperature"; @@ -254,6 +256,15 @@ public class NetatmoBindingConstants { public static final String CHANNEL_WELCOME_EVENT_MESSAGE = "welcomeEventMessage"; public static final String CHANNEL_WELCOME_EVENT_SUBTYPE = "welcomeEventSubType"; + // Camera specific channels + public static final String CHANNEL_CAMERA_STATUS = "cameraStatus"; + public static final String CHANNEL_CAMERA_SDSTATUS = "cameraSdStatus"; + public static final String CHANNEL_CAMERA_ALIMSTATUS = "cameraAlimStatus"; + public static final String CHANNEL_CAMERA_ISLOCAL = "cameraIsLocal"; + public static final String CHANNEL_CAMERA_LIVEPICTURE = "cameraLivePicture"; + public static final String CHANNEL_CAMERA_LIVEPICTURE_URL = "cameraLivePictureUrl"; + public static final String CHANNEL_CAMERA_LIVESTREAM_URL = "cameraLiveStreamUrl"; + public static final String WELCOME_PICTURE_URL = "https://api.netatmo.com/api/getcamerapicture"; public static final String WELCOME_PICTURE_IMAGEID = "image_id"; public static final String WELCOME_PICTURE_KEY = "key"; @@ -262,7 +273,7 @@ public class NetatmoBindingConstants { public static final Set SUPPORTED_DEVICE_THING_TYPES_UIDS = Stream .of(MAIN_THING_TYPE, MODULE1_THING_TYPE, MODULE2_THING_TYPE, MODULE3_THING_TYPE, MODULE4_THING_TYPE, HOMECOACH_THING_TYPE, PLUG_THING_TYPE, THERM1_THING_TYPE, WELCOME_HOME_THING_TYPE, - WELCOME_CAMERA_THING_TYPE, WELCOME_PERSON_THING_TYPE) + WELCOME_CAMERA_THING_TYPE, WELCOME_PERSON_THING_TYPE, PRESENCE_CAMERA_THING_TYPE) .collect(Collectors.toSet()); // List of all adressable things in OH = SUPPORTED_DEVICE_THING_TYPES_UIDS + the virtual bridge @@ -285,5 +296,4 @@ public class NetatmoBindingConstants { .collect(Collectors.toSet()); public static final Set PRESENCE_EVENTS = Stream .of(EventTypeEnum.OUTDOOR, EventTypeEnum.ALIM, EventTypeEnum.DAILY_SUMMARY).collect(Collectors.toSet()); - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java index a377b546e7e87..870f6a83ab142 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/NetatmoHandlerFactory.java @@ -20,7 +20,8 @@ import javax.servlet.http.HttpServlet; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; @@ -44,6 +45,7 @@ import org.openhab.binding.netatmo.internal.welcome.NAWelcomeHomeHandler; import org.openhab.binding.netatmo.internal.welcome.NAWelcomePersonHandler; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.http.HttpService; @@ -56,14 +58,21 @@ * * @author Gaël L'hopital - Initial contribution */ - +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.netatmo") public class NetatmoHandlerFactory extends BaseThingHandlerFactory { - private Logger logger = LoggerFactory.getLogger(NetatmoHandlerFactory.class); - private Map> discoveryServiceRegs = new HashMap<>(); - private Map> webHookServiceRegs = new HashMap<>(); - private HttpService httpService; - private NATherm1StateDescriptionProvider stateDescriptionProvider; + private final Logger logger = LoggerFactory.getLogger(NetatmoHandlerFactory.class); + private final Map> discoveryServiceRegs = new HashMap<>(); + private final Map> webHookServiceRegs = new HashMap<>(); + private final HttpService httpService; + private final NATherm1StateDescriptionProvider stateDescriptionProvider; + + @Activate + public NetatmoHandlerFactory(final @Reference HttpService httpService, + final @Reference NATherm1StateDescriptionProvider stateDescriptionProvider) { + this.httpService = httpService; + this.stateDescriptionProvider = stateDescriptionProvider; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -71,7 +80,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(APIBRIDGE_THING_TYPE)) { WelcomeWebHookServlet servlet = registerWebHookServlet(thing.getUID()); @@ -96,7 +105,7 @@ protected ThingHandler createHandler(Thing thing) { return new NATherm1Handler(thing, stateDescriptionProvider); } else if (thingTypeUID.equals(WELCOME_HOME_THING_TYPE)) { return new NAWelcomeHomeHandler(thing); - } else if (thingTypeUID.equals(WELCOME_CAMERA_THING_TYPE)) { + } else if (thingTypeUID.equals(WELCOME_CAMERA_THING_TYPE) || thingTypeUID.equals(PRESENCE_CAMERA_THING_TYPE)) { return new NAWelcomeCameraHandler(thing); } else if (thingTypeUID.equals(WELCOME_PERSON_THING_TYPE)) { return new NAWelcomePersonHandler(thing); @@ -115,7 +124,7 @@ protected void removeHandler(ThingHandler thingHandler) { } } - private synchronized void registerDeviceDiscoveryService(@NonNull NetatmoBridgeHandler netatmoBridgeHandler) { + private synchronized void registerDeviceDiscoveryService(NetatmoBridgeHandler netatmoBridgeHandler) { if (bundleContext != null) { NetatmoModuleDiscoveryService discoveryService = new NetatmoModuleDiscoveryService(netatmoBridgeHandler); discoveryService.activate(null); @@ -136,7 +145,7 @@ private synchronized void unregisterDeviceDiscoveryService(ThingUID thingUID) { } } - private synchronized WelcomeWebHookServlet registerWebHookServlet(ThingUID thingUID) { + private synchronized @Nullable WelcomeWebHookServlet registerWebHookServlet(ThingUID thingUID) { WelcomeWebHookServlet servlet = null; if (bundleContext != null) { servlet = new WelcomeWebHookServlet(httpService, thingUID.getId()); @@ -152,23 +161,4 @@ private synchronized void unregisterWebHookServlet(ThingUID thingUID) { serviceReg.unregister(); } } - - @Reference - public void setHttpService(HttpService httpService) { - this.httpService = httpService; - } - - public void unsetHttpService(HttpService httpService) { - this.httpService = null; - } - - @Reference - protected void setDynamicStateDescriptionProvider(NATherm1StateDescriptionProvider provider) { - this.stateDescriptionProvider = provider; - } - - protected void unsetDynamicStateDescriptionProvider(NATherm1StateDescriptionProvider provider) { - this.stateDescriptionProvider = null; - } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/RefreshStrategy.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/RefreshStrategy.java index f3467ec8c1088..797334daa7242 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/RefreshStrategy.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/RefreshStrategy.java @@ -91,5 +91,4 @@ public void expireData() { ZonedDateTime now = ZonedDateTime.now().minus(this.dataValidityPeriod, ChronoUnit.MILLIS); dataTimeStamp = now.toInstant().toEpochMilli(); } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/WeatherUtils.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/WeatherUtils.java index 53ceeea5c7722..4d04bff509011 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/WeatherUtils.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/WeatherUtils.java @@ -80,5 +80,4 @@ public static double getHumidex(double temperature, double hygro) { result = temperature + 0.555555556 * (result - 10); return result; } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/camera/CameraHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/camera/CameraHandler.java new file mode 100644 index 0000000000000..da94ff23d4d0c --- /dev/null +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/camera/CameraHandler.java @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.netatmo.internal.camera; + +import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.toOnOffType; +import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.toStringType; +import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.eclipse.smarthome.io.net.http.HttpUtil; +import org.openhab.binding.netatmo.internal.handler.NetatmoModuleHandler; + +import io.swagger.client.model.NAWelcomeCamera; + +/** + * {@link CameraHandler} is the class used to handle Camera Data + * + * @author Sven Strohschein (partly moved code from NAWelcomeCameraHandler to introduce inheritance, see + * NAWelcomeCameraHandler) + * + */ +public class CameraHandler extends NetatmoModuleHandler { + + private static final String LIVE_PICTURE = "/live/snapshot_720.jpg"; + + public CameraHandler(@NonNull Thing thing) { + super(thing); + } + + @Override + protected void updateProperties(NAWelcomeCamera moduleData) { + updateProperties(null, moduleData.getType()); + } + + @SuppressWarnings("null") + @Override + protected State getNAThingProperty(String channelId) { + switch (channelId) { + case CHANNEL_CAMERA_STATUS: + return getStatusState(); + case CHANNEL_CAMERA_SDSTATUS: + return getSdStatusState(); + case CHANNEL_CAMERA_ALIMSTATUS: + return getAlimStatusState(); + case CHANNEL_CAMERA_ISLOCAL: + return getIsLocalState(); + case CHANNEL_CAMERA_LIVEPICTURE_URL: + return getLivePictureURLState(); + case CHANNEL_CAMERA_LIVEPICTURE: + return getLivePictureState(); + case CHANNEL_CAMERA_LIVESTREAM_URL: + return getLiveStreamState(); + } + return super.getNAThingProperty(channelId); + } + + protected State getStatusState() { + return module != null ? toOnOffType(module.getStatus()) : UnDefType.UNDEF; + } + + protected State getSdStatusState() { + return module != null ? toOnOffType(module.getSdStatus()) : UnDefType.UNDEF; + } + + protected State getAlimStatusState() { + return module != null ? toOnOffType(module.getAlimStatus()) : UnDefType.UNDEF; + } + + protected State getIsLocalState() { + return module != null ? toOnOffType(module.getIsLocal()) : UnDefType.UNDEF; + } + + protected State getLivePictureURLState() { + String livePictureURL = getLivePictureURL(); + return livePictureURL == null ? UnDefType.UNDEF : toStringType(livePictureURL); + } + + protected State getLivePictureState() { + String livePictureURL = getLivePictureURL(); + return livePictureURL == null ? UnDefType.UNDEF : HttpUtil.downloadImage(livePictureURL); + } + + protected State getLiveStreamState() { + String liveStreamURL = getLiveStreamURL(); + return liveStreamURL == null ? UnDefType.UNDEF : new StringType(liveStreamURL); + } + + /** + * Get the url for the live snapshot + * + * @return Url of the live snapshot + */ + private String getLivePictureURL() { + String result = getVpnUrl(); + if (result != null) { + result += LIVE_PICTURE; + } + return result; + } + + /** + * Get the url for the live stream depending wether local or not + * + * @return Url of the live stream + */ + private String getLiveStreamURL() { + String result = getVpnUrl(); + if (result == null) { + return null; + } + + StringBuilder resultStringBuilder = new StringBuilder(result); + resultStringBuilder.append("/live/index"); + if (isLocal()) { + resultStringBuilder.append("_local"); + } + resultStringBuilder.append(".m3u8"); + return resultStringBuilder.toString(); + } + + @SuppressWarnings("null") + private String getVpnUrl() { + return (module == null) ? null : module.getVpnUrl(); + } + + public String getStreamURL(String videoId) { + String result = getVpnUrl(); + if (result == null) { + return null; + } + + StringBuilder resultStringBuilder = new StringBuilder(result); + resultStringBuilder.append("/vod/"); + resultStringBuilder.append(videoId); + resultStringBuilder.append("/index"); + if (isLocal()) { + resultStringBuilder.append("_local"); + } + resultStringBuilder.append(".m3u8"); + return resultStringBuilder.toString(); + } + + @SuppressWarnings("null") + private boolean isLocal() { + return (module == null || module.getIsLocal() == null) ? false : module.getIsLocal(); + } +} diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/channelhelper/RadioHelper.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/channelhelper/RadioHelper.java index 77fe2a4bab07b..f5d27283a937d 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/channelhelper/RadioHelper.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/channelhelper/RadioHelper.java @@ -78,5 +78,4 @@ public Optional getNAThingProperty(String channelId) { } return Optional.empty(); } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/config/NetatmoBridgeConfiguration.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/config/NetatmoBridgeConfiguration.java index bb0d00ee8e8cc..bcf5f1ba32915 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/config/NetatmoBridgeConfiguration.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/config/NetatmoBridgeConfiguration.java @@ -27,6 +27,7 @@ public class NetatmoBridgeConfiguration { public Boolean readThermostat; public Boolean readHealthyHomeCoach; public Boolean readWelcome; + public Boolean readPresence; public String webHookUrl; public Integer reconnectInterval; } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java index 1bffa8c8aa7a9..1d8eb8c694103 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/discovery/NetatmoModuleDiscoveryService.java @@ -93,7 +93,7 @@ public void startScan() { }); } } - if (netatmoBridgeHandler.configuration.readWelcome) { + if (netatmoBridgeHandler.configuration.readWelcome || netatmoBridgeHandler.configuration.readPresence) { NAWelcomeHomeData welcomeHomeData = netatmoBridgeHandler.getWelcomeDataBody(null); if (welcomeHomeData != null) { welcomeHomeData.getHomes().forEach(home -> { @@ -194,5 +194,4 @@ private ThingUID findThingUID(String thingType, String thingId) throws IllegalAr throw new IllegalArgumentException("Unsupported device type discovered : " + thingType); } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/AbstractNetatmoThingHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/AbstractNetatmoThingHandler.java index 8ee52bcfafdf1..10e3e375a6a34 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/AbstractNetatmoThingHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/AbstractNetatmoThingHandler.java @@ -37,7 +37,9 @@ import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.BridgeHandler; import org.eclipse.smarthome.core.thing.type.ChannelKind; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; @@ -81,17 +83,43 @@ public abstract class AbstractNetatmoThingHandler extends BaseThingHandler { @Override public void initialize() { - config = getThing().getConfiguration(); + logger.debug("initializing handler for thing {}", getThing().getUID()); + Bridge bridge = getBridge(); + initializeThing(bridge != null ? bridge.getStatus() : null); + } + + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + logger.debug("bridgeStatusChanged {} for thing {}", bridgeStatusInfo, getThing().getUID()); + initializeThing(bridgeStatusInfo.getStatus()); + } - radioHelper = thing.getProperties().containsKey(PROPERTY_SIGNAL_LEVELS) - ? Optional.of(new RadioHelper(thing.getProperties().get(PROPERTY_SIGNAL_LEVELS))) - : Optional.empty(); - batteryHelper = thing.getProperties().containsKey(PROPERTY_BATTERY_LEVELS) - ? Optional.of(new BatteryHelper(thing.getProperties().get(PROPERTY_BATTERY_LEVELS))) - : Optional.empty(); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Pending parent object initialization"); + private void initializeThing(ThingStatus bridgeStatus) { + Bridge bridge = getBridge(); + BridgeHandler bridgeHandler = bridge != null ? bridge.getHandler() : null; + if (bridgeHandler != null && bridgeStatus != null) { + if (bridgeStatus == ThingStatus.ONLINE) { + config = getThing().getConfiguration(); + + radioHelper = thing.getProperties().containsKey(PROPERTY_SIGNAL_LEVELS) + ? Optional.of(new RadioHelper(thing.getProperties().get(PROPERTY_SIGNAL_LEVELS))) + : Optional.empty(); + batteryHelper = thing.getProperties().containsKey(PROPERTY_BATTERY_LEVELS) + ? Optional.of(new BatteryHelper(thing.getProperties().get(PROPERTY_BATTERY_LEVELS))) + : Optional.empty(); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Pending parent object initialization"); + + initializeThing(); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); + } } + protected abstract void initializeThing(); + protected State getNAThingProperty(String channelId) { Optional result; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java index f3045a45262ee..6f9c55ddf5e23 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoBridgeHandler.java @@ -99,7 +99,6 @@ public Object get(Class apiClass) { } return super.get(apiClass); } - } public NetatmoBridgeHandler(@NonNull Bridge bridge, WelcomeWebHookServlet webHookServlet) { @@ -211,6 +210,11 @@ private String getApiScope() { scopes.add("write_camera"); } + if (configuration.readPresence) { + scopes.add("read_presence"); + scopes.add("access_presence"); + } + return String.join(" ", scopes); } @@ -349,7 +353,8 @@ public void webHookEvent(NAWebhookCameraEvent event) { private String getWebHookURI() { String webHookURI = null; - if (configuration.webHookUrl != null && configuration.readWelcome && webHookServlet != null) { + if (configuration.webHookUrl != null && (configuration.readWelcome || configuration.readPresence) + && webHookServlet != null) { webHookURI = configuration.webHookUrl + webHookServlet.getPath(); } return webHookURI; diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java index 103c66ff3189b..ade2f286c83a6 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoDeviceHandler.java @@ -26,7 +26,6 @@ import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.PointType; -import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; @@ -60,23 +59,10 @@ public NetatmoDeviceHandler(Thing thing) { } @Override - public void initialize() { - super.initialize(); - Bridge bridge = getBridge(); - if (bridge != null) { - logger.debug("Initializing {} with id '{}'", getClass(), getId()); - if (bridge.getStatus() == ThingStatus.ONLINE) { - defineRefreshInterval(); - updateStatus(ThingStatus.ONLINE); - scheduleRefreshJob(); - } else { - logger.debug("setting device '{}' offline (bridge or thing offline)", getId()); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.BRIDGE_OFFLINE); - } - } else { - logger.debug("setting device '{}' offline (bridge == null)", getId()); - updateStatus(ThingStatus.OFFLINE); - } + protected void initializeThing() { + defineRefreshInterval(); + updateStatus(ThingStatus.ONLINE); + scheduleRefreshJob(); } private void scheduleRefreshJob() { @@ -231,5 +217,4 @@ private void defineRefreshInterval() { public void expireData() { refreshStrategy.expireData(); } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoModuleHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoModuleHandler.java index d5a286bcdec10..9656992571eeb 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoModuleHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/handler/NetatmoModuleHandler.java @@ -47,8 +47,7 @@ protected NetatmoModuleHandler(Thing thing) { } @Override - public void initialize() { - super.initialize(); + protected void initializeThing() { refreshJob = scheduler.schedule(() -> { requestParentRefresh(); }, 5, TimeUnit.SECONDS); @@ -130,5 +129,4 @@ protected boolean isRefreshRequired() { protected void setRefreshRequired(boolean refreshRequired) { this.refreshRequired = refreshRequired; } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/homecoach/NAHealthyHomeCoachHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/homecoach/NAHealthyHomeCoachHandler.java index b08123553a93a..da0f74303e59a 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/homecoach/NAHealthyHomeCoachHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/homecoach/NAHealthyHomeCoachHandler.java @@ -120,5 +120,4 @@ private String toHealthIndexString(Integer healthIndex) { } return null; } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NAPlugHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NAPlugHandler.java index d3845a8a0f92d..5f3db29ec4803 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NAPlugHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NAPlugHandler.java @@ -96,5 +96,4 @@ protected State getNAThingProperty(String channelId) { } return null; } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NATherm1Handler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NATherm1Handler.java index b004f32012366..3a95e34af5058 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NATherm1Handler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/thermostat/NATherm1Handler.java @@ -304,5 +304,4 @@ private int getSetPointDefaultDuration() { // TODO : this informations could be sourced from Netatmo API instead of a local configuration element return ((Number) config.get(SETPOINT_DEFAULT_DURATION)).intValue(); } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/webhook/NAWebhookCameraEvent.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/webhook/NAWebhookCameraEvent.java index 5ad19658444b2..c04fdf47d876f 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/webhook/NAWebhookCameraEvent.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/webhook/NAWebhookCameraEvent.java @@ -152,5 +152,4 @@ public String getHomeId() { public List getPersons() { return persons; } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/webhook/WelcomeWebHookServlet.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/webhook/WelcomeWebHookServlet.java index a57edb2ad5c9d..2364ae3e22d57 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/webhook/WelcomeWebHookServlet.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/webhook/WelcomeWebHookServlet.java @@ -109,5 +109,4 @@ private void setHeaders(HttpServletResponse response) { public String getPath() { return path; } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeCameraHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeCameraHandler.java index 8eecffbfb2170..c0a0c845efbec 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeCameraHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeCameraHandler.java @@ -12,19 +12,12 @@ */ package org.openhab.binding.netatmo.internal.welcome; -import static org.openhab.binding.netatmo.internal.ChannelTypeUtils.*; import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*; import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.State; -import org.eclipse.smarthome.core.types.UnDefType; -import org.eclipse.smarthome.io.net.http.HttpUtil; -import org.openhab.binding.netatmo.internal.handler.NetatmoModuleHandler; - -import io.swagger.client.model.NAWelcomeCamera; +import org.openhab.binding.netatmo.internal.camera.CameraHandler; /** * {@link NAWelcomeCameraHandler} is the class used to handle the Welcome Camera Data @@ -32,87 +25,31 @@ * @author Ing. Peter Weiss - Initial contribution * */ -public class NAWelcomeCameraHandler extends NetatmoModuleHandler { - private static final String LIVE_PICTURE = "/live/snapshot_720.jpg"; +public class NAWelcomeCameraHandler extends CameraHandler { public NAWelcomeCameraHandler(@NonNull Thing thing) { super(thing); } - @Override - protected void updateProperties(NAWelcomeCamera moduleData) { - updateProperties(null, moduleData.getType()); - } - @SuppressWarnings("null") @Override - protected State getNAThingProperty(String chanelId) { - switch (chanelId) { + protected State getNAThingProperty(String channelId) { + switch (channelId) { case CHANNEL_WELCOME_CAMERA_STATUS: - return module != null ? toOnOffType(module.getStatus()) : UnDefType.UNDEF; + return getStatusState(); case CHANNEL_WELCOME_CAMERA_SDSTATUS: - return module != null ? toOnOffType(module.getSdStatus()) : UnDefType.UNDEF; + return getSdStatusState(); case CHANNEL_WELCOME_CAMERA_ALIMSTATUS: - return module != null ? toOnOffType(module.getAlimStatus()) : UnDefType.UNDEF; + return getAlimStatusState(); case CHANNEL_WELCOME_CAMERA_ISLOCAL: - return (module == null || module.getIsLocal() == null) ? UnDefType.UNDEF - : module.getIsLocal() ? OnOffType.ON : OnOffType.OFF; + return getIsLocalState(); case CHANNEL_WELCOME_CAMERA_LIVEPICTURE_URL: - return getLivePictureURL() == null ? UnDefType.UNDEF : toStringType(getLivePictureURL()); + return getLivePictureURLState(); case CHANNEL_WELCOME_CAMERA_LIVEPICTURE: - return getLivePictureURL() == null ? UnDefType.UNDEF : HttpUtil.downloadImage(getLivePictureURL()); + return getLivePictureState(); case CHANNEL_WELCOME_CAMERA_LIVESTREAM_URL: - return getLiveStreamURL() == null ? UnDefType.UNDEF : new StringType(getLiveStreamURL()); - } - return super.getNAThingProperty(chanelId); - } - - /** - * Get the url for the live snapshot - * - * @return Url of the live snapshot - */ - private String getLivePictureURL() { - String result = getVpnUrl(); - if (result != null) { - result += LIVE_PICTURE; - } - return result; - } - - /** - * Get the url for the live stream depending wether local or not - * - * @return Url of the live stream - */ - private String getLiveStreamURL() { - String result = getVpnUrl(); - if (result != null) { - result += "/live/index"; - result += isLocal() ? "_local" : ""; - result += ".m3u8"; + return getLiveStreamState(); } - return result; + return super.getNAThingProperty(channelId); } - - @SuppressWarnings("null") - private String getVpnUrl() { - return (module == null) ? null : module.getVpnUrl(); - } - - public String getStreamURL(String videoId) { - String result = getVpnUrl(); - if (result != null) { - result += "/vod/" + videoId + "/index"; - result += isLocal() ? "_local" : ""; - result += ".m3u8"; - } - return result; - } - - @SuppressWarnings("null") - private boolean isLocal() { - return (module == null || module.getIsLocal() == null) ? false : module.getIsLocal().booleanValue(); - } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeHomeHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeHomeHandler.java index ea41e70ab2923..55d76b51b4b71 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeHomeHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomeHomeHandler.java @@ -189,5 +189,4 @@ protected String getSnapshotURL(NAWelcomeSnapshot snapshot) { protected @Nullable Integer getDataTimestamp() { return dataTimeStamp; } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomePersonHandler.java b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomePersonHandler.java index 436f93aeaeee2..45c490c4103c6 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomePersonHandler.java +++ b/bundles/org.openhab.binding.netatmo/src/main/java/org/openhab/binding/netatmo/internal/welcome/NAWelcomePersonHandler.java @@ -121,5 +121,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { invalidateParentCacheAndRefresh(); } } - } diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/binding/binding.xml index 4eabfae57fcd4..af7cba2e6a13a 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/binding/binding.xml @@ -1,11 +1,11 @@ - + Netatmo Binding - The Netatmo binding integrates Weather Station with companion modules, Healthy Home Coach, Thermostat Plug and Welcome Camera. + The Netatmo binding integrates Weather Station with companion modules, Healthy Home Coach, Thermostat Plug + and Welcome Camera. Gaël L'hopital and Ing. Peter Weiss diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/config/config.xml index be947333380d8..8d5f222af057e 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - @@ -15,6 +16,7 @@ Client Secret provided for the application you created true + password @@ -54,13 +56,19 @@ false + + + Read and Access Presence camera's data. + false + + Protocol, public IP and port to access OH2 server from Internet. true - + The reconnection interval to Netatmo API (in s). 5400 @@ -84,7 +92,7 @@ true - + The refresh interval to poll Netatmo API (in ms). 300000 @@ -133,7 +141,7 @@ UUID of the home - + The refresh interval to poll Netatmo API (in ms). 300000 @@ -141,7 +149,7 @@ - + Camera MAC Address diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/i18n/netatmo_de.properties b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/i18n/netatmo_de.properties index 869f8dddc7613..7de1fc8e9dc6d 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/i18n/netatmo_de.properties +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/i18n/netatmo_de.properties @@ -31,6 +31,9 @@ thing-type.config.netatmo.bridge.readThermostat.description = Aktiviert den Zugr #thing-type.config.netatmo.bridge.readWelcome.label = Access Welcome camera #thing-type.config.netatmo.bridge.readWelcome.description = Read and Access Welcome camera's data. +#thing-type.config.netatmo.bridge.readPresence.label = Access Presence camera +#thing-type.config.netatmo.bridge.readPresence.description = Read and Access Presence camera's data. + #thing-type.config.netatmo.bridge.webHookUrl.label = Webhook address #thing-type.config.netatmo.bridge.webHookUrl.description = Protocol, public IP and port to access OH2 server from Internet. @@ -99,11 +102,11 @@ thing-type.config.netatmo.module.parentId.description = MAC-Adresse des Haupt-In #thing-type.config.netatmo.welcomehome.refreshInterval.label = Refresh Interval #thing-type.config.netatmo.welcomehome.refreshInterval.description = The refresh interval to poll Netatmo API (in ms). -#thing-type.config.netatmo.nawelcomecamera.id.label = Camera ID -#thing-type.config.netatmo.nawelcomecamera.id.description = Camera MAC Address +#thing-type.config.netatmo.camera.id.label = Camera ID +#thing-type.config.netatmo.camera.id.description = Camera MAC Address -#thing-type.config.netatmo.nawelcomecamera.parentId.label = Home ID -#thing-type.config.netatmo.nawelcomecamera.parentId.description = UUID of the home hosting the camera +#thing-type.config.netatmo.camera.parentId.label = Home ID +#thing-type.config.netatmo.camera.parentId.description = UUID of the home hosting the camera #thing-type.config.netatmo.nawelcomeperson.id.label = Person ID #thing-type.config.netatmo.nawelcomeperson.id.description = UUID of the Person diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/i18n/netatmo_fr.properties b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/i18n/netatmo_fr.properties index 8c89b19c838e3..6f271745df87e 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/i18n/netatmo_fr.properties +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/i18n/netatmo_fr.properties @@ -29,6 +29,9 @@ thing-type.config.netatmo.bridge.readThermostat.description = Acc thing-type.config.netatmo.bridge.readWelcome.label = Accs la Camera Welcome thing-type.config.netatmo.bridge.readWelcome.description = Accde ou non aux donnes de la camra Welcome. +thing-type.config.netatmo.bridge.readPresence.label = Accs la Camera Presence +thing-type.config.netatmo.bridge.readPresence.description = Accde ou non aux donnes de la camra Presence. + thing-type.config.netatmo.bridge.webHookUrl.label = Adresse Webhook thing-type.config.netatmo.bridge.webHookUrl.description = Protocole, IP publique et port pour l'accs au sereveur OH2 depuis l'Internet. @@ -97,11 +100,11 @@ thing-type.config.netatmo.welcomehome.id.description = ID de la maison thing-type.config.netatmo.welcomehome.refreshInterval.label = Frquence de rafrachissement thing-type.config.netatmo.welcomehome.refreshInterval.description = La frquence d'interrogation de l'API Netatmo (en ms) -thing-type.config.netatmo.nawelcomecamera.id.label = ID camra -thing-type.config.netatmo.nawelcomecamera.id.description = ID de la camra (adresse MAC) +thing-type.config.netatmo.camera.id.label = ID camra +thing-type.config.netatmo.camera.id.description = ID de la camra (adresse MAC) -thing-type.config.netatmo.nawelcomecamera.parentId.label = ID maison -thing-type.config.netatmo.nawelcomecamera.parentId.description = ID de la maison hbergeant la camra +thing-type.config.netatmo.camera.parentId.label = ID maison +thing-type.config.netatmo.camera.parentId.description = ID de la maison hbergeant la camra thing-type.config.netatmo.nawelcomeperson.id.label = ID personne thing-type.config.netatmo.nawelcomeperson.id.description = ID de la personne diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/bridge.xml index 8516b683185db..b3591dfe04ede 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/bridge.xml @@ -8,7 +8,7 @@ This bridge represents the gateway to Netatmo API. - + diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomecamera.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/camera.xml similarity index 68% rename from bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomecamera.xml rename to bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/camera.xml index d47ff042ad4de..06675b5b12e94 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomecamera.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/camera.xml @@ -1,11 +1,12 @@ - - + @@ -23,7 +24,29 @@ id - + + + + + + + + + + This represents a presence camera at home + + + + + + + + + + + + id + @@ -51,7 +74,8 @@ Switch - Only for scope access_camera. If Camera and application requesting the information are on the same network (true/false) + Only for scope access_camera. If Camera and application requesting the information are on the same + network (true/false) @@ -62,7 +86,7 @@ - + Image Camera Live Snapshot diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/channels.xml index c02f86bb64983..c105e83050152 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/channels.xml @@ -8,14 +8,14 @@ DateTime Last Status Store - + Location Location of the device - + @@ -23,7 +23,7 @@ Current temperature Temperature - + @@ -31,7 +31,7 @@ Minimum Temperature on current day Temperature - + @@ -39,7 +39,7 @@ Minimum Temperature this week Temperature - + @@ -47,7 +47,7 @@ Minimum Temperature this month Temperature - + @@ -55,7 +55,7 @@ Maximum Temperature on current day Temperature - + @@ -63,7 +63,7 @@ Maximum Temperature this week Temperature - + @@ -71,7 +71,7 @@ Maximum Temperature this month Temperature - + @@ -93,7 +93,7 @@ Thermostat temperature setpoint Temperature - + @@ -116,321 +116,321 @@ Switch Indicates whether the furnace is heating or not - + Number Physical orientation of the thermostat module - + DateTime Timestamp when data was measured - + DateTime Last Plug Seen - + DateTime Date when minimum CO2 was reached on current day - + DateTime Date when minimum CO2 was reached this week - + DateTime Date when minimum CO2 was reached this month - + DateTime Date when maximum CO2 was reached on current day - + DateTime Date when maximum CO2 was reached this week - + DateTime Date when maximum CO2 was reached this month - + DateTime Date when minimum temperature was reached on current day - + DateTime Date when minimum temperature was reached this week - + DateTime Date when minimum temperature was reached this month - + DateTime Date when maximum temperature was reached on current day - + DateTime Date when maximum temperature was reached this week - + DateTime Date when maximum temperature was reached this month - + DateTime Date when minimum humidity was reached on current day - + DateTime Date when minimum humidity was reached this week - + DateTime Date when minimum humidity was reached this month - + DateTime Date when maximum humidity was reached on current day - + DateTime Date when maximum humidity was reached this week - + DateTime Date when maximum humidity was reached this month - + DateTime Date when minimum noise was reached on current day - + DateTime Date when minimum noise was reached this week - + DateTime Date when minimum noise was reached this month - + DateTime Date when maximum noise was reached on current day - + DateTime Date when maximum noise was reached this week - + DateTime Date when maximum noise was reached this month - + DateTime Date when minimum pressure was reached on current day - + DateTime Date when minimum pressure was reached this week - + DateTime Date when minimum pressure was reached this month - + DateTime Date when maximum pressure was reached on current day - + DateTime Date when maximum pressure was reached this week - + DateTime Date when maximum pressure was reached this month - + DateTime Month of the last available thermostat bilan - + Switch - + DateTime Last Message emitted by the module - + DateTime Thermostat goes back to schedule after that timestamp. - + DateTime Last Them Seen - + Number:Dimensionless Air Quality - + Number:Dimensionless Minimum CO2 on current day - + Number:Dimensionless Minimum CO2 this week - + Number:Dimensionless Minimum CO2 this month - + Number:Dimensionless Maximum CO2 on current day - + Number:Dimensionless Maximum CO2 this week - + Number:Dimensionless Maximum CO2 this month - + @@ -438,7 +438,7 @@ Current Noise Level Noise - + @@ -446,7 +446,7 @@ Minimum Noise on current day Noise - + @@ -454,7 +454,7 @@ Minimum Noise this week Noise - + @@ -462,7 +462,7 @@ Minimum Noise this month Noise - + @@ -470,7 +470,7 @@ Maximum Noise on current day Noise - + @@ -478,7 +478,7 @@ Maximum Noise this week Noise - + @@ -486,7 +486,7 @@ Maximum Noise this month Noise - + @@ -509,7 +509,7 @@ Current pressure Pressure - + @@ -517,7 +517,7 @@ Minimum Pressure on current day Pressure - + @@ -525,7 +525,7 @@ Minimum Pressure this week Pressure - + @@ -533,7 +533,7 @@ Minimum Pressure this month Pressure - + @@ -541,7 +541,7 @@ Maximum Pressure on current day Pressure - + @@ -549,7 +549,7 @@ Maximum Pressure this week Pressure - + @@ -557,7 +557,7 @@ Maximum Pressure this month Pressure - + @@ -578,7 +578,7 @@ String Heat planning currently used - + @@ -586,7 +586,7 @@ Absolute pressure Pressure - + @@ -594,7 +594,7 @@ Current humidity Humidity - + @@ -602,7 +602,7 @@ Minimum Humidity on current day Humidity - + @@ -610,7 +610,7 @@ Minimum Humidity this week Humidity - + @@ -618,7 +618,7 @@ Minimum Humidity this month Humidity - + @@ -626,7 +626,7 @@ Maximum Humidity on current day Humidity - + @@ -634,7 +634,7 @@ Minimum Humidity this week Humidity - + @@ -642,7 +642,7 @@ Maximum Humidity this month Humidity - + @@ -650,7 +650,7 @@ Computed Humidex index Temperature - + @@ -658,7 +658,7 @@ Computed Heat Index Temperature - + @@ -666,14 +666,14 @@ Computed Dewpoint Temperature Temperature - + Number:Temperature Computed Dewpoint Depression - + @@ -681,7 +681,7 @@ Quantity of water Rain - + @@ -689,7 +689,7 @@ Quantity of water on last hour Rain - + @@ -697,7 +697,7 @@ Quantity of water on last day Rain - + @@ -705,7 +705,7 @@ Quantity of water this week Rain - + @@ -713,7 +713,7 @@ Quantity of water this month Rain - + @@ -721,7 +721,7 @@ Current 5 minutes average wind direction Wind - + @@ -729,7 +729,7 @@ Current 5 minutes average wind speed Wind - + @@ -737,14 +737,14 @@ Maximum wind strength recorded Wind - + DateTime Timestamp when MaxWindStrength was recorded. - + @@ -752,7 +752,7 @@ Direction of the last 5 minutes highest gust wind Wind - + @@ -760,7 +760,7 @@ Speed of the last 5 minutes highest gust wind Wind - + diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/healthyhomecoach.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/healthyhomecoach.xml index 0938478c62370..c8a2090e4f50e 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/healthyhomecoach.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/healthyhomecoach.xml @@ -6,30 +6,31 @@ - + - This represents the healthy home coach capable of reporting health index,temperature,humidity,pressure,air quality and sound level + This represents the healthy home coach capable of reporting health + index,temperature,humidity,pressure,air quality and sound level - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -38,6 +39,6 @@ id - + diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/station.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/station.xml index 977c85d16e4d4..f2b43468d7c0f 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/station.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/station.xml @@ -6,90 +6,91 @@ - + - This represents the main indoor module capable of reporting temperature,humidity,pressure,air quality and sound level + This represents the main indoor module capable of reporting temperature,humidity,pressure,air quality and + sound level - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + @@ -98,55 +99,55 @@ id - + - + This represents the outdoor module capable of reporting temperature and humidity - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + @@ -155,30 +156,30 @@ id - + - + This represents the wind module capable of reporting wind angle and strength - - - - - - + + + + + + - - - - - + + + + + @@ -187,29 +188,29 @@ id - + - + This represents the Rain Gauge capable of measuring precipitation - - - - - + + + + + - - - - - + + + + + @@ -218,68 +219,68 @@ id - + - + This represents an additional indoor module capable of reporting temperature, humidity and CO2 level - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + @@ -288,7 +289,7 @@ id - + diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/thermostat.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/thermostat.xml index 3b128154cf58e..b2b9b69777477 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/thermostat.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/thermostat.xml @@ -7,54 +7,54 @@ - + This represents the thermostat relay - - - - - - - + + + + + + + 86,71,56 3600000 - + id - + - + This represents the thermostat module itself - - - - + + + + - - + + - - - - - + + + + + @@ -63,7 +63,7 @@ id - + diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomehome.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomehome.xml index 0a63138853b17..f49c25620cc25 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomehome.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomehome.xml @@ -1,15 +1,16 @@ - - + - This represents a home hosting a Welcome Camera + This represents a home hosting a camera @@ -34,7 +35,7 @@ id - + @@ -99,12 +100,12 @@ - + Image Event Snapshot - + String diff --git a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomeperson.xml b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomeperson.xml index dd1b3066ac2c5..ecf3eaf6f7c14 100644 --- a/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomeperson.xml +++ b/bundles/org.openhab.binding.netatmo/src/main/resources/ESH-INF/thing/welcomeperson.xml @@ -1,11 +1,12 @@ - - + @@ -24,7 +25,7 @@ id - + @@ -61,14 +62,14 @@ - + Image Avatar of this person - + Image Picture of the last event for this person diff --git a/bundles/org.openhab.binding.network/pom.xml b/bundles/org.openhab.binding.network/pom.xml index 12a5ab73497f9..5c9141b23079d 100644 --- a/bundles/org.openhab.binding.network/pom.xml +++ b/bundles/org.openhab.binding.network/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.network @@ -29,12 +31,12 @@ 1.04 compile - - commons-net - commons-net - 3.6 - compile - + + commons-net + commons-net + 3.6 + compile + diff --git a/bundles/org.openhab.binding.network/src/main/feature/feature.xml b/bundles/org.openhab.binding.network/src/main/feature/feature.xml index 5479ba232903d..a1fd91f9992fd 100644 --- a/bundles/org.openhab.binding.network/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.network/src/main/feature/feature.xml @@ -1,12 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-core-model-script - mvn:commons-net/commons-net/3.6 - mvn:org.openhab.addons.bundles/org.openhab.binding.network/${project.version} - + + openhab-runtime-base + openhab-core-model-script + mvn:commons-net/commons-net/3.6 + mvn:org.openhab.addons.bundles/org.openhab.binding.network/${project.version} + - diff --git a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/NetworkBindingConfiguration.java b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/NetworkBindingConfiguration.java index edb4e82c817c3..14594569072ce 100644 --- a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/NetworkBindingConfiguration.java +++ b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/NetworkBindingConfiguration.java @@ -62,13 +62,9 @@ private void notifyListeners() { @Override public String toString() { - return "NetworkBindingConfiguration{" + - "allowSystemPings=" + allowSystemPings + - ", allowDHCPlisten=" + allowDHCPlisten + - ", cacheDeviceStateTimeInMS=" + cacheDeviceStateTimeInMS + - ", arpPingToolPath='" + arpPingToolPath + '\'' + - ", arpPingUtilMethod=" + arpPingUtilMethod + - ", preferResponseTimeAsLatency=" + preferResponseTimeAsLatency + - '}'; + return "NetworkBindingConfiguration{" + "allowSystemPings=" + allowSystemPings + ", allowDHCPlisten=" + + allowDHCPlisten + ", cacheDeviceStateTimeInMS=" + cacheDeviceStateTimeInMS + ", arpPingToolPath='" + + arpPingToolPath + '\'' + ", arpPingUtilMethod=" + arpPingUtilMethod + ", preferResponseTimeAsLatency=" + + preferResponseTimeAsLatency + '}'; } } diff --git a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/NetworkBindingConstants.java b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/NetworkBindingConstants.java index 012f6ee40b811..689c16af33494 100644 --- a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/NetworkBindingConstants.java +++ b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/NetworkBindingConstants.java @@ -69,5 +69,4 @@ public class NetworkBindingConstants { SUPPORTED_THING_TYPES_UIDS.add(BACKWARDS_COMPATIBLE_DEVICE); SUPPORTED_THING_TYPES_UIDS.add(SPEEDTEST_DEVICE); } - } diff --git a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/dhcp/DHCPPacket.java b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/dhcp/DHCPPacket.java index c363bc0712ba2..c99af8ce101f7 100644 --- a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/dhcp/DHCPPacket.java +++ b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/dhcp/DHCPPacket.java @@ -89,7 +89,6 @@ static class BadPacketException extends IllegalArgumentException { BadPacketException(String message, Throwable cause) { super(message, cause); } - } private byte op; diff --git a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/handler/NetworkHandler.java b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/handler/NetworkHandler.java index 16902d98394ec..66469c86d3e97 100644 --- a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/handler/NetworkHandler.java +++ b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/handler/NetworkHandler.java @@ -47,7 +47,8 @@ * @author David Graeff - Rewritten */ @NonNullByDefault -public class NetworkHandler extends BaseThingHandler implements PresenceDetectionListener, NetworkBindingConfigurationListener { +public class NetworkHandler extends BaseThingHandler + implements PresenceDetectionListener, NetworkBindingConfigurationListener { private final Logger logger = LoggerFactory.getLogger(NetworkHandler.class); private @NonNullByDefault({}) PresenceDetection presenceDetection; diff --git a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/LatencyParser.java b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/LatencyParser.java index 70db4dc062523..6217739efbd87 100644 --- a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/LatencyParser.java +++ b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/LatencyParser.java @@ -12,13 +12,13 @@ */ package org.openhab.binding.network.internal.utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Examines output lines of the ping command and tries to extract the contained latency value. * @@ -42,14 +42,14 @@ public class LatencyParser { * * @param inputLine Single output line of the ping command. * @return Latency value provided by the ping command. Optional is empty if the provided line did not contain a - * latency value which matches the known patterns. + * latency value which matches the known patterns. */ public Optional parseLatency(String inputLine) { logger.debug("Parsing latency from input {}", inputLine); String pattern = ".*time=(.*) ms"; Matcher m = Pattern.compile(pattern).matcher(inputLine); - if(m.find() && m.groupCount() == 1) { + if (m.find() && m.groupCount() == 1) { return Optional.of(Double.parseDouble(m.group(1))); } diff --git a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/NetworkUtils.java b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/NetworkUtils.java index e612d4663e77b..972ff29f5d842 100644 --- a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/NetworkUtils.java +++ b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/NetworkUtils.java @@ -12,6 +12,13 @@ */ package org.openhab.binding.network.internal.utils; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.*; +import java.util.*; +import java.util.stream.Collectors; + import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.apache.commons.net.util.SubnetUtils; @@ -23,13 +30,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.*; -import java.util.*; -import java.util.stream.Collectors; - /** * Network utility functions for pinging and for determining all interfaces and assigned IP addresses. * @@ -62,7 +62,7 @@ public Set getInterfaceNames() { try { // For each interface ... - for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { + for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface networkInterface = en.nextElement(); if (!networkInterface.isLoopback()) { result.add(networkInterface.getName()); @@ -264,9 +264,9 @@ public Optional nativePing(@Nullable IpPingMethodEnum method, String // Because of the Windows issue, we need to check this. We assume that the ping was successful whenever // this specific string is contained in the output if (line.contains("TTL=") || line.contains("ttl=")) { - PingResult pingResult = new PingResult(true, System.currentTimeMillis() - execStartTimeInMS); - latencyParser.parseLatency(line).ifPresent(pingResult::setResponseTimeInMS); - return Optional.of(pingResult); + PingResult pingResult = new PingResult(true, System.currentTimeMillis() - execStartTimeInMS); + latencyParser.parseLatency(line).ifPresent(pingResult::setResponseTimeInMS); + return Optional.of(pingResult); } line = r.readLine(); } while (line != null); @@ -298,7 +298,7 @@ public enum ArpPingUtilEnum { * @throws IOException The ping command could probably not be found */ public Optional nativeARPPing(@Nullable ArpPingUtilEnum arpingTool, @Nullable String arpUtilPath, - String interfaceName, String ipV4address, int timeoutInMS) throws IOException, InterruptedException { + String interfaceName, String ipV4address, int timeoutInMS) throws IOException, InterruptedException { double execStartTimeInMS = System.currentTimeMillis(); if (arpUtilPath == null || arpingTool == null || arpingTool == ArpPingUtilEnum.UNKNOWN_TOOL) { @@ -333,7 +333,7 @@ public Optional javaPing(int timeoutInMS, InetAddress destinationAdd double execStartTimeInMS = System.currentTimeMillis(); try { - if(destinationAddress.isReachable(timeoutInMS)) { + if (destinationAddress.isReachable(timeoutInMS)) { return Optional.of(new PingResult(true, System.currentTimeMillis() - execStartTimeInMS)); } else { return Optional.of(new PingResult(false, System.currentTimeMillis() - execStartTimeInMS)); diff --git a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/PingResult.java b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/PingResult.java index 46169bef2f062..9bc0b0ef94a7d 100644 --- a/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/PingResult.java +++ b/bundles/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/PingResult.java @@ -26,7 +26,7 @@ public class PingResult { private double executionTimeInMS; /** - * @param success true if the device was reachable, false if not. + * @param success true if the device was reachable, false if not. * @param executionTimeInMS Execution time of the ping command in ms. */ public PingResult(boolean success, double executionTimeInMS) { @@ -43,7 +43,7 @@ public boolean isSuccess() { /** * @return Response time in ms which was returned by the ping command. Optional is empty if response time provided - * by ping command is not available. + * by ping command is not available. */ public Optional getResponseTimeInMS() { return responseTimeInMS == null ? Optional.empty() : Optional.of(responseTimeInMS); @@ -58,11 +58,8 @@ public void setResponseTimeInMS(double responseTimeInMS) { @Override public String toString() { - return "PingResult{" + - "success=" + success + - ", responseTimeInMS=" + responseTimeInMS + - ", executionTimeInMS=" + executionTimeInMS + - '}'; + return "PingResult{" + "success=" + success + ", responseTimeInMS=" + responseTimeInMS + ", executionTimeInMS=" + + executionTimeInMS + '}'; } /** diff --git a/bundles/org.openhab.binding.network/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.network/src/main/resources/ESH-INF/binding/binding.xml index 89628e8b919d7..ece305fba1013 100644 --- a/bundles/org.openhab.binding.network/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.network/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Network Binding The Network Binding can be used for device presence detection and to determine network device health @@ -12,29 +11,36 @@ true Allows or disallows to use system pings next to the java integrated ping functionality. - On windows the system ping works more reliable most of the time. + On windows the + system ping works more reliable most of the time. true - Usually a device requests an IP address in an IPv4 network with the help of DHCP as soon as it enters a network. If we listen to those - packets, we can detect a device presence even faster. You need elevated access rights (see readme) for this to work. + Usually a device requests an IP address in an IPv4 network with the help of DHCP as soon as it enters a + network. If we listen to those + packets, we can detect a device presence even faster. You need elevated access rights + (see readme) for this to work. 2000 - The result of a device presence detection is cached for a small amount of time. Be aware that no new pings will be issued within this time frame, even if explicitly requested. + The result of a device presence detection is cached for a small amount of time. Be aware that no new + pings will be issued within this time frame, even if explicitly requested. true arping - If your arp ping tool is not called arping and cannot be found in the PATH environment, you can configure the absolute path / tool name here. + If your arp ping tool is not called arping and cannot be found in the PATH environment, you can + configure the absolute path / tool name here. false - If enabled, an attempt will be made to extract the latency from the output of the ping command. If no such latency value is found in the ping command output, the time to execute the ping command is used as fallback latency. If disabled, the time to execute the ping command is always used as latency value. + If enabled, an attempt will be made to extract the latency from the output of the ping command. If no + such latency value is found in the ping command output, the time to execute the ping command is used as fallback + latency. If disabled, the time to execute the ping command is always used as latency value. diff --git a/bundles/org.openhab.binding.network/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.network/src/main/resources/ESH-INF/thing/thing-types.xml index 8e3e9e4368e53..b0a388320aaf5 100644 --- a/bundles/org.openhab.binding.network/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.network/src/main/resources/ESH-INF/thing/thing-types.xml @@ -6,13 +6,14 @@ The presence detection is performed by using ICMP and, if available, ARP pings. - You can change the arping tool path in the binding configuration. - DHCP sniffing is performed for faster network reentry discovery. + You can change the arping + tool path in the binding configuration. + DHCP sniffing is performed for faster network reentry discovery. - - - + + + @@ -37,7 +38,8 @@ - How many refresh interval cycles should a presence detection should take place, before the device is stated as offline + How many refresh interval cycles should a presence detection should take place, before the device is + stated as offline 1 @@ -53,12 +55,13 @@ A device which reachable state is detected by connecting to a TCP port. - DHCP sniffing is performed for faster network reentry discovery. + DHCP sniffing is performed for + faster network reentry discovery. - - - + + + @@ -77,7 +80,8 @@ - The port on which the device can be accessed. Windows systems usually have the 445 port open. Webservers are on port 80. + The port on which the device can be accessed. Windows systems usually have the 445 port open. + Webservers are on port 80. 80 @@ -106,10 +110,10 @@ Provides information about bandwidth speed. - - - - + + + + @@ -163,28 +167,28 @@ Number:Dimensionless Current Test progression - + Number:DataTransferRate Current upload rate - + Number:DataTransferRate Current download rate - + DateTime Status timestamp - + diff --git a/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/toberemoved/cache/ExpiringCacheHelper.java b/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/toberemoved/cache/ExpiringCacheHelper.java index 2e851b69b9261..c94a5af6a1aa2 100644 --- a/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/toberemoved/cache/ExpiringCacheHelper.java +++ b/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/toberemoved/cache/ExpiringCacheHelper.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.network.internal.toberemoved.cache; -import org.openhab.binding.network.internal.toberemoved.cache.ExpiringCacheAsync; - /** * Helper class to make the package private cacheUpdater field available for tests. * diff --git a/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/utils/LatencyParserTest.java b/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/utils/LatencyParserTest.java index 5758c96023ac9..141f6644f94d7 100644 --- a/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/utils/LatencyParserTest.java +++ b/bundles/org.openhab.binding.network/src/test/java/org/openhab/binding/network/internal/utils/LatencyParserTest.java @@ -12,11 +12,11 @@ */ package org.openhab.binding.network.internal.utils; +import java.util.Optional; + import org.junit.Assert; import org.junit.Test; -import java.util.Optional; - /** * Tests the parser which extracts latency values from the output of the ping command. * @@ -44,14 +44,10 @@ public void parseLinuxAndMacResultNotFoundTest() { LatencyParser latencyParser = new LatencyParser(); // This is the output of the command. We exclude the line which contains the latency, because here we want // to test that no latency is returned for all other lines. - String[] inputLines = { - "ping -c 1 192.168.1.1", - "PING 192.168.1.1 (192.168.1.1): 56 data bytes", + String[] inputLines = { "ping -c 1 192.168.1.1", "PING 192.168.1.1 (192.168.1.1): 56 data bytes", // "64 bytes from 192.168.1.1: icmp_seq=0 ttl=64 time=1.225 ms", - "--- 192.168.1.1 ping statistics ---", - "1 packets transmitted, 1 packets received, 0.0% packet loss", - "round-trip min/avg/max/stddev = 1.225/1.225/1.225/0.000 ms" - }; + "--- 192.168.1.1 ping statistics ---", "1 packets transmitted, 1 packets received, 0.0% packet loss", + "round-trip min/avg/max/stddev = 1.225/1.225/1.225/0.000 ms" }; for (String inputLine : inputLines) { // Act diff --git a/bundles/org.openhab.binding.networkupstools/pom.xml b/bundles/org.openhab.binding.networkupstools/pom.xml index c0aec4555f179..0d0797bd0d703 100644 --- a/bundles/org.openhab.binding.networkupstools/pom.xml +++ b/bundles/org.openhab.binding.networkupstools/pom.xml @@ -1,15 +1,17 @@ - + + - 4.0.0 + 4.0.0 - - org.openhab.addons.bundles - org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT - + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + - org.openhab.binding.networkupstools + org.openhab.binding.networkupstools - openHAB Add-ons :: Bundles :: Network UPS Tools Binding + openHAB Add-ons :: Bundles :: Network UPS Tools Binding diff --git a/bundles/org.openhab.binding.networkupstools/src/main/feature/feature.xml b/bundles/org.openhab.binding.networkupstools/src/main/feature/feature.xml index d0de2604754e0..3d9189b0edcc0 100644 --- a/bundles/org.openhab.binding.networkupstools/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.networkupstools/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.networkupstools/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.networkupstools/${project.version} + diff --git a/bundles/org.openhab.binding.networkupstools/src/main/java/org/openhab/binding/networkupstools/internal/NUTDynamicChannelConfiguration.java b/bundles/org.openhab.binding.networkupstools/src/main/java/org/openhab/binding/networkupstools/internal/NUTDynamicChannelConfiguration.java index 52d95b7474d73..0dc1898bc9659 100644 --- a/bundles/org.openhab.binding.networkupstools/src/main/java/org/openhab/binding/networkupstools/internal/NUTDynamicChannelConfiguration.java +++ b/bundles/org.openhab.binding.networkupstools/src/main/java/org/openhab/binding/networkupstools/internal/NUTDynamicChannelConfiguration.java @@ -24,5 +24,4 @@ public class NUTDynamicChannelConfiguration { public String networkupstools = ""; public @Nullable String unit; - } diff --git a/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/channels.xml index 4159b0807185b..435eba8d920ff 100644 --- a/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/channels.xml @@ -8,25 +8,25 @@ String UPS alarms - + Number:Dimensionless Load on UPS (percent) - + Number:Power Current value of apparent power (Volt-Amps) - + Number:Power Current value of real power (Watts) - + String @@ -52,91 +52,91 @@ Number:Temperature UPS temperature (degrees C) - + String Results of last self test (opaque string) - + Number:ElectricCurrent Input current (A) - + String Status relative to the thresholds - + Number:Dimensionless Load on (ePDU) input (percent of full) - + Number:Power Current sum value of all (ePDU) phases real power (W) - + String Input power quality (*** opaque) - + String Reason for last transfer to battery (*** opaque) - + Number:ElectricPotential Input voltage (V) - + String Status relative to the thresholds - + Number:ElectricCurrent Output current (A) - + Number:ElectricPotential Output voltage (V) - + Number:Dimensionless Battery charge (percent) - + Number:Time Battery runtime (seconds) - + Number:ElectricPotential Battery voltage (V) - + diff --git a/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/dynamic-channels.xml b/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/dynamic-channels.xml index 36d62ebd1f1ee..5ed6d1973c566 100644 --- a/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/dynamic-channels.xml +++ b/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/dynamic-channels.xml @@ -8,57 +8,57 @@ String String channel - - + + Number Number channel - - + + Number:ElectricCurrent Electric Current channel - - + + Number:ElectricPotential Electric Potential channel - - + + Number:Frequency Frequency channel - - + + Number:Power Power channel - - + + Number:Time Time channel - - + + Switch Switch channel - - + + diff --git a/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/thing-types.xml index 323a08ccc9259..3720317e0ace7 100644 --- a/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.networkupstools/src/main/resources/ESH-INF/thing/thing-types.xml @@ -10,29 +10,29 @@ Network UPS Tool Thing - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.networkupstools/src/test/java/org/openhab/binding/networkupstools/internal/NutNameChannelsTest.java b/bundles/org.openhab.binding.networkupstools/src/test/java/org/openhab/binding/networkupstools/internal/NutNameChannelsTest.java index 85adf07990812..ca0d213c03db9 100644 --- a/bundles/org.openhab.binding.networkupstools/src/test/java/org/openhab/binding/networkupstools/internal/NutNameChannelsTest.java +++ b/bundles/org.openhab.binding.networkupstools/src/test/java/org/openhab/binding/networkupstools/internal/NutNameChannelsTest.java @@ -56,11 +56,11 @@ public class NutNameChannelsTest { private static final String TEMPLATE_ITEM_TYPE = "%s"; private static final String TEMPLATE_LABEL = ""; private static final String TEMPLATE_DESCRIPTION = "%s"; - private static final String TEMPLATE_STATE = ""; - private static final String TEMPLATE_STATE_NO_PATTERN = ""; + private static final String TEMPLATE_STATE = ""; + private static final String TEMPLATE_STATE_NO_PATTERN = ""; private static final String TEMPLATE_STATE_OPTIONS = ""; private static final String TEMPLATE_CHANNEL_TYPE_END = ""; - private static final String TEMPLATE_CHANNEL = ""; + private static final String TEMPLATE_CHANNEL = ""; private static final String README_IS_ADVANCED = "yes"; @@ -221,5 +221,4 @@ private String nutNameToPattern(final String itemType) { } return pattern; } - } diff --git a/bundles/org.openhab.binding.networkupstools/src/test/java/org/openhab/binding/networkupstools/internal/nut/NutApiTest.java b/bundles/org.openhab.binding.networkupstools/src/test/java/org/openhab/binding/networkupstools/internal/nut/NutApiTest.java index 777b0b6c4f6c7..b90ff77412023 100644 --- a/bundles/org.openhab.binding.networkupstools/src/test/java/org/openhab/binding/networkupstools/internal/nut/NutApiTest.java +++ b/bundles/org.openhab.binding.networkupstools/src/test/java/org/openhab/binding/networkupstools/internal/nut/NutApiTest.java @@ -102,5 +102,4 @@ public void write(int b) throws IOException { assertThat("Should send commands correctly", actualCommands.toString(), is(expectedCommands)); } } - } diff --git a/bundles/org.openhab.binding.nibeheatpump/pom.xml b/bundles/org.openhab.binding.nibeheatpump/pom.xml index 6a83496fd337e..1a05d8c994c19 100644 --- a/bundles/org.openhab.binding.nibeheatpump/pom.xml +++ b/bundles/org.openhab.binding.nibeheatpump/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.nibeheatpump diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/feature/feature.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/feature/feature.xml index 51c50b1b34862..13bdb7587afed 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.nibeheatpump/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.nibeheatpump/${project.version} + diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpCommandResult.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpCommandResult.java index 6146301ce0ecd..fd71f7b86e0bd 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpCommandResult.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpCommandResult.java @@ -53,7 +53,6 @@ public boolean isDone() { } finally { lock.unlock(); } - } @Override diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpException.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpException.java index ce0b5578868e3..896ba3632d58c 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpException.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpException.java @@ -32,5 +32,4 @@ public NibeHeatPumpException(String message, Throwable cause) { public NibeHeatPumpException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpHandlerFactory.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpHandlerFactory.java index 4215cf23eb486..960769853e5fc 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpHandlerFactory.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/NibeHeatPumpHandlerFactory.java @@ -14,14 +14,19 @@ import static org.openhab.binding.nibeheatpump.internal.NibeHeatPumpBindingConstants.SUPPORTED_THING_TYPES_UIDS; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.nibeheatpump.internal.handler.NibeHeatPumpHandler; import org.openhab.binding.nibeheatpump.internal.models.PumpModel; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link NibeHeatPumpHandlerFactory} is responsible for creating things and @@ -29,20 +34,28 @@ * * @author Pauli Anttila - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.nibeheatpump") public class NibeHeatPumpHandlerFactory extends BaseThingHandlerFactory { + private final SerialPortManager serialPortManager; + + @Activate + public NibeHeatPumpHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { - return new NibeHeatPumpHandler(thing, parsePumpModel(thing)); + return new NibeHeatPumpHandler(thing, parsePumpModel(thing), serialPortManager); } return null; diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/ConnectorFactory.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/ConnectorFactory.java deleted file mode 100644 index 1b0e2bc49ee98..0000000000000 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/ConnectorFactory.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeheatpump.internal.connection; - -import static org.openhab.binding.nibeheatpump.internal.NibeHeatPumpBindingConstants.*; - -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException; - -/** - * The {@link ConnectorFactory} implements factory class to create Nibe connectors. - * - * - * @author Pauli Anttila - Initial contribution - */ -public class ConnectorFactory { - - public static NibeHeatPumpConnector getConnector(ThingTypeUID type) throws NibeHeatPumpException { - if (type != null) { - if (THING_TYPE_F1X45_UDP.equals(type) || THING_TYPE_F1X55_UDP.equals(type) - || THING_TYPE_F750_UDP.equals(type) || THING_TYPE_F470_UDP.equals(type)) { - return new UDPConnector(); - } else if (THING_TYPE_F1X45_SERIAL.equals(type) || THING_TYPE_F1X55_SERIAL.equals(type) - || THING_TYPE_F750_SERIAL.equals(type) || THING_TYPE_F470_SERIAL.equals(type)) { - return new SerialConnector(); - } else if (THING_TYPE_F1X45_SIMULATOR.equals(type) || THING_TYPE_F1X55_SIMULATOR.equals(type) - || THING_TYPE_F750_SIMULATOR.equals(type) || THING_TYPE_F470_SIMULATOR.equals(type)) { - return new SimulatorConnector(); - } - } - - String description = String.format("Unknown connector type %s", type); - throw new NibeHeatPumpException(description); - } -} diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/NibeHeatPumpConnector.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/NibeHeatPumpConnector.java index a533c902fd278..038345cb4931f 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/NibeHeatPumpConnector.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/NibeHeatPumpConnector.java @@ -67,5 +67,4 @@ public interface NibeHeatPumpConnector { * @return true, if connected */ boolean isConnected(); - } diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/NibeHeatPumpEventListener.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/NibeHeatPumpEventListener.java index a9a4e41ace355..3594a1343cad4 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/NibeHeatPumpEventListener.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/NibeHeatPumpEventListener.java @@ -36,5 +36,4 @@ public interface NibeHeatPumpEventListener { * Error occurred. */ void errorOccurred(String error); - } diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SerialConnector.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SerialConnector.java index e9da07f984b5e..9c1e53d73d81c 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SerialConnector.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SerialConnector.java @@ -21,8 +21,14 @@ import java.util.List; import java.util.TooManyListenersException; -import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.core.util.HexUtils; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException; import org.openhab.binding.nibeheatpump.internal.config.NibeHeatPumpConfiguration; import org.openhab.binding.nibeheatpump.internal.message.MessageFactory; @@ -35,14 +41,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * Connector for serial port communication. * @@ -55,14 +53,16 @@ public class SerialConnector extends NibeHeatPumpBaseConnector { private InputStream in; private OutputStream out; private SerialPort serialPort; + private final SerialPortManager serialPortManager; private Thread readerThread; private NibeHeatPumpConfiguration conf; private final List readQueue = new ArrayList<>(); private final List writeQueue = new ArrayList<>(); - SerialConnector() { + public SerialConnector(SerialPortManager serialPortManager) { logger.debug("Nibe heatpump Serial Port message listener created"); + this.serialPortManager = serialPortManager; } @Override @@ -73,7 +73,10 @@ public void connect(NibeHeatPumpConfiguration configuration) throws NibeHeatPump conf = configuration; try { - CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(conf.serialPort); + SerialPortIdentifier portIdentifier = serialPortManager.getIdentifier(conf.serialPort); + if (portIdentifier == null) { + throw new NibeHeatPumpException("Connection failed, no such port: " + conf.serialPort); + } serialPort = portIdentifier.open(this.getClass().getName(), 2000); serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); @@ -88,12 +91,10 @@ public void connect(NibeHeatPumpConfiguration configuration) throws NibeHeatPump if (in.markSupported()) { in.reset(); } - } catch (NoSuchPortException e) { - throw new NibeHeatPumpException("Connection failed, no such a port", e); } catch (PortInUseException e) { - throw new NibeHeatPumpException("Connection failed, port in use", e); + throw new NibeHeatPumpException("Connection failed, port in use: " + conf.serialPort, e); } catch (UnsupportedCommOperationException | IOException e) { - throw new NibeHeatPumpException("Connection failed, reason: {}" + e.getMessage(), e); + throw new NibeHeatPumpException("Connection failed, reason: " + e.getMessage(), e); } readQueue.clear(); @@ -107,18 +108,28 @@ public void connect(NibeHeatPumpConfiguration configuration) throws NibeHeatPump @Override public void disconnect() { logger.debug("Disconnecting"); - serialPort.removeEventListener(); + if (serialPort != null) { + serialPort.removeEventListener(); + } if (readerThread != null) { logger.debug("Interrupt serial listener"); readerThread.interrupt(); } if (out != null) { logger.debug("Close serial out stream"); - IOUtils.closeQuietly(out); + try { + out.close(); + } catch (IOException e) { + logger.debug("Error while closing the output stream: {}", e.getMessage()); + } } if (in != null) { logger.debug("Close serial in stream"); - IOUtils.closeQuietly(in); + try { + in.close(); + } catch (IOException e) { + logger.debug("Error while closing the input stream: {}", e.getMessage()); + } } if (serialPort != null) { logger.debug("Close serial port"); @@ -161,7 +172,6 @@ public class SerialReader extends Thread implements SerialPortEventListener { public void interrupt() { interrupted = true; super.interrupt(); - IOUtils.closeQuietly(in); } @Override diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SimulatorConnector.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SimulatorConnector.java index 0e5eb21646d36..6fa3888165c16 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SimulatorConnector.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/connection/SimulatorConnector.java @@ -75,7 +75,7 @@ public class SimulatorConnector extends NibeHeatPumpBaseConnector { private final Map cache = Collections.synchronizedMap(new HashMap<>()); - SimulatorConnector() { + public SimulatorConnector() { logger.debug("Nibe heatpump Test message listener created"); } diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandler.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandler.java index 14a6536c54e61..5baf99014200d 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandler.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandler.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.nibeheatpump.internal.handler; +import static org.openhab.binding.nibeheatpump.internal.NibeHeatPumpBindingConstants.*; + import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; @@ -34,17 +36,21 @@ import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpCommandResult; import org.openhab.binding.nibeheatpump.internal.NibeHeatPumpException; import org.openhab.binding.nibeheatpump.internal.config.NibeHeatPumpConfiguration; -import org.openhab.binding.nibeheatpump.internal.connection.ConnectorFactory; import org.openhab.binding.nibeheatpump.internal.connection.NibeHeatPumpConnector; import org.openhab.binding.nibeheatpump.internal.connection.NibeHeatPumpEventListener; +import org.openhab.binding.nibeheatpump.internal.connection.SerialConnector; +import org.openhab.binding.nibeheatpump.internal.connection.SimulatorConnector; +import org.openhab.binding.nibeheatpump.internal.connection.UDPConnector; import org.openhab.binding.nibeheatpump.internal.message.ModbusDataReadOutMessage; import org.openhab.binding.nibeheatpump.internal.message.ModbusReadRequestMessage; import org.openhab.binding.nibeheatpump.internal.message.ModbusReadResponseMessage; @@ -70,6 +76,7 @@ public class NibeHeatPumpHandler extends BaseThingHandler implements NibeHeatPum private static final int TIMEOUT = 4500; private final Logger logger = LoggerFactory.getLogger(NibeHeatPumpHandler.class); private final PumpModel pumpModel; + private final SerialPortManager serialPortManager; private final List itemsToPoll = Collections.synchronizedList(new ArrayList<>()); private final List itemsToEnableWrite = new ArrayList<>(); private final Map stateMap = Collections.synchronizedMap(new HashMap<>()); @@ -135,9 +142,28 @@ && getThing().getStatusInfo().getStatus() == ThingStatus.ONLINE) { private ScheduledFuture pollingJob; private long lastUpdateTime = 0; - public NibeHeatPumpHandler(Thing thing, PumpModel pumpModel) { + public NibeHeatPumpHandler(Thing thing, PumpModel pumpModel, SerialPortManager serialPortManager) { super(thing); this.pumpModel = pumpModel; + this.serialPortManager = serialPortManager; + } + + private NibeHeatPumpConnector getConnector() throws NibeHeatPumpException { + ThingTypeUID type = thing.getThingTypeUID(); + + if (THING_TYPE_F1X45_UDP.equals(type) || THING_TYPE_F1X55_UDP.equals(type) || THING_TYPE_F750_UDP.equals(type) + || THING_TYPE_F470_UDP.equals(type)) { + return new UDPConnector(); + } else if (THING_TYPE_F1X45_SERIAL.equals(type) || THING_TYPE_F1X55_SERIAL.equals(type) + || THING_TYPE_F750_SERIAL.equals(type) || THING_TYPE_F470_SERIAL.equals(type)) { + return new SerialConnector(serialPortManager); + } else if (THING_TYPE_F1X45_SIMULATOR.equals(type) || THING_TYPE_F1X55_SIMULATOR.equals(type) + || THING_TYPE_F750_SIMULATOR.equals(type) || THING_TYPE_F470_SIMULATOR.equals(type)) { + return new SimulatorConnector(); + } + + String description = String.format("Unknown connector type %s", type); + throw new NibeHeatPumpException(description); } @Override @@ -260,7 +286,7 @@ public void initialize() { try { parseWriteEnabledItems(); - connector = ConnectorFactory.getConnector(thing.getThingTypeUID()); + connector = getConnector(); } catch (IllegalArgumentException | NibeHeatPumpException e) { String description = String.format("Illegal configuration, %s", e.getMessage()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, description); diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/message/NibeHeatPumpBaseMessage.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/message/NibeHeatPumpBaseMessage.java index e13e1d66e13ec..c8646f8ce39d0 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/message/NibeHeatPumpBaseMessage.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/message/NibeHeatPumpBaseMessage.java @@ -52,7 +52,6 @@ public enum MessageType { public byte toByte() { return (byte) msgType; } - } public byte[] rawMessage; @@ -89,5 +88,4 @@ public String toHexString() { return HexUtils.bytesToHex(rawMessage); } } - } diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F1X45.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F1X45.java index cc77afc9dd637..505ee0ee6e6d7 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F1X45.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F1X45.java @@ -31,7 +31,7 @@ public class F1X45 { private static final Map VARIABLE_INFO_F1X45 = Collections .unmodifiableMap(new HashMap() { { - // @formatter:off + // @formatter:off put(40004, new VariableInformation( 10, NibeDataType.S16, Type.SENSOR , "BT1 Outdoor temp")); put(40005, new VariableInformation( 10, NibeDataType.S16, Type.SENSOR , "EP23-BT2 Supply temp S4")); put(40006, new VariableInformation( 10, NibeDataType.S16, Type.SENSOR , "EP22-BT2 Supply temp S3")); diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F1X55.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F1X55.java index b47c3f8a9cc05..c94f5ba68bef7 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F1X55.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F1X55.java @@ -12,13 +12,13 @@ */ package org.openhab.binding.nibeheatpump.internal.models; -import org.openhab.binding.nibeheatpump.internal.models.VariableInformation.NibeDataType; -import org.openhab.binding.nibeheatpump.internal.models.VariableInformation.Type; - import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.openhab.binding.nibeheatpump.internal.models.VariableInformation.NibeDataType; +import org.openhab.binding.nibeheatpump.internal.models.VariableInformation.Type; + /** * Class which holds all data variables of F1x55 heat pumps. * @@ -31,7 +31,7 @@ public class F1X55 { private static final Map VARIABLE_INFO_F1X55 = Collections .unmodifiableMap(new HashMap() { { - // @formatter:off + // @formatter:off put(32260, new VariableInformation( 1, NibeDataType.U8 , Type.SENSOR , "NIBE Inverter 216-state")); put(40004, new VariableInformation( 10, NibeDataType.S16, Type.SENSOR , "BT1 Outdoor Temperature")); put(40005, new VariableInformation( 10, NibeDataType.S16, Type.SENSOR , "EP23-BT2 Supply temp S4")); diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F750.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F750.java index 6ea83fde56823..6e61e68ec1509 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F750.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/models/F750.java @@ -31,7 +31,7 @@ public class F750 { private static final Map VARIABLE_INFO_F750 = Collections .unmodifiableMap(new HashMap() { { - // @formatter:off + // @formatter:off put(32260, new VariableInformation( 1, NibeDataType.U8 , Type.SENSOR , "NIBE Inverter 216-state")); put(40004, new VariableInformation( 10, NibeDataType.S16, Type.SENSOR , "BT1 Outdoor Temperature")); put(40005, new VariableInformation( 10, NibeDataType.S16, Type.SENSOR , "EP23-BT2 Supply temp S4")); diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/protocol/NibeHeatPumpProtocolStates.java b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/protocol/NibeHeatPumpProtocolStates.java index 8dd958493a0dd..4f7aefd46f300 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/protocol/NibeHeatPumpProtocolStates.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/java/org/openhab/binding/nibeheatpump/internal/protocol/NibeHeatPumpProtocolStates.java @@ -80,7 +80,6 @@ public boolean process(NibeHeatPumpProtocolContext context) { } return false; } - }, OK_MESSAGE_RECEIVED { @Override @@ -102,7 +101,6 @@ public boolean process(NibeHeatPumpProtocolContext context) { } return true; } - }, WRITE_TOKEN_RECEIVED { @Override @@ -112,7 +110,6 @@ public boolean process(NibeHeatPumpProtocolContext context) { context.state(WAIT_START); return true; } - }, READ_TOKEN_RECEIVED { @Override @@ -122,7 +119,6 @@ public boolean process(NibeHeatPumpProtocolContext context) { context.state(WAIT_START); return true; } - }, CHECKSUM_FAILURE { @Override diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/binding/binding.xml index 17178e7453a2b..1ade6b609ffa5 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - NibeHeatPump Binding diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45-channel-groups.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45-channel-groups.xml index ca27f6ebe49e4..c0dc5e05427aa 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45-channel-groups.xml @@ -1,748 +1,749 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45-types.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45-types.xml index 7e961f4327a9c..294bc219c14e4 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45-types.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45-types.xml @@ -1,5 +1,6 @@ - @@ -461,7 +462,8 @@ String - Indicates what heating action (HW/heat/pool) currently prioritised 10=Off 20=Hot Water 30=Heat 40=Pool 41=Pool 2 50=Transfer 60=Cooling + Indicates what heating action (HW/heat/pool) currently prioritised 10=Off 20=Hot Water 30=Heat 40=Pool + 41=Pool 2 50=Transfer 60=Cooling @@ -2961,7 +2963,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -2975,7 +2978,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -2989,7 +2993,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3003,7 +3008,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3017,7 +3023,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3031,7 +3038,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3045,7 +3053,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3059,7 +3068,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3073,7 +3083,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3087,7 +3098,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3101,7 +3113,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3115,7 +3128,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3129,7 +3143,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3143,7 +3158,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3157,7 +3173,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3171,7 +3188,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3185,7 +3203,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -3199,7 +3218,8 @@ String - Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 = Pool2 + Indicates what need is assigned to the compressor module, 0 = Off, 1 = Heat, 2 = Hot water, 3 = Pool 1, 4 + = Pool2 @@ -4028,7 +4048,8 @@ String - Display language in the heat pump 0=English 1=Svenska 2=Deutsch 3=Francais 4=Espanol 5=Suomi 6=Lietuviu 7=Cesky 8=Polski 9=Nederlands 10=Norsk 11=Dansk 12=Eesti 13=Latviesu 16=Magyar + Display language in the heat pump 0=English 1=Svenska 2=Deutsch 3=Francais 4=Espanol 5=Suomi 6=Lietuviu + 7=Cesky 8=Polski 9=Nederlands 10=Norsk 11=Dansk 12=Eesti 13=Latviesu 16=Magyar @@ -4650,13 +4671,15 @@ Switch - Lowers the room temperature during red light alarms to notify the occupants of the building that something is the matter 0=Off 1=On + Lowers the room temperature during red light alarms to notify the occupants of the building that + something is the matter 0=Off 1=On Switch - Lowers the hot water temperature during red light alarms to notify the occupants of the building that something is the matter 0=Off 1=On + Lowers the hot water temperature during red light alarms to notify the occupants of the building that + something is the matter 0=Off 1=On @@ -4714,28 +4737,32 @@ Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. @@ -4959,7 +4986,8 @@ Number - The value below the last compressor step the degree minutes needed to be reached for the pump to start electric addition + The value below the last compressor step the degree minutes needed to be reached for the pump to start + electric addition diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45.xml index bb14023e3308b..a68cfaffb56c0 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x45.xml @@ -9,8 +9,8 @@ - - + + @@ -57,7 +57,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 @@ -69,8 +70,8 @@ - - + + @@ -117,7 +118,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 @@ -128,8 +130,8 @@ - - + + @@ -157,7 +159,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55-channel-groups.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55-channel-groups.xml index 14505d4ee76e7..95d6500689dc0 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55-channel-groups.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55-types.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55-types.xml index 31420fd6647cf..f40cc454475b9 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55-types.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55-types.xml @@ -1,5 +1,6 @@ - @@ -665,7 +666,8 @@ Number Indicates the status of the relays on the ERS accessory. The information is binary encoded. b0: K1, - b1: K2, b2: K3, b3: K4 + b1: + K2, b2: K3, b3: K4 @@ -905,7 +907,8 @@ Number Bitmap telling the reason to why the compressor slows down. b0:inverter b1:brine b2:current b3:high - cond b4:hot gas b5:evaporator + cond + b4:hot gas b5:evaporator @@ -2087,7 +2090,8 @@ Number Indicates the status of the relays on the ERS accessory. The information is binary encoded. b0: K1, - b1: K2, b2: K3, b3: K4 + b1: + K2, b2: K3, b3: K4 @@ -2096,7 +2100,8 @@ Number Indicates the status of the relays on the ERS accessory. The information is binary encoded. b0: K1, - b1: K2, b2: K3, b3: K4 + b1: + K2, b2: K3, b3: K4 @@ -2105,7 +2110,8 @@ Number Indicates the status of the relays on the ERS accessory. The information is binary encoded. b0: K1, - b1: K2, b2: K3, b3: K4 + b1: + K2, b2: K3, b3: K4 @@ -2303,7 +2309,8 @@ Number Degree minutes, 16bit value (-32768 < x < 32767). Values outside valid values are rounded to - the closest valid value. + the + closest valid value. @@ -2389,7 +2396,8 @@ String Indicates what heating action (HW/heat/pool) currently prioritised 10=Off 20=Hot Water 30=Heat - 40=Pool 41=Pool 2 50=Transfer 60=Cooling + 40=Pool + 41=Pool 2 50=Transfer 60=Cooling @@ -2754,7 +2762,8 @@ String Indicates active relays on the PCA Base card. Please refer to the wiring diagram for relay - description. Binary encoded. 1=on, 0=off. Bit0=K4,Bit1=K3,Bit2=K2,Bit3=K1 + description. + Binary encoded. 1=on, 0=off. Bit0=K4,Bit1=K3,Bit2=K2,Bit3=K1 @@ -3576,7 +3585,8 @@ String Display language in the heat pump 0=English 1=Svenska 2=Deutsch 3=Francais 4=Espanol 5=Suomi - 6=Lietuviu 7=Cesky 8=Polski 9=Nederlands 10=Norsk 11=Dansk 12=Eesti 13=Latviesu 16=Magyar + 6=Lietuviu + 7=Cesky 8=Polski 9=Nederlands 10=Norsk 11=Dansk 12=Eesti 13=Latviesu 16=Magyar @@ -3952,7 +3962,8 @@ Number Minimum time between defrost in FLM 1|Minimum time between defrost in FLM 2|Minimum time between - defrost in FLM 3|Minimum time between defrost in FLM 4 + defrost + in FLM 3|Minimum time between defrost in FLM 4 @@ -4264,7 +4275,8 @@ Switch Lowers the hot water temperature during red light alarms to notify the occupants of the building - that something is the matter 0=Off 1=On + that + something is the matter 0=Off 1=On @@ -4402,7 +4414,8 @@ String Preset flow setting for climate system. 0 = manual setting, 1 = radiator, 2 = floor heating, 3 = - radiator + floor heating. + radiator + + floor heating. @@ -4593,7 +4606,8 @@ Number The value below the last compressor step the degree minutes needed to be reached for the pump to - start electric addition + start + electric addition @@ -4790,7 +4804,8 @@ Switch Sets if the valve should be used or not in cooling mode. Only applies if cooling is available in - the system + the + system @@ -4798,7 +4813,8 @@ Switch Sets if the valve should be used or not in cooling mode. Only applies if cooling is available in - the system + the + system @@ -4806,7 +4822,8 @@ Switch Sets if the valve should be used or not in cooling mode. Only applies if cooling is available in - the system + the + system @@ -4814,7 +4831,8 @@ Number Sets if the valve should be used or not in cooling mode. Only applies if cooling is available in - the system + the + system @@ -5269,7 +5287,8 @@ Switch Sets if the valve should be used or not in cooling mode. Only applies if cooling is available in - the system + the + system @@ -5277,7 +5296,8 @@ Switch Sets if the valve should be used or not in cooling mode. Only applies if cooling is available in - the system + the + system @@ -5285,7 +5305,8 @@ Switch Sets if the valve should be used or not in cooling mode. Only applies if cooling is available in - the system + the + system @@ -5293,7 +5314,8 @@ Switch Sets if the valve should be used or not in cooling mode. Only applies if cooling is available in - the system + the + system @@ -5301,7 +5323,8 @@ Switch Sets if the valve should be used or not in heating mode. Only applies if cooling is available in - the system. Otherwise the valve is always used in heating mode. + the + system. Otherwise the valve is always used in heating mode. @@ -5309,7 +5332,8 @@ Switch Sets if the valve should be used or not in heating mode. Only applies if cooling is available in - the system. Otherwise the valve is always used in heating mode. + the + system. Otherwise the valve is always used in heating mode. @@ -5317,7 +5341,8 @@ Switch Sets if the valve should be used or not in heating mode. Only applies if cooling is available in - the system. Otherwise the valve is always used in heating mode. + the + system. Otherwise the valve is always used in heating mode. @@ -5325,7 +5350,8 @@ Switch Sets if the valve should be used or not in heating mode. Only applies if cooling is available in - the system. Otherwise the valve is always used in heating mode. + the + system. Otherwise the valve is always used in heating mode. @@ -5333,7 +5359,8 @@ Switch Sets if the valve should be used or not in heating mode. Only applies if cooling is available in - the system. Otherwise the valve is always used in heating mode. + the + system. Otherwise the valve is always used in heating mode. @@ -5341,7 +5368,8 @@ Switch Sets if the valve should be used or not in heating mode. Only applies if cooling is available in - the system. Otherwise the valve is always used in heating mode. + the + system. Otherwise the valve is always used in heating mode. @@ -5349,7 +5377,8 @@ Switch Sets if the valve should be used or not in heating mode. Only applies if cooling is available in - the system. Otherwise the valve is always used in heating mode. + the + system. Otherwise the valve is always used in heating mode. @@ -5357,7 +5386,8 @@ Switch Sets if the valve should be used or not in heating mode. Only applies if cooling is available in - the system. Otherwise the valve is always used in heating mode. + the + system. Otherwise the valve is always used in heating mode. @@ -6340,7 +6370,8 @@ Switch Smart energy source, fixed electricity price part source, if spot electricity price are used. 0 = - fixed price. 1 = tariff. + fixed + price. 1 = tariff. @@ -6355,7 +6386,8 @@ Switch Smart energy source, shunted addition price part source. From tariff or fixed price. 0 = fixed - price. 1 = tariff. + price. 1 = + tariff. diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55.xml index 10d11511c9895..1afdb4d721e61 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f1x55.xml @@ -9,8 +9,8 @@ - - + + @@ -57,7 +57,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 @@ -69,8 +70,8 @@ - - + + @@ -117,7 +118,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 @@ -128,8 +130,8 @@ - - + + @@ -157,7 +159,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470-channel-groups.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470-channel-groups.xml index c8de97f0ab646..24112dce59922 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470-channel-groups.xml @@ -7,498 +7,498 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470-types.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470-types.xml index dd822c4443bd6..99aef58972981 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470-types.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> Number @@ -1478,7 +1478,8 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ String - Indicates what heating action (HW/heat/pool) currently prioritised 10=Off 20=Hot Water 30=Heat 40=Pool 41=Pool 2 50=Transfer 60=Cooling + Indicates what heating action (HW/heat/pool) currently prioritised 10=Off 20=Hot Water 30=Heat 40=Pool + 41=Pool 2 50=Transfer 60=Cooling @@ -1664,7 +1665,8 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ String - Indicates active relays on the PCA Base card. Please refer to the wiring diagram for relay description. Binary encoded. 1=on, 0=off. Bit0=K4,Bit1=K3,Bit2=K2,Bit3=K1 + Indicates active relays on the PCA Base card. Please refer to the wiring diagram for relay description. + Binary encoded. 1=on, 0=off. Bit0=K4,Bit1=K3,Bit2=K2,Bit3=K1 @@ -2186,7 +2188,8 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ String - Display language in the heat pump 0=English 1=Svenska 2=Deutsch 3=Francais 4=Espanol 5=Suomi 6=Lietuviu 7=Cesky 8=Polski 9=Nederlands 10=Norsk 11=Dansk 12=Eesti 13=Latviesu 16=Magyar + Display language in the heat pump 0=English 1=Svenska 2=Deutsch 3=Francais 4=Espanol 5=Suomi 6=Lietuviu + 7=Cesky 8=Polski 9=Nederlands 10=Norsk 11=Dansk 12=Eesti 13=Latviesu 16=Magyar @@ -2458,7 +2461,8 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ Number - Above the set outdoor temperature the addition activation time is limited to give the compressor more time to raise the hot water temperature. + Above the set outdoor temperature the addition activation time is limited to give the compressor more + time to raise the hot water temperature. @@ -2678,13 +2682,15 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ Switch - Lowers the room temperature during red light alarms to notify the occupants of the building that something is the matter 0=Off 1=On + Lowers the room temperature during red light alarms to notify the occupants of the building that + something is the matter 0=Off 1=On Switch - Lowers the hot water temperature during red light alarms to notify the occupants of the building that something is the matter 0=Off 1=On + Lowers the hot water temperature during red light alarms to notify the occupants of the building that + something is the matter 0=Off 1=On @@ -2742,35 +2748,40 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. String - Preset flow setting for climate system. 0 = manual setting, 1 = radiator, 2 = floor heating, 3 = radiator + floor heating. + Preset flow setting for climate system. 0 = manual setting, 1 = radiator, 2 = floor heating, 3 = radiator + + floor heating. @@ -3176,28 +3187,32 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. @@ -3274,49 +3289,57 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ Switch - + + Switch - + + Switch - + + Switch - + + Switch - + + Switch - + + Switch - + + Switch - + + @@ -3328,14 +3351,16 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ Number - Setting of how much the difference between set and actual room humidity should affect the supply temperature. + Setting of how much the difference between set and actual room humidity should affect the supply + temperature. Number - Setting of how much the difference between set and actual room humidity should affect the supply temperature in cooling mode. + Setting of how much the difference between set and actual room humidity should affect the supply + temperature in cooling mode. @@ -3379,7 +3404,8 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https:/ Switch - + + diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470.xml index 91a89b18bd493..0289070610557 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f470.xml @@ -9,8 +9,8 @@ - - + + @@ -57,7 +57,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 @@ -69,8 +70,8 @@ - - + + @@ -117,7 +118,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 @@ -128,8 +130,8 @@ - - + + @@ -157,7 +159,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750-channel-groups.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750-channel-groups.xml index d238f2be2ae7f..351fe6738fc3a 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750-channel-groups.xml @@ -1,656 +1,657 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750-types.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750-types.xml index 48133727d8511..6d2e252007e9d 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750-types.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750-types.xml @@ -1,5 +1,6 @@ - @@ -700,7 +701,7 @@ - + @@ -1771,7 +1772,8 @@ Number - Degree minutes, 16bit value (-32768 < x < 32767). Values outside valid values are rounded to the closest valid value. + Degree minutes, 16bit value (-32768 < x < 32767). Values outside valid values are rounded to the + closest valid value. @@ -1865,7 +1867,8 @@ String - Indicates what heating action (HW/heat/pool) currently prioritised 10=Off 20=Hot Water 30=Heat 40=Pool 41=Pool 2 50=Transfer 60=Cooling + Indicates what heating action (HW/heat/pool) currently prioritised 10=Off 20=Hot Water 30=Heat 40=Pool + 41=Pool 2 50=Transfer 60=Cooling @@ -2168,7 +2171,8 @@ String - Indicates active relays on the PCA Base card. Please refer to the wiring diagram for relay description. Binary encoded. 1=on, 0=off. Bit0=K4,Bit1=K3,Bit2=K2,Bit3=K1 + Indicates active relays on the PCA Base card. Please refer to the wiring diagram for relay description. + Binary encoded. 1=on, 0=off. Bit0=K4,Bit1=K3,Bit2=K2,Bit3=K1 @@ -2200,7 +2204,8 @@ Number - Indicates the status of the relays on the external supply air accessory. The information is binary encoded. B0: relay K1 (QN40 close signal). B1: relay K2 (QN40 open signal) + Indicates the status of the relays on the external supply air accessory. The information is binary + encoded. B0: relay K1 (QN40 close signal). B1: relay K2 (QN40 open signal) @@ -2242,7 +2247,8 @@ Number - Indicates the status of the relays on the SCA accessory. The information is binary encoded. B0: relay K1 (Solar pump). B1: relay K2 (Solar Cooling Pump) B2: relay K3 (QN28) + Indicates the status of the relays on the SCA accessory. The information is binary encoded. B0: relay K1 + (Solar pump). B1: relay K2 (Solar Cooling Pump) B2: relay K3 (QN28) @@ -2876,7 +2882,8 @@ String - Display language in the heat pump 0=English 1=Svenska 2=Deutsch 3=Francais 4=Espanol 5=Suomi 6=Lietuviu 7=Cesky 8=Polski 9=Nederlands 10=Norsk 11=Dansk 12=Eesti 13=Latviesu 16=Magyar + Display language in the heat pump 0=English 1=Svenska 2=Deutsch 3=Francais 4=Espanol 5=Suomi 6=Lietuviu + 7=Cesky 8=Polski 9=Nederlands 10=Norsk 11=Dansk 12=Eesti 13=Latviesu 16=Magyar @@ -3439,13 +3446,15 @@ Switch - Lowers the room temperature during red light alarms to notify the occupants of the building that something is the matter 0=Off 1=On + Lowers the room temperature during red light alarms to notify the occupants of the building that + something is the matter 0=Off 1=On Switch - Lowers the hot water temperature during red light alarms to notify the occupants of the building that something is the matter 0=Off 1=On + Lowers the hot water temperature during red light alarms to notify the occupants of the building that + something is the matter 0=Off 1=On @@ -3503,35 +3512,40 @@ Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. String - Preset flow setting for climate system. 0 = manual setting, 1 = radiator, 2 = floor heating, 3 = radiator + floor heating. + Preset flow setting for climate system. 0 = manual setting, 1 = radiator, 2 = floor heating, 3 = radiator + + floor heating. @@ -3602,7 +3616,8 @@ Number - The value below the last compressor step the degree minutes needed to be reached for the pump to start electric addition + The value below the last compressor step the degree minutes needed to be reached for the pump to start + electric addition @@ -3630,42 +3645,48 @@ Number - The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 and T3. + The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 + and T3. Number - The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 and T3. + The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 + and T3. Number - The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 and T3. + The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 + and T3. Number - The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 and T3. + The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 + and T3. Number - The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 and T3. + The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 + and T3. Number - The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 and T3. + The supply air curve is defined by 3 supply air temperatures at 3 different outdoor temperatures T1, T2 + and T3. @@ -4103,28 +4124,32 @@ Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. Number - Setting of how much the difference between set and actual room temperature should affect the supply temperature. + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. @@ -4207,55 +4232,64 @@ Switch - + + Switch - + + Switch - + + Switch - + + Switch - + + Switch - + + Switch - + + Switch - + + Switch - If set, swapping the words in 32-bit variables when value requested via ''read holding register'' commando. + If set, swapping the words in 32-bit variables when value requested via ''read holding register'' + commando. @@ -4314,14 +4348,16 @@ Number - Setting of how much the difference between set and actual room humidity should affect the supply temperature. + Setting of how much the difference between set and actual room humidity should affect the supply + temperature. Number - Setting of how much the difference between set and actual room humidity should affect the supply temperature in cooling mode. + Setting of how much the difference between set and actual room humidity should affect the supply + temperature in cooling mode. @@ -4449,7 +4485,8 @@ Switch - + + diff --git a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750.xml b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750.xml index 9526c0bc672c4..68a8bc0b827ef 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750.xml +++ b/bundles/org.openhab.binding.nibeheatpump/src/main/resources/ESH-INF/thing/f750.xml @@ -9,8 +9,8 @@ - - + + @@ -57,7 +57,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 @@ -69,8 +70,8 @@ - - + + @@ -117,7 +118,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 @@ -128,8 +130,8 @@ - - + + @@ -157,7 +159,8 @@ - Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle time in milliseconds. + Throttle incoming data read out messages from heat pump. 0 = throttle is disabled, otherwise throttle + time in milliseconds. 0 diff --git a/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerCommand2NibeTest.java b/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerCommand2NibeTest.java index 3998850d3322c..2473a85614d4c 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerCommand2NibeTest.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerCommand2NibeTest.java @@ -12,24 +12,27 @@ */ package org.openhab.binding.nibeheatpump.internal.handler; +import static org.junit.Assert.assertEquals; +import static org.mockito.MockitoAnnotations.initMocks; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collection; + import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.mockito.Mock; import org.openhab.binding.nibeheatpump.internal.models.PumpModel; import org.openhab.binding.nibeheatpump.internal.models.VariableInformation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; - -import static org.junit.Assert.assertEquals; - /** * Tests cases for {@link NibeHeatPumpHandler}. * @@ -40,32 +43,24 @@ public class NibeHeatPumpHandlerCommand2NibeTest { private NibeHeatPumpHandler product; // the class under test private Method m; private static String METHOD_NAME = "convertCommandToNibeValue"; - private Class[] parameterTypes; + private Class[] parameterTypes; private Object[] parameters; private int fCoilAddress; - private Command fCommand; - private int fExpected; + private @Mock SerialPortManager serialPortManager; + @Parameterized.Parameters(name = "{index}: f({0}, {1})={2}") public static Collection data() { - return Arrays.asList(new Object[][] { - { 47028, new DecimalType("-1"), (byte)0xFF }, - { 48132, new DecimalType("0"), 0 }, - { 48132, new StringType("0"), 0 }, - { 43009, new DecimalType("28.7"), 0x011F }, - { 40004, new DecimalType("-0.1"), (short)0xFFFF }, - { 47418, new DecimalType("75"), 0x004B }, - { 43514, new DecimalType("7"), 0x0007 }, - { 47291, new DecimalType("65535"), 0xFFFF }, - { 42437, new DecimalType("429496729.5"), 0xFFFFFFFF }, - { 42504, new DecimalType("4294967295"), 0xFFFFFFFF }, - { 47041, new StringType("1"), 0x1 }, - { 47371, OnOffType.from(true), 0x1 }, - { 47371, OnOffType.from(false), 0x0 }, - }); + return Arrays.asList(new Object[][] { { 47028, new DecimalType("-1"), (byte) 0xFF }, + { 48132, new DecimalType("0"), 0 }, { 48132, new StringType("0"), 0 }, + { 43009, new DecimalType("28.7"), 0x011F }, { 40004, new DecimalType("-0.1"), (short) 0xFFFF }, + { 47418, new DecimalType("75"), 0x004B }, { 43514, new DecimalType("7"), 0x0007 }, + { 47291, new DecimalType("65535"), 0xFFFF }, { 42437, new DecimalType("429496729.5"), 0xFFFFFFFF }, + { 42504, new DecimalType("4294967295"), 0xFFFFFFFF }, { 47041, new StringType("1"), 0x1 }, + { 47371, OnOffType.from(true), 0x1 }, { 47371, OnOffType.from(false), 0x0 }, }); } public NibeHeatPumpHandlerCommand2NibeTest(final int coilAddress, final Command command, final int expected) { @@ -76,7 +71,9 @@ public NibeHeatPumpHandlerCommand2NibeTest(final int coilAddress, final Command @Before public void setUp() throws Exception { - product = new NibeHeatPumpHandler(null, PumpModel.F1X55); + initMocks(this); + + product = new NibeHeatPumpHandler(null, PumpModel.F1X55, serialPortManager); parameterTypes = new Class[2]; parameterTypes[0] = VariableInformation.class; parameterTypes[1] = Command.class; diff --git a/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerNibe2StateTest.java b/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerNibe2StateTest.java index f40efb7f0dc53..03dd6129ee5fb 100644 --- a/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerNibe2StateTest.java +++ b/bundles/org.openhab.binding.nibeheatpump/src/test/java/org/openhab/binding/nibeheatpump/internal/handler/NibeHeatPumpHandlerNibe2StateTest.java @@ -13,6 +13,7 @@ package org.openhab.binding.nibeheatpump.internal.handler; import static org.junit.Assert.assertEquals; +import static org.mockito.MockitoAnnotations.initMocks; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -21,10 +22,12 @@ import java.util.Collection; import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import org.mockito.Mock; import org.openhab.binding.nibeheatpump.internal.models.PumpModel; import org.openhab.binding.nibeheatpump.internal.models.VariableInformation; @@ -50,6 +53,8 @@ public class NibeHeatPumpHandlerNibe2StateTest { private String fType; private String fExpected; + private @Mock SerialPortManager serialPortManager; + @Parameterized.Parameters(name = "{index}: f({0}, {1}, {3})={4}") public static Collection data() { return Arrays.asList(new Object[][] { // @@ -93,7 +98,9 @@ public NibeHeatPumpHandlerNibe2StateTest(final int coilAddress, final int value, @Before public void setUp() throws Exception { - product = new NibeHeatPumpHandler(null, PumpModel.F1X55); + initMocks(this); + + product = new NibeHeatPumpHandler(null, PumpModel.F1X55, serialPortManager); parameterTypes = new Class[3]; parameterTypes[0] = VariableInformation.class; parameterTypes[1] = int.class; diff --git a/bundles/org.openhab.binding.nibeuplink/README.md b/bundles/org.openhab.binding.nibeuplink/README.md index 06b408e7a3f1f..9719f772d1e55 100644 --- a/bundles/org.openhab.binding.nibeuplink/README.md +++ b/bundles/org.openhab.binding.nibeuplink/README.md @@ -61,10 +61,6 @@ Setting less than 60 seconds does not make any sense as the heat pump only provi interval (seconds) in which list of "dead channels" (channels that do not return any data or invalid data) should be purged (default = 3600). Usually this settings should not be changed. -- **customChannel01 - customChannel08** -allows to define up to 8 custom channels which are not covered in the basic channel list of your model. -Any number between 10000 and 50000 is allowed. - ### Examples - minimum configuration @@ -304,13 +300,27 @@ Following models/channels are currently available: | airsupply#40942 | Switch | --- | --- | No | External ERS accessory block status | | | airsupply#47260 | Number | --- | --- | Yes | Selected fan speed | 0=normal, 1=speed 1, 2=speed 2, 3=speed 3, 4=speed 4 | +### Custom Channels + +An arbitrary number of custom channels can be added via paper-ui or file based configuration. +The recommended way is to use paper-ui as this is much easier to use. +There are three custom channel types available, which allow different scaling of the raw values retrieved from the NIBE API: + +- type-number-unscaled +- type-number-scale10 +- type-number-scale100 + ## Full Example ### Thing ``` -nibeuplink:vvm320:mynibe [ user="nibe@my-domain.de", password="secret123", nibeId="4711", pollingInterval=300, customChannel01=47376, customChannel02=48009 ] +nibeuplink:vvm320:mynibe [ user="nibe@my-domain.de", password="secret123", nibeId="4711", pollingInterval=300] { + Channels: + Type type-number-scale10 : 47015 "min supply temp heating" + Type type-number-unscaled : 48177 "min supply temp cooling" +} ``` ### Items @@ -322,14 +332,15 @@ Channels which have more than two states are internally represented as number. You need to define a map file which also gives you the opportunity to translate the state into your preferred language. ``` -Number:Temperature NIBE_SUPPLY "Vorlauf" { channel="nibeuplink:vvm320:mynibe:base#40008" } -Number:Temperature NIBE_RETURN "Rücklauf [%.2f °F]" { channel="nibeuplink:vvm320:mynibe:base#40012" } -Number:Temperature NIBE_HW_TOP "Brauchwasser oben" { channel="nibeuplink:vvm320:mynibe:hotwater#40013" } -Number:Energy NIBE_HM_HEAT "WM Heizung" { channel="nibeuplink:vvm320:mynibe:base#44308" } -Switch NIBE_COMP_DEFROST "Enteisung" { channel="nibeuplink:vvm320:mynibe:compressor#44703" } -Number NIBE_HW_MODE "Modus [MAP(hwmode.map):%s]" { channel="nibeuplink:vvm320:mynibe:hotwater#47041" } - -Number NIBE_CUSTOM_01 "Custom 01" { channel="nibeuplink:vvm320:mynibe:custom#CH01" } +Number:Temperature NIBE_SUPPLY "Vorlauf" { channel="nibeuplink:vvm320:mynibe:base#40008" } +Number:Temperature NIBE_RETURN "Rücklauf [%.2f °F]" { channel="nibeuplink:vvm320:mynibe:base#40012" } +Number:Temperature NIBE_HW_TOP "Brauchwasser oben" { channel="nibeuplink:vvm320:mynibe:hotwater#40013" } +Number:Energy NIBE_HM_HEAT "WM Heizung" { channel="nibeuplink:vvm320:mynibe:base#44308" } +Switch NIBE_COMP_DEFROST "Enteisung" { channel="nibeuplink:vvm320:mynibe:compressor#44703" } +Number NIBE_HW_MODE "Modus [MAP(hwmode.map):%s]" { channel="nibeuplink:vvm320:mynibe:hotwater#47041" } + +Number NIBE_MIN_SUP_HEAT "min supply temp. heating [%.1f °C]" { channel="nibeuplink:vvm320:mynibe:47015" } +Number NIBE_MIN_SUP_COOL "min supply temp. cooling [%d °C]" { channel="nibeuplink:vvm320:mynibe:48177" } ``` ### Transformations diff --git a/bundles/org.openhab.binding.nibeuplink/pom.xml b/bundles/org.openhab.binding.nibeuplink/pom.xml index 8cd6fd7e7221b..38f2d43033e23 100644 --- a/bundles/org.openhab.binding.nibeuplink/pom.xml +++ b/bundles/org.openhab.binding.nibeuplink/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.nibeuplink diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/feature/feature.xml b/bundles/org.openhab.binding.nibeuplink/src/main/feature/feature.xml index 7ebd19dd08391..e021703b5b93f 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.nibeuplink/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.nibeuplink/${project.version} + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/AtomicReferenceTrait.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/AtomicReferenceTrait.java index abeea81c8501f..139f1abd3504d 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/AtomicReferenceTrait.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/AtomicReferenceTrait.java @@ -42,7 +42,7 @@ default void cancelJob(@Nullable Future job) { * updates a job reference with a new job. the old job will be cancelled if there is one. * * @param jobReference reference to be updated - * @param newJob job to be assigned + * @param newJob job to be assigned */ default void updateJobReference(AtomicReference<@Nullable Future> jobReference, Future newJob) { cancelJob(jobReference.getAndSet(newJob)); @@ -56,5 +56,4 @@ default void updateJobReference(AtomicReference<@Nullable Future> jobReferenc default void cancelJobReference(AtomicReference<@Nullable Future> jobReference) { cancelJob(jobReference.getAndSet(null)); } - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/NibeUplinkBindingConstants.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/NibeUplinkBindingConstants.java index aa3a44a48e607..adcd674cec9e4 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/NibeUplinkBindingConstants.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/NibeUplinkBindingConstants.java @@ -48,7 +48,44 @@ public final class NibeUplinkBindingConstants { public static final ThingTypeUID THING_TYPE_F1145 = new ThingTypeUID(BINDING_ID, DEVICE_F1145); public static final ThingTypeUID THING_TYPE_F1155 = new ThingTypeUID(BINDING_ID, DEVICE_F1155); - // List of all Channel ids ==> see UplinkDataChannels + public static final String VALID_CHANNEL_ID_REGEX = "[1-5][0-9][0-9][0-9][0-9]"; + + public static final String PARAMETER_NAME_WRITE_API_URL = "writeApiUrl"; + public static final String PARAMETER_NAME_VALIDATION_REGEXP = "validationExpression"; + public static final String PARAMETER_NAME_OFF_MAPPING = "offMapping"; + public static final String PARAMETER_NAME_ON_MAPPING = "onMapping"; + + // List of all channel types + public static final String CHANNEL_TYPE_NUMBER_UNSCALED = "type-number-unscaled"; + public static final String CHANNEL_TYPE_NUMBER_SCALE10 = "type-number-scale10"; + public static final String CHANNEL_TYPE_NUMBER_SCALE100 = "type-number-scale100"; + public static final String CHANNEL_TYPE_TEMPERATURE = "type-temperature"; + public static final String CHANNEL_TYPE_SWITCH = "type-switch"; + public static final String CHANNEL_TYPE_POWER = "type-power"; + public static final String CHANNEL_TYPE_ENERGY = "type-energy"; + public static final String CHANNEL_TYPE_ELECTRIC_CURRENT = "type-electric-current"; + public static final String CHANNEL_TYPE_TIME_UNSCALED = "type-time-unscaled"; + public static final String CHANNEL_TYPE_TIME_SCALE10 = "type-time-scale10"; + public static final String CHANNEL_TYPE_FREQUENCY_UNSCALED = "type-frequency-unscaled"; + public static final String CHANNEL_TYPE_FREQUENCY_SCALE10 = "type-frequency-scale10"; + public static final String CHANNEL_TYPE_FLOW = "type-flow"; + public static final String CHANNEL_TYPE_SPEED = "type-speed-percent"; + public static final String CHANNEL_TYPE_DEFROSTING_STATE = "type-defrosting-state"; + public static final String CHANNEL_TYPE_HPAC_STATE = "type-hpac-state"; + public static final String CHANNEL_TYPE_PRESSURE = "type-pressure"; + + public static final String RW_CHANNEL_PREFIX = "rw"; + public static final String CHANNEL_TYPE_HEAT_OFFSET_RW = "rwtype-heat-offset"; + public static final String CHANNEL_TYPE_START_COOLING_RW = "rwtype-start-cooling"; + public static final String CHANNEL_TYPE_STOP_HEATING_RW = "rwtype-stop-heating"; + public static final String CHANNEL_TYPE_STOP_ADD_HEATING_RW = "rwtype-stop-add-heating"; + public static final String CHANNEL_TYPE_FILTER_TIME_RW = "rwtype-filter-time"; + public static final String CHANNEL_TYPE_ROOM_SENSOR_FACTOR_RW = "rwtype-room-sensor-factor"; + public static final String CHANNEL_TYPE_SWITCH_RW = "rwtype-switch"; + public static final String CHANNEL_TYPE_DEGREE_MINUTES_RW = "rwtype-degree-minutes"; + public static final String CHANNEL_TYPE_HW_LUX_RW = "rwtype-hw-lux"; + public static final String CHANNEL_TYPE_HW_MODE_RW = "rwtype-hw-mode"; + public static final String CHANNEL_TYPE_FAN_SPEED_RW = "rwtype-fan-speed"; // URLs public static final String LOGIN_URL = "https://www.nibeuplink.com/LogIn"; @@ -75,5 +112,4 @@ public final class NibeUplinkBindingConstants { public static final Set SUPPORTED_THING_TYPES_UIDS = Collections .unmodifiableSet(Stream.of(THING_TYPE_VVM320, THING_TYPE_VVM310, THING_TYPE_F730, THING_TYPE_F750, THING_TYPE_F1145, THING_TYPE_F1155).collect(Collectors.toSet())); - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/NibeUplinkHandlerFactory.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/NibeUplinkHandlerFactory.java index 078058f2047e6..f0f940b2025d2 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/NibeUplinkHandlerFactory.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/NibeUplinkHandlerFactory.java @@ -12,8 +12,10 @@ */ package org.openhab.binding.nibeuplink.internal; -import static org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants.*; +import static org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants.SUPPORTED_THING_TYPES_UIDS; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; @@ -22,12 +24,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.eclipse.smarthome.io.net.http.HttpClientFactory; import org.openhab.binding.nibeuplink.internal.handler.GenericHandler; -import org.openhab.binding.nibeuplink.internal.model.F1145Channels; -import org.openhab.binding.nibeuplink.internal.model.F1155Channels; -import org.openhab.binding.nibeuplink.internal.model.F730Channels; -import org.openhab.binding.nibeuplink.internal.model.F750Channels; -import org.openhab.binding.nibeuplink.internal.model.VVM310Channels; -import org.openhab.binding.nibeuplink.internal.model.VVM320Channels; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; @@ -40,13 +37,19 @@ * @author Alexander Friese - initial contribution */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.nibeuplink") +@NonNullByDefault public class NibeUplinkHandlerFactory extends BaseThingHandlerFactory { private final Logger logger = LoggerFactory.getLogger(NibeUplinkHandlerFactory.class); /** * the shared http client */ - private HttpClient httpClient; + private final HttpClient httpClient; + + @Activate + public NibeUplinkHandlerFactory(@Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -54,36 +57,15 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - if (thingTypeUID.equals(THING_TYPE_VVM320)) { - return new GenericHandler(thing, httpClient, VVM320Channels.getInstance()); - } else if (thingTypeUID.equals(THING_TYPE_VVM310)) { - return new GenericHandler(thing, httpClient, VVM310Channels.getInstance()); - } else if (thingTypeUID.equals(THING_TYPE_F750)) { - return new GenericHandler(thing, httpClient, F750Channels.getInstance()); - } else if (thingTypeUID.equals(THING_TYPE_F730)) { - return new GenericHandler(thing, httpClient, F730Channels.getInstance()); - } else if (thingTypeUID.equals(THING_TYPE_F1145)) { - return new GenericHandler(thing, httpClient, F1145Channels.getInstance()); - } else if (thingTypeUID.equals(THING_TYPE_F1155)) { - return new GenericHandler(thing, httpClient, F1155Channels.getInstance()); + if (supportsThingType(thingTypeUID)) { + return new GenericHandler(thing, httpClient); } else { logger.warn("Unsupported Thing-Type: {}", thingTypeUID.getAsString()); } return null; } - - @Reference - protected void setHttpClientFactory(HttpClientFactory httpClientFactory) { - logger.debug("setHttpClientFactory"); - this.httpClient = httpClientFactory.getCommonHttpClient(); - } - - protected void unsetHttpClientFactory(HttpClientFactory httpClientFactory) { - logger.debug("unsetHttpClientFactory"); - this.httpClient = null; - } } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/callback/AbstractUplinkCommandCallback.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/callback/AbstractUplinkCommandCallback.java index c01bfa5c7c467..f63623e746d8b 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/callback/AbstractUplinkCommandCallback.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/callback/AbstractUplinkCommandCallback.java @@ -30,6 +30,7 @@ import org.openhab.binding.nibeuplink.internal.config.NibeUplinkConfiguration; import org.openhab.binding.nibeuplink.internal.connector.CommunicationStatus; import org.openhab.binding.nibeuplink.internal.connector.StatusUpdateListener; +import org.openhab.binding.nibeuplink.internal.model.GenericDataResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -61,13 +62,12 @@ public abstract class AbstractUplinkCommandCallback extends BufferingResponseLis /** * listener to provide updates to the WebInterface class */ - @Nullable - private StatusUpdateListener listener; + private @Nullable StatusUpdateListener listener; /** * JSON deserializer */ - protected final Gson gson; + private final Gson gson; /** * the constructor @@ -134,13 +134,21 @@ public void performAction(HttpClient asyncclient) { prepareRequest(request).send(this); } + /** + * @Nullable wrapper of gson which does not 'understand' nonnull annotations + * + * @param json + * @return + */ + protected @Nullable GenericDataResponse fromJson(String json) { + // gson is not able to handle @NonNull annotation, thus the return value can be null. + return gson.fromJson(json, GenericDataResponse.class); + } + /** * returns Http Status Code */ public CommunicationStatus getCommunicationStatus() { - if (communicationStatus.getHttpCode() == null) { - communicationStatus.setHttpCode(Code.INTERNAL_SERVER_ERROR); - } return communicationStatus; } @@ -167,5 +175,4 @@ public CommunicationStatus getCommunicationStatus() { public final void setListener(StatusUpdateListener listener) { this.listener = listener; } - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/GenericStatusUpdate.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/GenericStatusUpdate.java index eea29f0032e7c..9277b120e8cf7 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/GenericStatusUpdate.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/GenericStatusUpdate.java @@ -25,14 +25,12 @@ import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.util.Fields; +import org.eclipse.smarthome.core.thing.Channel; import org.openhab.binding.nibeuplink.internal.callback.AbstractUplinkCommandCallback; import org.openhab.binding.nibeuplink.internal.connector.StatusUpdateListener; import org.openhab.binding.nibeuplink.internal.handler.NibeUplinkHandler; -import org.openhab.binding.nibeuplink.internal.model.Channel; import org.openhab.binding.nibeuplink.internal.model.DataResponse; import org.openhab.binding.nibeuplink.internal.model.DataResponseTransformer; -import org.openhab.binding.nibeuplink.internal.model.GenericDataResponse; -import org.openhab.binding.nibeuplink.internal.model.VVM320Channels; /** * generic command that retrieves status values for all channels defined in {@link VVM320Channels} @@ -59,9 +57,7 @@ protected Request prepareRequest(Request requestToPrepare) { for (Channel channel : handler.getChannels()) { if (!handler.getDeadChannels().contains(channel)) { - if (!channel.getChannelCode().equals("0")) { - fields.add(DATA_API_FIELD_DATA, channel.getChannelCode()); - } + fields.add(DATA_API_FIELD_DATA, channel.getUID().getIdWithoutGroup()); } } @@ -94,10 +90,12 @@ public void onComplete(@Nullable Result result) { handler.getWebInterface().enqueueCommand(this); } else { String json = getContentAsString(StandardCharsets.UTF_8); - if (json != null) { + if (json != null && !json.isEmpty()) { logger.debug("JSON String: {}", json); - DataResponse jsonObject = gson.fromJson(json, GenericDataResponse.class); - handler.updateChannelStatus(transformer.transform(jsonObject)); + DataResponse jsonObject = fromJson(json); + if (jsonObject != null) { + handler.updateChannelStatus(transformer.transform(jsonObject)); + } } } } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/Login.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/Login.java index 88b0c4d593ab8..96f4c9f03009e 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/Login.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/Login.java @@ -14,6 +14,8 @@ import static org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants.*; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.util.FormContentProvider; @@ -28,6 +30,7 @@ * * @author Alexander Friese - initial contribution */ +@NonNullByDefault public class Login extends AbstractUplinkCommandCallback implements NibeUplinkCommand { public Login(NibeUplinkHandler handler, StatusUpdateListener listener) { @@ -55,7 +58,7 @@ protected String getURL() { } @Override - public void onComplete(Result result) { + public void onComplete(@Nullable Result result) { StatusUpdateListener listener = getListener(); if (listener != null) { listener.update(getCommunicationStatus()); diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/NibeUplinkCommand.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/NibeUplinkCommand.java index 3fd077d803b81..e7aa4d239590f 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/NibeUplinkCommand.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/NibeUplinkCommand.java @@ -52,5 +52,4 @@ public interface NibeUplinkCommand extends SuccessListener, FailureListener, Con * @param listener the listener to be registered. */ void setListener(StatusUpdateListener listener); - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/UpdateSetting.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/UpdateSetting.java index c55deee57701b..42e077cd1a67e 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/UpdateSetting.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/command/UpdateSetting.java @@ -12,8 +12,6 @@ */ package org.openhab.binding.nibeuplink.internal.command; -import static org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants.MANAGE_API_BASE_URL; - import java.nio.charset.StandardCharsets; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -27,11 +25,13 @@ import org.eclipse.jetty.util.Fields; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants; import org.openhab.binding.nibeuplink.internal.callback.AbstractUplinkCommandCallback; +import org.openhab.binding.nibeuplink.internal.handler.ChannelUtil; import org.openhab.binding.nibeuplink.internal.handler.NibeUplinkHandler; -import org.openhab.binding.nibeuplink.internal.model.Channel; -import org.openhab.binding.nibeuplink.internal.model.SwitchChannel; import org.openhab.binding.nibeuplink.internal.model.ValidationException; /** @@ -58,8 +58,8 @@ private String extractValue(Command command) { // this is necessary because we must not send the unit to the nibe backend if (command instanceof QuantityType) { return String.valueOf(((QuantityType) command).doubleValue()); - } else if (command instanceof OnOffType && channel instanceof SwitchChannel) { - return ((SwitchChannel) channel).mapValue((OnOffType) command); + } else if (command instanceof OnOffType) { + return ChannelUtil.mapValue(channel, (OnOffType) command); } else { return command.toString(); } @@ -67,10 +67,13 @@ private String extractValue(Command command) { @Override protected Request prepareRequest(Request requestToPrepare) { - if (channel.isReadOnly()) { - logger.info("channel '{}' does not support write access - value to set '{}'", channel.getFQName(), value); - throw new UnsupportedOperationException( - "channel (" + channel.getFQName() + ") does not support write access"); + ChannelTypeUID typeUID = channel.getChannelTypeUID(); + String channelId = channel.getUID().getIdWithoutGroup(); + + if (typeUID == null || typeUID.getId() == null + || !typeUID.getId().startsWith(NibeUplinkBindingConstants.RW_CHANNEL_PREFIX)) { + logger.info("channel '{}' does not support write access - value to set '{}'", channelId, value); + throw new UnsupportedOperationException("channel (" + channelId + ") does not support write access"); } // although we have integers openhab often transfers decimals which will then cause a validation error. So we @@ -79,9 +82,11 @@ protected Request prepareRequest(Request requestToPrepare) { value = value.substring(0, value.length() - 2); } - if (value.matches(channel.getValidationExpression())) { + String expr = ChannelUtil.getValidationExpression(channel); + + if (value.matches(expr)) { Fields fields = new Fields(); - fields.add(channel.getChannelCode(), value); + fields.add(channelId, value); FormContentProvider cp = new FormContentProvider(fields); @@ -92,16 +97,15 @@ protected Request prepareRequest(Request requestToPrepare) { return requestToPrepare; } else { - logger.info("channel '{}' does not allow value '{}' - validation rule '{}'", channel.getFQName(), value, - channel.getValidationExpression()); - throw new ValidationException( - "channel (" + channel.getFQName() + ") could not be updated due to a validation error"); + logger.info("channel '{}' does not allow value '{}' - validation rule '{}'", channelId, value, expr); + throw new ValidationException("channel (" + channelId + ") could not be updated due to a validation error"); } } @Override protected String getURL() { - return MANAGE_API_BASE_URL + config.getNibeId() + channel.getWriteApiUrlSuffix(); + return NibeUplinkBindingConstants.MANAGE_API_BASE_URL + config.getNibeId() + + ChannelUtil.getWriteApiUrlSuffix(channel); } @Override @@ -109,8 +113,8 @@ public void onComplete(@Nullable Result result) { logger.debug("onComplete()"); if (!HttpStatus.Code.FOUND.equals(getCommunicationStatus().getHttpCode()) && retries++ < MAX_RETRIES) { - logger.debug("Could not set value '{}' for channel '{}' ({})", value, channel.getChannelCode(), - channel.getName()); + logger.debug("Could not set value '{}' for channel '{}' ({})", value, channel.getUID().getId(), + channel.getLabel()); handler.getWebInterface().enqueueCommand(this); } } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/config/NibeUplinkConfiguration.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/config/NibeUplinkConfiguration.java index 798241e7df0c5..8495d1912e2c8 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/config/NibeUplinkConfiguration.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/config/NibeUplinkConfiguration.java @@ -33,15 +33,6 @@ public class NibeUplinkConfiguration { private Integer pollingInterval = 60; private Integer houseKeepingInterval = 3600; - private Integer customChannel01 = 0; - private Integer customChannel02 = 0; - private Integer customChannel03 = 0; - private Integer customChannel04 = 0; - private Integer customChannel05 = 0; - private Integer customChannel06 = 0; - private Integer customChannel07 = 0; - private Integer customChannel08 = 0; - public @Nullable String getUser() { return user; } @@ -98,79 +89,11 @@ public void setHouseKeepingInterval(Integer houseKeepingInterval) { this.houseKeepingInterval = houseKeepingInterval; } - public Integer getCustomChannel01() { - return customChannel01; - } - - public void setCustomChannel01(Integer customChannel01) { - this.customChannel01 = customChannel01; - } - - public Integer getCustomChannel02() { - return customChannel02; - } - - public void setCustomChannel02(Integer customChannel02) { - this.customChannel02 = customChannel02; - } - - public Integer getCustomChannel03() { - return customChannel03; - } - - public void setCustomChannel03(Integer customChannel03) { - this.customChannel03 = customChannel03; - } - - public Integer getCustomChannel04() { - return customChannel04; - } - - public void setCustomChannel04(Integer customChannel04) { - this.customChannel04 = customChannel04; - } - - public Integer getCustomChannel05() { - return customChannel05; - } - - public void setCustomChannel05(Integer customChannel05) { - this.customChannel05 = customChannel05; - } - - public Integer getCustomChannel06() { - return customChannel06; - } - - public void setCustomChannel06(Integer customChannel06) { - this.customChannel06 = customChannel06; - } - - public Integer getCustomChannel07() { - return customChannel07; - } - - public void setCustomChannel07(Integer customChannel07) { - this.customChannel07 = customChannel07; - } - - public Integer getCustomChannel08() { - return customChannel08; - } - - public void setCustomChannel08(Integer customChannel08) { - this.customChannel08 = customChannel08; - } - @Override public String toString() { return new ToStringBuilder(this).append("user", getUser()).append("password", getPassword()) .append("nibeId", getNibeId()).append("pollingInterval", getPollingInterval()) .append("houseKeepingInterval", getHouseKeepingInterval()).append("asyncTimeout", getAsyncTimeout()) - .append("syncTimeout", getSyncTimeout()).append("customChannel01", getCustomChannel01()) - .append("customChannel02", getCustomChannel02()).append("customChannel03", getCustomChannel03()) - .append("customChannel04", getCustomChannel04()).append("customChannel05", getCustomChannel05()) - .append("customChannel06", getCustomChannel06()).append("customChannel07", getCustomChannel07()) - .append("customChannel08", getCustomChannel08()).toString(); + .append("syncTimeout", getSyncTimeout()).toString(); } } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/CommunicationStatus.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/CommunicationStatus.java index 1f81dec49c891..2240b1af00de1 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/CommunicationStatus.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/CommunicationStatus.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.nibeuplink.internal.connector; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.http.HttpStatus.Code; /** @@ -20,20 +22,22 @@ * * @author Alexander Friese - initial contribution */ +@NonNullByDefault public class CommunicationStatus { - private Code httpCode; - private Exception error; + private @Nullable Code httpCode; + private @Nullable Exception error; public final Code getHttpCode() { - return httpCode == null ? Code.INTERNAL_SERVER_ERROR : httpCode; + Code code = httpCode; + return code == null ? Code.INTERNAL_SERVER_ERROR : code; } public final void setHttpCode(Code httpCode) { this.httpCode = httpCode; } - public final Exception getError() { + public final @Nullable Exception getError() { return error; } @@ -42,12 +46,13 @@ public final void setError(Exception error) { } public final String getMessage() { - if (error != null && error.getMessage() != null && !error.getMessage().isEmpty()) { - return error.getMessage(); - } else if (httpCode != null & httpCode.getMessage() != null && !httpCode.getMessage().isEmpty()) { - return httpCode.getMessage(); + Exception err = error; + String msg = getHttpCode().getMessage(); + if (err != null && err.getMessage() != null && !err.getMessage().isEmpty()) { + return err.getMessage(); + } else if (msg != null && !msg.isEmpty()) { + return msg; } return ""; } - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/StatusUpdateListener.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/StatusUpdateListener.java index 9414a9662e4b3..99fc58bbe5eeb 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/StatusUpdateListener.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/StatusUpdateListener.java @@ -23,5 +23,4 @@ public interface StatusUpdateListener { void update(CommunicationStatus status); - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/UplinkWebInterface.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/UplinkWebInterface.java index 470a37b997dad..7b903db7ec772 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/UplinkWebInterface.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/connector/UplinkWebInterface.java @@ -89,12 +89,13 @@ public class UplinkWebInterface implements AtomicReferenceTrait { * * @author afriese - initial contribution */ + @NonNullByDefault private class WebRequestExecutor implements Runnable { /** * queue which holds the commands to execute */ - private final Queue commandQueue; + private final Queue<@Nullable NibeUplinkCommand> commandQueue; /** * constructor @@ -157,11 +158,12 @@ public void update(CommunicationStatus status) { }; NibeUplinkCommand command = commandQueue.poll(); - command.setListener(statusUpdater); - command.performAction(httpClient); + if (command != null) { + command.setListener(statusUpdater); + command.performAction(httpClient); + } } } - } /** @@ -262,7 +264,6 @@ private boolean preCheck() { this.uplinkHandler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, preCheckStatusMessage); return false; - } /** diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/ChannelProvider.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/ChannelProvider.java index f730af072d435..0eb8c367757f1 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/ChannelProvider.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/ChannelProvider.java @@ -12,11 +12,12 @@ */ package org.openhab.binding.nibeuplink.internal.handler; +import java.util.List; import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.nibeuplink.internal.model.Channel; +import org.eclipse.smarthome.core.thing.Channel; /** * this interface provides all methods which deal with channels @@ -26,11 +27,10 @@ @NonNullByDefault public interface ChannelProvider { - Set getChannels(); + List getChannels(); Set getDeadChannels(); @Nullable Channel getSpecificChannel(String channelCode); - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/ChannelUtil.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/ChannelUtil.java new file mode 100644 index 0000000000000..85f3cc2f6a1ba --- /dev/null +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/ChannelUtil.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.nibeuplink.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants; +import org.openhab.binding.nibeuplink.internal.model.ConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * this class provides all methods which deal with channels + * + * @author Alexander Friese - initial contribution + */ +@NonNullByDefault +public final class ChannelUtil { + private static final Logger logger = LoggerFactory.getLogger(ChannelUtil.class); + + /** + * only static methods no instance needed + */ + private ChannelUtil() { + } + + /** + * checks whether the channel ha a valid numeric Id + * + * @param channel to check + * @return true or false + */ + public static boolean isValidNibeChannel(Channel channel) { + String id = channel.getUID().getIdWithoutGroup(); + return id.matches(NibeUplinkBindingConstants.VALID_CHANNEL_ID_REGEX); + } + + /** + * map data response from API to OnOff-Type. uses mapping from channel configuration + * + * @param channel switch channel which has mapping configured + * @param value value to map + * @return mapped value + */ + public static State mapValue(Channel channel, String value) { + String off = getOffMapping(channel); + String on = getOnMapping(channel); + if (value.equals(off)) { + return OnOffType.OFF; + } else if (value.equals(on)) { + return OnOffType.ON; + } else { + logger.warn("Channel {} value '{}' could not be mapped, valid values: ON={}, OFF={}", + channel.getUID().getId(), value, on, off); + return UnDefType.UNDEF; + } + } + + /** + * map data response from API to OnOff-Type. uses mapping from channel configuration + * + * @param channel switch channel which has mapping configured + * @param value value to map + * @return mapped value + */ + public static State mapValue(Channel channel, long value) { + return mapValue(channel, String.valueOf(value)); + } + + /** + * map OnOff-Type to API compatible value. uses mapping from channel configuration + * + * @param channel switch channel which has mapping configured + * @param value value to map + * @return mapped value + */ + public static String mapValue(Channel channel, OnOffType value) { + if (value.equals(OnOffType.OFF)) { + return String.valueOf(getOffMapping(channel)); + } else { + return String.valueOf(getOnMapping(channel)); + } + } + + /** + * retrieves the validation expression which is assigned to this channel, fallback to a default, if no validation is + * defined. + * + * @param channel + * @return the validation expression + */ + public static String getValidationExpression(Channel channel) { + String expr = getPropertyOrParameter(channel, NibeUplinkBindingConstants.PARAMETER_NAME_VALIDATION_REGEXP); + if (expr == null) { + logger.info("Channel {} does not have a validation expression configured", channel.getUID().getId()); + throw new ConfigurationException( + "channel (" + channel.getUID().getId() + ") does not have a validation expression configured"); + } + return expr; + } + + /** + * retrieves the write API url suffix which is assigned to this channel. + * + * @param channel + * @return the url suffix + */ + public static String getWriteApiUrlSuffix(Channel channel) { + String suffix = getPropertyOrParameter(channel, NibeUplinkBindingConstants.PARAMETER_NAME_WRITE_API_URL); + if (suffix == null) { + logger.info("channel {} does not have a write api url suffix configured", channel.getUID().getId()); + throw new ConfigurationException( + "channel (" + channel.getUID().getId() + ") does not have a write api url suffix configured"); + } + return suffix; + } + + private static @Nullable String getOffMapping(Channel channel) { + return getPropertyOrParameter(channel, NibeUplinkBindingConstants.PARAMETER_NAME_OFF_MAPPING); + } + + private static @Nullable String getOnMapping(Channel channel) { + return getPropertyOrParameter(channel, NibeUplinkBindingConstants.PARAMETER_NAME_ON_MAPPING); + } + + private static @Nullable String getPropertyOrParameter(Channel channel, String name) { + String value = channel.getProperties().get(name); + // also eclipse says this cannot be null, it definitely can! + if (value == null || value.isEmpty()) { + Object obj = channel.getConfiguration().get(name); + value = obj == null ? null : obj.toString(); + } + return value; + } +} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/GenericHandler.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/GenericHandler.java index 97019603150d2..a3258739298bb 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/GenericHandler.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/GenericHandler.java @@ -12,16 +12,15 @@ */ package org.openhab.binding.nibeuplink.internal.handler; -import java.util.HashSet; -import java.util.Set; +import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelGroupUID; +import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; -import org.openhab.binding.nibeuplink.internal.model.Channel; -import org.openhab.binding.nibeuplink.internal.model.ChannelList; -import org.openhab.binding.nibeuplink.internal.model.CustomChannels; /** * generic implementation of handler logic @@ -30,37 +29,33 @@ */ @NonNullByDefault public class GenericHandler extends UplinkBaseHandler { - private final ChannelList channelList; /** * constructor, called by the factory * - * @param thing instance of the thing, passed in by the factory - * @param httpClient the httpclient that communicates with the API - * @param channelList the specific channellist + * @param thing instance of the thing, passed in by the factory + * @param httpClient the httpclient that communicates with the API */ - public GenericHandler(Thing thing, HttpClient httpClient, ChannelList channelList) { + public GenericHandler(Thing thing, HttpClient httpClient) { super(thing, httpClient); - this.channelList = channelList; } @Override - public @Nullable Channel getSpecificChannel(String channelCode) { - Channel channel = channelList.fromCode(channelCode); - - // check custom channels if no stock channel was found + public @Nullable Channel getSpecificChannel(String channelId) { + Channel channel = getThing().getChannel(channelId); if (channel == null) { - channel = CustomChannels.getInstance().fromCode(channelCode); + for (ChannelGroupUID channelGroupUID : getRegisteredGroups()) { + channel = getThing().getChannel(new ChannelUID(channelGroupUID, channelId)); + if (channel != null) { + break; + } + } } return channel; } @Override - public Set getChannels() { - Set specificAndCustomChannels = new HashSet<>(); - specificAndCustomChannels.addAll(channelList.getChannels()); - specificAndCustomChannels.addAll(CustomChannels.getInstance().getChannels()); - return specificAndCustomChannels; + public List getChannels() { + return getThing().getChannels(); } - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/NibeUplinkHandler.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/NibeUplinkHandler.java index 6604e439fa9ad..563b6d3378a12 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/NibeUplinkHandler.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/NibeUplinkHandler.java @@ -15,13 +15,13 @@ import java.util.Map; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.State; import org.openhab.binding.nibeuplink.internal.config.NibeUplinkConfiguration; import org.openhab.binding.nibeuplink.internal.connector.UplinkWebInterface; -import org.openhab.binding.nibeuplink.internal.model.Channel; /** * public interface of the {@link UplinkBaseHandler} @@ -34,9 +34,9 @@ public interface NibeUplinkHandler extends ThingHandler, ChannelProvider { * Called from {@link NibeUplinkWebInterface#authenticate()} to update * the thing status because updateStatus is protected. * - * @param status Bridge status + * @param status Bridge status * @param statusDetail Bridge status detail - * @param description Bridge status description + * @param description Bridge status description */ void setStatusInfo(ThingStatus status, ThingStatusDetail statusDetail, String description); @@ -50,5 +50,4 @@ public interface NibeUplinkHandler extends ThingHandler, ChannelProvider { void updateChannelStatus(Map values); NibeUplinkConfiguration getConfiguration(); - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/UplinkBaseHandler.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/UplinkBaseHandler.java index 909e21bf84aad..b876769c0da69 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/UplinkBaseHandler.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/UplinkBaseHandler.java @@ -22,20 +22,23 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelGroupUID; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; import org.openhab.binding.nibeuplink.internal.AtomicReferenceTrait; +import org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants; import org.openhab.binding.nibeuplink.internal.command.UpdateSetting; import org.openhab.binding.nibeuplink.internal.config.NibeUplinkConfiguration; import org.openhab.binding.nibeuplink.internal.connector.UplinkWebInterface; -import org.openhab.binding.nibeuplink.internal.model.Channel; -import org.openhab.binding.nibeuplink.internal.model.CustomChannels; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,7 +55,8 @@ public abstract class UplinkBaseHandler extends BaseThingHandler implements Nibe private final long POLLING_INITIAL_DELAY = 30; private final long HOUSE_KEEPING_INITIAL_DELAY = 300; - private Set deadChannels = new HashSet<>(100); + private final Set deadChannels = new HashSet<>(100); + private final Set registeredGroups = new HashSet<>(10); /** * Interface object for querying the NibeUplink web interface @@ -81,8 +85,12 @@ public void handleCommand(ChannelUID channelUID, Command command) { if (!(command instanceof RefreshType)) { logger.debug("command for {}: {}", channelUID.getIdWithoutGroup(), command.toString()); Channel channel = getSpecificChannel(channelUID.getIdWithoutGroup()); - if (channel != null && !channel.isReadOnly()) { - webInterface.enqueueCommand(new UpdateSetting(this, channel, command)); + if (channel != null) { + ChannelTypeUID typeUID = channel.getChannelTypeUID(); + if (typeUID != null && typeUID.getId() != null + && typeUID.getId().startsWith(NibeUplinkBindingConstants.RW_CHANNEL_PREFIX)) { + webInterface.enqueueCommand(new UpdateSetting(this, channel, command)); + } } } } @@ -91,10 +99,10 @@ public void handleCommand(ChannelUID channelUID, Command command) { public void initialize() { logger.debug("About to initialize NibeUplink"); NibeUplinkConfiguration config = getConfiguration(); - logger.debug("NibeUplink initialized with configuration: {}", config); - setupCustomChannels(config); + registeredGroups.clear(); + validateChannelsAndRegisterGroups(); startPolling(); webInterface.start(); @@ -102,19 +110,28 @@ public void initialize() { } /** - * initialize the custom channels out of the configuration + * initialize the channels out of the configuration * - * @param config the active configuration */ - private void setupCustomChannels(NibeUplinkConfiguration config) { - CustomChannels.CH_CH01.setCode(config.getCustomChannel01()); - CustomChannels.CH_CH02.setCode(config.getCustomChannel02()); - CustomChannels.CH_CH03.setCode(config.getCustomChannel03()); - CustomChannels.CH_CH04.setCode(config.getCustomChannel04()); - CustomChannels.CH_CH05.setCode(config.getCustomChannel05()); - CustomChannels.CH_CH06.setCode(config.getCustomChannel06()); - CustomChannels.CH_CH07.setCode(config.getCustomChannel07()); - CustomChannels.CH_CH08.setCode(config.getCustomChannel08()); + private void validateChannelsAndRegisterGroups() { + logger.debug("Validating {} channels", getThing().getChannels().size()); + for (Channel channel : getThing().getChannels()) { + if (!ChannelUtil.isValidNibeChannel(channel)) { + logger.warn("Channel {} is not a valid Nibe channel ({})", channel.getUID().getIdWithoutGroup(), + channel.getLabel()); + deadChannels.add(channel); + } else { + logger.debug("Successfully validated channel {} ({})", channel.getUID().getIdWithoutGroup(), + channel.getLabel()); + String groupId = channel.getUID().getGroupId(); + if (groupId != null) { + ThingUID thingUID = this.getThing().getUID(); + if (registeredGroups.add(new ChannelGroupUID(thingUID, groupId))) { + logger.debug("Successfully registered channel-group '{}'", groupId); + } + } + } + } } /** @@ -152,16 +169,18 @@ public UplinkWebInterface getWebInterface() { * @param values map containing the data updates */ @Override - public void updateChannelStatus(Map values) { + public void updateChannelStatus(Map values) { logger.debug("Handling channel update. ({} Channels)", values.size()); for (Channel channel : values.keySet()) { if (getChannels().contains(channel)) { State value = values.get(channel); - logger.debug("Channel is to be updated: {}: {}", channel.getFQName(), value); - updateState(channel.getFQName(), value); + if (value != null) { + logger.debug("Channel is to be updated: {}: {}", channel.getUID().getAsString(), value); + updateState(channel.getUID(), value); + } } else { - logger.debug("Could not identify channel: {} for model {}", channel.getFQName(), + logger.debug("Could not identify channel: {} for model {}", channel.getUID().getAsString(), getThing().getThingTypeUID().getAsString()); } } @@ -182,4 +201,7 @@ public NibeUplinkConfiguration getConfiguration() { return this.getConfigAs(NibeUplinkConfiguration.class); } + public Set getRegisteredGroups() { + return registeredGroups; + } } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/UplinkPolling.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/UplinkPolling.java index d94ebe4074844..7a0192cba3bfe 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/UplinkPolling.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/handler/UplinkPolling.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.nibeuplink.internal.handler; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.nibeuplink.internal.command.GenericStatusUpdate; import org.openhab.binding.nibeuplink.internal.command.NibeUplinkCommand; import org.slf4j.Logger; @@ -22,6 +23,7 @@ * * @author Alexander Friese - initial contribution */ +@NonNullByDefault public class UplinkPolling implements Runnable { private final Logger logger = LoggerFactory.getLogger(getClass()); diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/AbstractChannels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/AbstractChannels.java deleted file mode 100644 index ed05280ff7c5d..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/AbstractChannels.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * base class for all channellists - * - * @author Alexander Friese - initial contribution - */ -public abstract class AbstractChannels implements ChannelList { - - /** - * Holds the channels - */ - protected final Set channels = new HashSet<>(); - - /** - * returns an unmodifiable set containing all available channels. - * - * @return set of unique channels - */ - @Override - public Set getChannels() { - return Collections.unmodifiableSet(channels); - } - - /** - * returns the matching channel, null if no match was found. - * - * @param channelCode the channelCode which identifies the channel - * @return channel which belongs to the code. might be null if there is no channel found. - */ - @Override - public Channel fromCode(String channelCode) { - for (Channel channel : channels) { - if (channel.getChannelCode().equals(channelCode)) { - return channel; - } - } - return null; - } - - /** - * adds a channel to the internal channel list - * - * @param channel - * @return - */ - protected final T addChannel(T channel) { - channels.add(channel); - return channel; - } -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/BaseChannels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/BaseChannels.java deleted file mode 100644 index 0ab2718e6f6c5..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/BaseChannels.java +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.smarthome.core.library.unit.MetricPrefix; -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.openhab.binding.nibeuplink.internal.model.ScaledChannel.ScaleFactor; - -/** - * this class contains all base channels which are used by all heatpump models - * - * @author Alexander Friese - initial contribution - */ -public class BaseChannels extends AbstractChannels { - - /** - * singleton - */ - private static final BaseChannels INSTANCE = new BaseChannels(); - - /** - * Returns the unique instance of this class. - * - * @return the Units instance. - */ - protected static BaseChannels getInstance() { - return INSTANCE; - } - - /** - * singleton should not be instantiated from outside - */ - protected BaseChannels() { - } - - /** - * returns the matching channel, null if no match was found. - * - * @param channelCode the channelCode which identifies the channel - * @return channel which belongs to the code. might be null if there is no channel found. - */ - @Override - public Channel fromCode(String channelCode) { - Channel channel = super.fromCode(channelCode); - - // also check channels in this class if called from an inherited class - if (channel == null && this != INSTANCE) { - return INSTANCE.fromCode(channelCode); - } else { - return channel; - } - } - - /** - * returns an unmodifiable set containing all available channels. - * - * @return - */ - @Override - public Set getChannels() { - Set allChannels = new HashSet<>(); - allChannels.addAll(channels); - - // also add channels contained in this class if called from an inherited class - if (this != INSTANCE) { - allChannels.addAll(INSTANCE.channels); - } - - return Collections.unmodifiableSet(allChannels); - } - - // General - public static final Channel CH_40004 = INSTANCE.addChannel(new QuantityChannel("40004", "BT1 Outdoor Temperature", - ChannelGroup.BASE, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40067 = INSTANCE.addChannel( - new QuantityChannel("40067", "BT1 Average", ChannelGroup.BASE, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43005 = INSTANCE.addChannel(new ScaledChannel("43005", "Degree Minutes (16 bit)", - ChannelGroup.BASE, ScaleFactor.DIV_10, "/Manage/4.9.3", "-?[0-9]+")); - public static final Channel CH_43009 = INSTANCE.addChannel( - new QuantityChannel("43009", "Calc. Supply S1", ChannelGroup.BASE, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40071 = INSTANCE.addChannel( - new QuantityChannel("40071", "BT25 Ext. Supply", ChannelGroup.BASE, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40033 = INSTANCE.addChannel( - new QuantityChannel("40033", "BT50 Room Temp S1", ChannelGroup.BASE, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43161 = INSTANCE - .addChannel(new SwitchChannel("43161", "External adjustment activated via input S1", ChannelGroup.BASE)); - public static final Channel CH_40008 = INSTANCE.addChannel( - new QuantityChannel("40008", "BT2 Supply temp S1", ChannelGroup.BASE, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40012 = INSTANCE.addChannel(new QuantityChannel("40012", - "EB100-EP14-BT3 Return temp", ChannelGroup.BASE, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40072 = INSTANCE.addChannel(new QuantityChannel("40072", "BF1 EP14 Flow", - ChannelGroup.BASE, ScaleFactor.DIV_10, SmartHomeUnits.LITRE.divide(SIUnits.METRE))); - public static final Channel CH_43437 = INSTANCE.addChannel( - new QuantityChannel("43437", "Supply Pump Speed EP14", ChannelGroup.BASE, SmartHomeUnits.PERCENT)); - public static final Channel CH_40079 = INSTANCE.addChannel(new QuantityChannel("40079", "EB100-BE3 Current", - ChannelGroup.BASE, ScaleFactor.DIV_10, SmartHomeUnits.AMPERE)); - public static final Channel CH_40081 = INSTANCE.addChannel(new QuantityChannel("40081", "EB100-BE2 Current", - ChannelGroup.BASE, ScaleFactor.DIV_10, SmartHomeUnits.AMPERE)); - public static final Channel CH_40083 = INSTANCE.addChannel(new QuantityChannel("40083", "EB100-BE1 Current", - ChannelGroup.BASE, ScaleFactor.DIV_10, SmartHomeUnits.AMPERE)); - public static final Channel CH_10033 = INSTANCE - .addChannel(new SwitchChannel("10033", "Int. el.add. blocked", ChannelGroup.BASE)); - - // additional heater - public static final Channel CH_43081 = INSTANCE.addChannel(new QuantityChannel("43081", "Tot. op.time add.", - ChannelGroup.BASE, ScaleFactor.DIV_10, SmartHomeUnits.HOUR)); - public static final Channel CH_43084 = INSTANCE.addChannel(new QuantityChannel("43084", "Int. el.add. Power", - ChannelGroup.BASE, ScaleFactor.DIV_100, MetricPrefix.KILO(SmartHomeUnits.WATT))); - public static final Channel CH_47212 = INSTANCE.addChannel(new QuantityChannel("47212", "Max int add. power", - ChannelGroup.BASE, ScaleFactor.DIV_100, MetricPrefix.KILO(SmartHomeUnits.WATT))); - public static final Channel CH_48914 = INSTANCE - .addChannel(new QuantityChannel("48914", "Max int add. power, SG Ready", ChannelGroup.BASE, - ScaleFactor.DIV_100, MetricPrefix.KILO(SmartHomeUnits.WATT))); - - // heat meters - public static final Channel CH_44308 = INSTANCE - .addChannel(new QuantityChannel("44308", "Heat Meter - Heat Cpr EP14", ChannelGroup.BASE, - ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - public static final Channel CH_44304 = INSTANCE - .addChannel(new QuantityChannel("44304", "Heat Meter - Pool Cpr EP14", ChannelGroup.BASE, - ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - public static final Channel CH_44300 = INSTANCE - .addChannel(new QuantityChannel("44300", "Heat Meter - Heat Cpr and Add EP14", ChannelGroup.BASE, - ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - - public static final Channel CH_48043 = INSTANCE - .addChannel(new SwitchChannel("48043", "Holiday Mode", ChannelGroup.BASE, 0, 10, "/Manage/4.7")); - - // Hotwater - public static final Channel CH_40013 = INSTANCE.addChannel( - new QuantityChannel("40013", "BT7 HW Top", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40014 = INSTANCE.addChannel( - new QuantityChannel("40014", "BT6 HW Load", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44306 = INSTANCE.addChannel(new QuantityChannel("44306", "Heat Meter - HW Cpr EP14", - ChannelGroup.HOTWATER, ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - public static final Channel CH_44298 = INSTANCE - .addChannel(new QuantityChannel("44298", "Heat Meter - HW Cpr and Add EP14", ChannelGroup.HOTWATER, - ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - public static final Channel CH_48132 = INSTANCE - .addChannel(new Channel("48132", "Temporary Lux", ChannelGroup.HOTWATER, "/Manage/2.1", "[01234]")); - public static final Channel CH_47041 = INSTANCE - .addChannel(new Channel("47041", "Hot water mode", ChannelGroup.HOTWATER, "/Manage/2.2", "[012]")); - public static final Channel CH_47045 = INSTANCE.addChannel(new QuantityChannel("47045", - "Start temperature HW Economy", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_47049 = INSTANCE.addChannel(new QuantityChannel("47049", - "Stop temperature HW Economy", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_47044 = INSTANCE.addChannel(new QuantityChannel("47044", - "Start temperature HW Normal", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_47048 = INSTANCE.addChannel(new QuantityChannel("47048", - "Stop temperature HW Normal", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_47043 = INSTANCE.addChannel(new QuantityChannel("47043", - "Start temperature HW Luxury", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_47047 = INSTANCE.addChannel(new QuantityChannel("47047", - "Stop temperature HW Luxury", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_47046 = INSTANCE.addChannel(new QuantityChannel("47046", - "Stop temperature periodic HW", ChannelGroup.HOTWATER, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - - // Compressor - public static final Channel CH_10012 = INSTANCE - .addChannel(new SwitchChannel("10012", "Compressor blocked", ChannelGroup.BASE)); - -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/Channel.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/Channel.java deleted file mode 100644 index 275afa9691b65..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/Channel.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; - -/** - * the channel class - * - * @author Alexander Friese - initial contribution - */ -@NonNullByDefault -public class Channel { - - protected String channelCode; - private final String id; - private final String name; - private final ChannelGroup channelGroup; - private final @Nullable String writeApiUrl; - private final @Nullable String validationExpression; - - /** - * constructor for channels with write access enabled wihtout a unit - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - * @param writeApiUrl API URL for channel updates - * @param validationExpression expression to validate values before sent to the API - */ - Channel(String id, String name, ChannelGroup channelGroup, @Nullable String writeApiUrl, - @Nullable String validationExpression) { - this.channelCode = id; - this.id = id; - this.name = name; - this.channelGroup = channelGroup; - this.writeApiUrl = writeApiUrl; - this.validationExpression = validationExpression; - } - - /** - * constructor for channels without write access and without unit - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - */ - Channel(String id, String name, ChannelGroup channelGroup) { - this(id, name, channelGroup, null, null); - } - - public final String getName() { - return name; - } - - public final String getId() { - return id; - } - - public final String getChannelCode() { - return channelCode; - } - - public ChannelGroup getChannelGroup() { - return channelGroup; - } - - public String getFQName() { - return channelGroup.toString().toLowerCase() + "#" + id; - } - - public @Nullable String getWriteApiUrlSuffix() { - return writeApiUrl; - } - - public boolean isReadOnly() { - String localCopy = writeApiUrl; - return localCopy == null || localCopy.isEmpty(); - } - - public @Nullable String getValidationExpression() { - return validationExpression; - } -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ChannelList.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ChannelList.java deleted file mode 100644 index 4f961b77bc1a1..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ChannelList.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import java.util.Set; - -/** - * interface which contains the public methods of the channellist classes - * - * @author Alexander Friese - initial contribution - */ -public interface ChannelList { - - /** - * returns an unmodifiable set containing all available channels. - * - * @return - */ - Set getChannels(); - - /** - * returns the matching channel, null if no match was found - * - * @param channelCode the channelCode which identifies the channel - * @return channel which belongs to the code. might be null if there is no channel found. - */ - Channel fromCode(String channelCode); -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/CustomChannel.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ConfigurationException.java similarity index 53% rename from bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/CustomChannel.java rename to bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ConfigurationException.java index 9593862568782..dc92c15fc2ac3 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/CustomChannel.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ConfigurationException.java @@ -15,27 +15,27 @@ import org.eclipse.jdt.annotation.NonNullByDefault; /** - * the channel class + * exception whichs is used to state a validation error * * @author Alexander Friese - initial contribution */ @NonNullByDefault -public class CustomChannel extends Channel { +public class ConfigurationException extends RuntimeException { + private static final long serialVersionUID = 1L; - CustomChannel(String id, String name) { - super(id, name, ChannelGroup.CUSTOM); - this.channelCode = "0"; + public ConfigurationException() { + super(); } - /** - * used to set the channelcode obtained from configuration file - * - * @param channelCode the channelCode to be set - */ - public final void setCode(Integer channelCode) { - if (getChannelGroup().equals(ChannelGroup.CUSTOM)) { - this.channelCode = channelCode.toString(); - } + public ConfigurationException(String message) { + super(message); } + public ConfigurationException(Throwable cause) { + super(cause); + } + + public ConfigurationException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/CustomChannels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/CustomChannels.java deleted file mode 100644 index bfb0c130504a9..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/CustomChannels.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -/** - * the custom channels which can be configured via config-file - * - * @author Alexander Friese - initial contribution - */ -public final class CustomChannels extends AbstractChannels { - - /** - * singleton - */ - private static final CustomChannels INSTANCE = new CustomChannels(); - - /** - * Returns the unique instance of this class. - * - * @return the Units instance. - */ - public static CustomChannels getInstance() { - return INSTANCE; - } - - /** - * singleton should not be instantiated from outside - */ - private CustomChannels() { - } - - // Custom Channels - public static final CustomChannel CH_CH01 = INSTANCE.addChannel(new CustomChannel("CH01", "Custom Channel #01")); - public static final CustomChannel CH_CH02 = INSTANCE.addChannel(new CustomChannel("CH02", "Custom Channel #02")); - public static final CustomChannel CH_CH03 = INSTANCE.addChannel(new CustomChannel("CH03", "Custom Channel #03")); - public static final CustomChannel CH_CH04 = INSTANCE.addChannel(new CustomChannel("CH04", "Custom Channel #04")); - public static final CustomChannel CH_CH05 = INSTANCE.addChannel(new CustomChannel("CH05", "Custom Channel #05")); - public static final CustomChannel CH_CH06 = INSTANCE.addChannel(new CustomChannel("CH06", "Custom Channel #06")); - public static final CustomChannel CH_CH07 = INSTANCE.addChannel(new CustomChannel("CH07", "Custom Channel #07")); - public static final CustomChannel CH_CH08 = INSTANCE.addChannel(new CustomChannel("CH08", "Custom Channel #08")); - -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/DataResponseTransformer.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/DataResponseTransformer.java index 2afdc6562f9e6..d6cfe21746492 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/DataResponseTransformer.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/DataResponseTransformer.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.nibeuplink.internal.model; +import static org.openhab.binding.nibeuplink.internal.NibeUplinkBindingConstants.*; + import java.util.HashMap; import java.util.Map; @@ -19,10 +21,15 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.unit.MetricPrefix; +import org.eclipse.smarthome.core.library.unit.SIUnits; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.eclipse.smarthome.core.types.State; import org.openhab.binding.nibeuplink.internal.handler.ChannelProvider; +import org.openhab.binding.nibeuplink.internal.handler.ChannelUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,6 +42,10 @@ public class DataResponseTransformer { private final Logger logger = LoggerFactory.getLogger(DataResponseTransformer.class); + private static final double UNSCALED = 1; + private static final double DIV_10 = 0.1; + private static final double DIV_100 = 0.01; + private final ChannelProvider channelProvider; public DataResponseTransformer(ChannelProvider channelProvider) { @@ -53,28 +64,98 @@ public Map transform(DataResponse response) { // This should not happen but we want to get informed about it logger.warn("Channel not found: {}", channelId); } else { - if (channel instanceof QuantityChannel) { - Unit unit = ((QuantityChannel) channel).getUnit(); - double factor = ((ScaledChannel) channel).getFactor(); - logger.debug("Channel {} transformed to QuantityType ({}*{} {})", channel.getFQName(), value, - factor, unit.toString()); - result.put(channel, new QuantityType<>(value * factor, unit)); - } else if (channel instanceof SwitchChannel) { - logger.debug("Channel {} transformed to OnOffType ({})", channel.getFQName(), value); - OnOffType mapped = ((SwitchChannel) channel).mapValue(value); - result.put(channel, mapped); - } else if (channel instanceof ScaledChannel) { - double factor = ((ScaledChannel) channel).getFactor(); - logger.debug("Channel {} transformed to scaled NumberType ({}*{})", channel.getFQName(), value, - factor); - result.put(channel, new DecimalType(value * factor)); - } else { - logger.debug("Channel {} transformed to NumberType ({})", channel.getFQName(), value); - result.put(channel, new DecimalType(value)); + ChannelTypeUID typeUID = channel.getChannelTypeUID(); + String type = typeUID == null ? "null" : typeUID.getId(); + + switch (type) { + case CHANNEL_TYPE_TEMPERATURE: + case CHANNEL_TYPE_START_COOLING_RW: + putQuantityType(result, channel, value, DIV_10, SIUnits.CELSIUS); + break; + case CHANNEL_TYPE_PRESSURE: + putQuantityType(result, channel, value, DIV_10, SmartHomeUnits.BAR); + break; + case CHANNEL_TYPE_ENERGY: + putQuantityType(result, channel, value, DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR)); + break; + case CHANNEL_TYPE_POWER: + putQuantityType(result, channel, value, DIV_100, MetricPrefix.KILO(SmartHomeUnits.WATT)); + break; + case CHANNEL_TYPE_SWITCH_RW: + case CHANNEL_TYPE_SWITCH: + putOnOffType(result, channel, value); + break; + case CHANNEL_TYPE_ELECTRIC_CURRENT: + putQuantityType(result, channel, value, DIV_10, SmartHomeUnits.AMPERE); + break; + case CHANNEL_TYPE_TIME_UNSCALED: + putQuantityType(result, channel, value, UNSCALED, SmartHomeUnits.HOUR); + break; + case CHANNEL_TYPE_TIME_SCALE10: + putQuantityType(result, channel, value, DIV_10, SmartHomeUnits.HOUR); + break; + case CHANNEL_TYPE_FREQUENCY_UNSCALED: + putQuantityType(result, channel, value, UNSCALED, SmartHomeUnits.HERTZ); + break; + case CHANNEL_TYPE_FREQUENCY_SCALE10: + putQuantityType(result, channel, value, DIV_10, SmartHomeUnits.HERTZ); + break; + case CHANNEL_TYPE_FLOW: + putQuantityType(result, channel, value, DIV_10, + SmartHomeUnits.LITRE.divide(SmartHomeUnits.MINUTE)); + break; + case CHANNEL_TYPE_SPEED: + putQuantityType(result, channel, value, UNSCALED, SmartHomeUnits.PERCENT); + break; + case CHANNEL_TYPE_NUMBER_SCALE100: + putDecimalType(result, channel, value, DIV_100); + break; + case CHANNEL_TYPE_NUMBER_SCALE10: + case CHANNEL_TYPE_DEGREE_MINUTES_RW: + case CHANNEL_TYPE_STOP_HEATING_RW: + case CHANNEL_TYPE_STOP_ADD_HEATING_RW: + case CHANNEL_TYPE_ROOM_SENSOR_FACTOR_RW: + putDecimalType(result, channel, value, DIV_10); + break; + case CHANNEL_TYPE_NUMBER_UNSCALED: + case CHANNEL_TYPE_DEFROSTING_STATE: + case CHANNEL_TYPE_HPAC_STATE: + case CHANNEL_TYPE_HW_LUX_RW: + case CHANNEL_TYPE_HW_MODE_RW: + case CHANNEL_TYPE_FAN_SPEED_RW: + case CHANNEL_TYPE_FILTER_TIME_RW: + case CHANNEL_TYPE_HEAT_OFFSET_RW: + putDecimalType(result, channel, value, UNSCALED); + break; + default: + logger.warn("could not handle unknown type {}, channel {}, value {}", type, channel.getUID(), + value); } } } return result; } + private final void putQuantityType(Map targetMap, Channel channel, long value, double factor, + Unit unit) { + // make sure that values are stored as long if no factor is to be applied + State val = factor == UNSCALED ? new QuantityType<>(value, unit) : new QuantityType<>(value * factor, unit); + targetMap.put(channel, val); + logger.debug("Channel {} transformed to QuantityType ({}*{} {}) -> {}", channel.getUID().getId(), value, factor, + unit, val); + } + + private final void putOnOffType(Map targetMap, Channel channel, long value) { + State val = ChannelUtil.mapValue(channel, value); + targetMap.put(channel, val); + logger.debug("Channel {} transformed to OnOffType ({}) -> {}", channel.getUID().getId(), value, val); + } + + private final void putDecimalType(Map targetMap, Channel channel, long value, double factor) { + // make sure that values are stored as long if no factor is to be applied + State val = factor == UNSCALED ? new DecimalType(value) : new DecimalType(value * factor); + targetMap.put(channel, val); + logger.debug("Channel {} transformed to DecimalType ({}*{}) -> {}", channel.getUID().getId(), value, factor, + val); + } } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F1145Channels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F1145Channels.java deleted file mode 100644 index de01c89af5574..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F1145Channels.java +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.smarthome.core.library.unit.MetricPrefix; -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.openhab.binding.nibeuplink.internal.model.ScaledChannel.ScaleFactor; - -/** - * list of all available channels - * - * @author Alexander Friese - initial contribution - */ -public final class F1145Channels extends BaseChannels { - - /** - * singleton - */ - private static final F1145Channels INSTANCE = new F1145Channels(); - - /** - * Returns the unique instance of this class. - * - * @return the Units instance. - */ - public static F1145Channels getInstance() { - return INSTANCE; - } - - /** - * singleton should not be instantiated from outside - */ - private F1145Channels() { - } - - // General - public static final Channel CH_44302 = INSTANCE - .addChannel(new QuantityChannel("44302", "Heat Meter - Cooling Cpr EP14", ChannelGroup.GENERAL, - ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - public static final Channel CH_44270 = INSTANCE.addChannel(new QuantityChannel("44270", - "Calculated Cooling Supply Temperature S1", ChannelGroup.GENERAL, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43103 = INSTANCE - .addChannel(new Channel("43103", "HPAC state", ChannelGroup.GENERAL)); - - // Compressor - public static final Channel CH_43424 = INSTANCE.addChannel(new QuantityChannel("43424", - "EB100-EP14 Tot. HW op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_43420 = INSTANCE.addChannel(new QuantityChannel("43420", - "EB100-EP14 Tot. op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_43416 = INSTANCE - .addChannel(new Channel("43416", "EB100-EP14 Compressor starts", ChannelGroup.COMPRESSOR)); - public static final Channel CH_40022 = INSTANCE.addChannel(new QuantityChannel("40022", "EB100-EP14-BT17 Suction", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40019 = INSTANCE.addChannel(new QuantityChannel("40019", - "EB100-EP14-BT15 Liquid Line", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40018 = INSTANCE.addChannel(new QuantityChannel("40018", - "EB100-EP14-BT14 Hot Gas Temp", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40017 = INSTANCE.addChannel(new QuantityChannel("40017", - "EB100-EP14-BT12 Condensor Out", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40015 = INSTANCE.addChannel(new QuantityChannel("40015", - "EB100-EP14-BT10 Brine In Temperature", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40016 = INSTANCE.addChannel(new QuantityChannel("40016", - "EB100-EP14-BT11 Brine Out Temperature", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43439 = INSTANCE.addChannel( - new QuantityChannel("43439", "EP14-GP2 Brine Pump Speed", ChannelGroup.COMPRESSOR, SmartHomeUnits.PERCENT)); - - // Airsupply - public static final Channel CH_40025 = INSTANCE.addChannel(new QuantityChannel("40025", "BT20 Exhaust air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40026 = INSTANCE.addChannel(new QuantityChannel("40026", "BT21 Vented air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F1155Channels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F1155Channels.java deleted file mode 100644 index 84db09a27827e..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F1155Channels.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.smarthome.core.library.unit.MetricPrefix; -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.openhab.binding.nibeuplink.internal.model.ScaledChannel.ScaleFactor; - -/** - * list of all available channels - * - * @author Alexander Friese - initial contribution - */ -public final class F1155Channels extends BaseChannels { - - /** - * singleton - */ - private static final F1155Channels INSTANCE = new F1155Channels(); - - /** - * Returns the unique instance of this class. - * - * @return the Units instance. - */ - public static F1155Channels getInstance() { - return INSTANCE; - } - - /** - * singleton should not be instantiated from outside - */ - private F1155Channels() { - } - - // General - public static final Channel CH_44302 = INSTANCE - .addChannel(new QuantityChannel("44302", "Heat Meter - Cooling Cpr EP14", ChannelGroup.GENERAL, - ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - - // Compressor - public static final Channel CH_43424 = INSTANCE.addChannel(new QuantityChannel("43424", - "EB100-EP14 Tot. HW op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_43420 = INSTANCE.addChannel(new QuantityChannel("43420", - "EB100-EP14 Tot. op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_43416 = INSTANCE - .addChannel(new Channel("43416", "EB100-EP14 Compressor starts", ChannelGroup.COMPRESSOR)); - public static final Channel CH_40022 = INSTANCE.addChannel(new QuantityChannel("40022", "EB100-EP14-BT17 Suction", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40019 = INSTANCE.addChannel(new QuantityChannel("40019", - "EB100-EP14-BT15 Liquid Line", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40018 = INSTANCE.addChannel(new QuantityChannel("40018", - "EB100-EP14-BT14 Hot Gas Temp", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40017 = INSTANCE.addChannel(new QuantityChannel("40017", - "EB100-EP14-BT12 Condensor Out", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43136 = INSTANCE.addChannel(new QuantityChannel("43136", - "Compressor Frequency, Actual", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.HERTZ)); - public static final Channel CH_43122 = INSTANCE.addChannel(new QuantityChannel("43122", "Compr. current min.freq.", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.HERTZ)); - public static final Channel CH_43123 = INSTANCE.addChannel(new QuantityChannel("43123", "Compr. current max.freq.", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.HERTZ)); - public static final Channel CH_40015 = INSTANCE.addChannel(new QuantityChannel("40015", - "EB100-EP14-BT10 Brine In Temperature", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40016 = INSTANCE.addChannel(new QuantityChannel("40016", - "EB100-EP14-BT11 Brine Out Temperature", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43439 = INSTANCE.addChannel( - new QuantityChannel("43439", "EP14-GP2 Brine Pump Speed", ChannelGroup.COMPRESSOR, SmartHomeUnits.PERCENT)); - - // Airsupply - public static final Channel CH_40025 = INSTANCE.addChannel(new QuantityChannel("40025", "BT20 Exhaust air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40026 = INSTANCE.addChannel(new QuantityChannel("40026", "BT21 Vented air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F730Channels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F730Channels.java deleted file mode 100644 index 18082e4140487..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F730Channels.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.openhab.binding.nibeuplink.internal.model.ScaledChannel.ScaleFactor; - -/** - * list of all available channels - * - * @author Alexander Friese - initial contribution - */ -public final class F730Channels extends BaseChannels { - - /** - * singleton - */ - private static final F730Channels INSTANCE = new F730Channels(); - - /** - * Returns the unique instance of this class. - * - * @return the Units instance. - */ - public static F730Channels getInstance() { - return INSTANCE; - } - - /** - * singleton should not be instantiated from outside - */ - private F730Channels() { - } - - // General - // currently no general channels - - // Compressor - public static final Channel CH_43181 = INSTANCE.addChannel( - new QuantityChannel("43181", "Chargepump speed", ChannelGroup.COMPRESSOR, SmartHomeUnits.PERCENT)); - public static final Channel CH_43424 = INSTANCE.addChannel(new QuantityChannel("43424", - "EB100-EP14 Tot. HW op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_43420 = INSTANCE.addChannel(new QuantityChannel("43420", - "EB100-EP14 Tot. op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_43416 = INSTANCE - .addChannel(new Channel("43416", "EB100-EP14 Compressor starts", ChannelGroup.COMPRESSOR)); - public static final Channel CH_40022 = INSTANCE.addChannel(new QuantityChannel("40022", "EB100-EP14-BT17 Suction", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40019 = INSTANCE.addChannel(new QuantityChannel("40019", - "EB100-EP14-BT15 Liquid Line", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40018 = INSTANCE.addChannel(new QuantityChannel("40018", - "EB100-EP14-BT14 Hot Gas Temp", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40017 = INSTANCE.addChannel(new QuantityChannel("40017", - "EB100-EP14-BT12 Condensor Out", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40020 = INSTANCE.addChannel(new QuantityChannel("40020", - "EB100-EP14-BT16 Evaporator", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43136 = INSTANCE.addChannel(new QuantityChannel("43136", - "Compressor Frequency, Actual", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.HERTZ)); - public static final Channel CH_43122 = INSTANCE.addChannel( - new QuantityChannel("43122", "Compr. current min.freq.", ChannelGroup.COMPRESSOR, SmartHomeUnits.HERTZ)); - public static final Channel CH_43123 = INSTANCE.addChannel( - new QuantityChannel("43123", "Compr. current max.freq.", ChannelGroup.COMPRESSOR, SmartHomeUnits.HERTZ)); - public static final Channel CH_43066 = INSTANCE.addChannel( - new QuantityChannel("43066", "Defrosting time", ChannelGroup.COMPRESSOR, SmartHomeUnits.SECOND)); - - // Airsupply - public static final Channel CH_10001 = INSTANCE.addChannel( - new QuantityChannel("10001", "Fan speed current", ChannelGroup.AIRSUPPLY, SmartHomeUnits.PERCENT)); - public static final Channel CH_40025 = INSTANCE.addChannel(new QuantityChannel("40025", "BT20 Exhaust air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40026 = INSTANCE.addChannel(new QuantityChannel("40026", "BT21 Vented air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43124 = INSTANCE - .addChannel(new ScaledChannel("43124", "Air flow ref.", ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10)); - public static final Channel CH_41026 = INSTANCE - .addChannel(new Channel("41026", "EB100-Adjusted BS1 Air flow", ChannelGroup.AIRSUPPLY)); - public static final Channel CH_43125 = INSTANCE - .addChannel(new Channel("43125", "Air flow reduction", ChannelGroup.AIRSUPPLY)); - public static final Channel CH_40919 = INSTANCE.addChannel( - new QuantityChannel("40919", "Air mix", ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40101 = INSTANCE.addChannel(new QuantityChannel("40101", "BT28 Air mix Temp", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F750Channels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F750Channels.java deleted file mode 100644 index 865f30b1e5344..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/F750Channels.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.openhab.binding.nibeuplink.internal.model.ScaledChannel.ScaleFactor; - -/** - * list of all available channels - * - * @author Alexander Friese - initial contribution - */ -public final class F750Channels extends BaseChannels { - - /** - * singleton - */ - private static final F750Channels INSTANCE = new F750Channels(); - - /** - * Returns the unique instance of this class. - * - * @return the Units instance. - */ - public static F750Channels getInstance() { - return INSTANCE; - } - - /** - * singleton should not be instantiated from outside - */ - private F750Channels() { - } - - // General - // currently no general channels - - // Compressor - public static final Channel CH_43181 = INSTANCE.addChannel( - new QuantityChannel("43181", "Chargepump speed", ChannelGroup.COMPRESSOR, SmartHomeUnits.PERCENT)); - public static final Channel CH_43424 = INSTANCE.addChannel(new QuantityChannel("43424", - "EB100-EP14 Tot. HW op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_43420 = INSTANCE.addChannel(new QuantityChannel("43420", - "EB100-EP14 Tot. op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_43416 = INSTANCE - .addChannel(new Channel("43416", "EB100-EP14 Compressor starts", ChannelGroup.COMPRESSOR)); - public static final Channel CH_40022 = INSTANCE.addChannel(new QuantityChannel("40022", "EB100-EP14-BT17 Suction", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40019 = INSTANCE.addChannel(new QuantityChannel("40019", - "EB100-EP14-BT15 Liquid Line", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40018 = INSTANCE.addChannel(new QuantityChannel("40018", - "EB100-EP14-BT14 Hot Gas Temp", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40017 = INSTANCE.addChannel(new QuantityChannel("40017", - "EB100-EP14-BT12 Condensor Out", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40020 = INSTANCE.addChannel(new QuantityChannel("40020", - "EB100-EP14-BT16 Evaporator", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43136 = INSTANCE.addChannel(new QuantityChannel("43136", - "Compressor Frequency, Actual", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.HERTZ)); - public static final Channel CH_43122 = INSTANCE.addChannel( - new QuantityChannel("43122", "Compr. current min.freq.", ChannelGroup.COMPRESSOR, SmartHomeUnits.HERTZ)); - public static final Channel CH_43123 = INSTANCE.addChannel( - new QuantityChannel("43123", "Compr. current max.freq.", ChannelGroup.COMPRESSOR, SmartHomeUnits.HERTZ)); - - // Airsupply - public static final Channel CH_40025 = INSTANCE.addChannel(new QuantityChannel("40025", "BT20 Exhaust air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40026 = INSTANCE.addChannel(new QuantityChannel("40026", "BT21 Vented air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_43124 = INSTANCE - .addChannel(new ScaledChannel("43124", "Air flow ref.", ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10)); - public static final Channel CH_41026 = INSTANCE - .addChannel(new Channel("41026", "EB100-Adjusted BS1 Air flow", ChannelGroup.AIRSUPPLY)); - public static final Channel CH_47260 = INSTANCE - .addChannel(new Channel("47260", "Current Fan speed", ChannelGroup.AIRSUPPLY, "/Manage/1.2", "[01234]")); - -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/GenericDataResponse.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/GenericDataResponse.java index b489195b5468b..5776cc1765aa6 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/GenericDataResponse.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/GenericDataResponse.java @@ -17,6 +17,8 @@ import java.util.List; import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,60 +29,62 @@ * * @author Alexander Friese - initial contribution */ +@NonNullByDefault public class GenericDataResponse implements DataResponse { private final Logger logger = LoggerFactory.getLogger(GenericDataResponse.class); + @NonNullByDefault public static class Value { @SerializedName("VariableId") - private String variableId; + private @Nullable String variableId; @SerializedName("CurrentValue") - private String currentValue; + private @Nullable String currentValue; @SerializedName("CurrentIntValue") - private Long currentIntValue; + private @Nullable Long currentIntValue; @SerializedName("IsLoading") private boolean isLoading; } @SerializedName("IsOffline") - private String isOffline; + private @Nullable String isOffline; @SerializedName("OnlineImage") - private String onlineImage; + private @Nullable String onlineImage; @SerializedName("Date") - private String date; + private @Nullable String date; @SerializedName("FuzzyDate") - private String fuzzyDate; + private @Nullable String fuzzyDate; @SerializedName("Values") private List values = new ArrayList<>(); @Override - public Map getValues() { - Map valueMap = new HashMap<>(); + public Map getValues() { + Map valueMap = new HashMap<>(); for (Value value : values) { - if (!value.isLoading) { + String id = value.variableId; + if (!value.isLoading && id != null) { if (logger.isDebugEnabled()) { logger.debug("Channel {} updated to: {} ({})", value.variableId, value.currentIntValue, value.currentValue); } - valueMap.put(value.variableId, value.currentIntValue); + valueMap.put(id, value.currentIntValue); } } return valueMap; } - public String getIsOffline() { + public @Nullable String getIsOffline() { return isOffline; } - public String getOnlineImage() { + public @Nullable String getOnlineImage() { return onlineImage; } - public String getDate() { + public @Nullable String getDate() { return date; } - public String getFuzzyDate() { + public @Nullable String getFuzzyDate() { return fuzzyDate; } - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/QuantityChannel.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/QuantityChannel.java deleted file mode 100644 index 9039762689cec..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/QuantityChannel.java +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import javax.measure.Unit; - -import org.eclipse.jdt.annotation.NonNullByDefault; - -/** - * extension of the ScaledChannel class which adds support of QuantityType - * write access is in general not support by this type of channel as Nibe cannot handle unit conversions - * - * @author Alexander Friese - initial contribution - */ -@NonNullByDefault -public class QuantityChannel extends ScaledChannel { - - private final Unit unit; - - /** - * constructor for channels with explicit scaling - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - * @param factor scaling factor - * @param unit UoM unit - */ - QuantityChannel(String id, String name, ChannelGroup channelGroup, ScaleFactor factor, Unit unit) { - super(id, name, channelGroup, factor, null, null); - this.unit = unit; - } - - /** - * constructor for channels with defaulted scaling to 1 - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - * @param unit UoM unit - */ - QuantityChannel(String id, String name, ChannelGroup channelGroup, Unit unit) { - this(id, name, channelGroup, ScaleFactor.ONE, unit); - } - - public Unit getUnit() { - return unit; - } - -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ScaledChannel.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ScaledChannel.java deleted file mode 100644 index b3ffaaa73430d..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ScaledChannel.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; - -/** - * extension of the channel class which adds support of QuantityType - * - * @author Alexander Friese - initial contribution - */ -@NonNullByDefault -public class ScaledChannel extends Channel { - - static enum ScaleFactor { - ONE(1), - DIV_10(0.1), - DIV_100(0.01); - - private final double factor; - - private ScaleFactor(double factor) { - this.factor = factor; - } - - private final double getFactor() { - return factor; - } - } - - private final ScaleFactor factor; - - /** - * constructor for channels with write access enabled + unit - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - * @param factor scaling factor - * @param writeApiUrl API URL for channel updates - * @param validationExpression expression to validate values before sent to the API - */ - ScaledChannel(String id, String name, ChannelGroup channelGroup, ScaleFactor factor, @Nullable String writeApiUrl, - @Nullable String validationExpression) { - super(id, name, channelGroup, writeApiUrl, validationExpression); - this.factor = factor; - } - - /** - * constructor for channels without write access - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - * @param factor scaling factor - */ - ScaledChannel(String id, String name, ChannelGroup channelGroup, ScaleFactor factor) { - this(id, name, channelGroup, factor, null, null); - } - - public final double getFactor() { - return factor.getFactor(); - } -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/SwitchChannel.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/SwitchChannel.java deleted file mode 100644 index eabff98df9de2..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/SwitchChannel.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.types.OnOffType; - -/** - * extension of Channel class to support SwitchType - * - * @author Alexander Friese - initial contribution - */ -@NonNullByDefault -public class SwitchChannel extends Channel { - - private static final double DEFAULT_OFF = 0; - private static final double DEFAULT_ON = 1; - - private final double offValue; - private final double onValue; - - /** - * constructor for channels with write access enabled. custom on/off mapping - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - * @param offValue value which represents OFF state - * @param onValue value which represents ON state - * @param writeApiUrl API URL for channel updates - */ - SwitchChannel(String id, String name, ChannelGroup channelGroup, double offValue, double onValue, - @Nullable String writeApiUrl) { - super(id, name, channelGroup, writeApiUrl, ".*"); - this.offValue = offValue; - this.onValue = onValue; - } - - /** - * constructor for channels without write access. custom on/off mapping - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - * @param offValue value which represents OFF state - * @param onValue value which represents ON state - */ - SwitchChannel(String id, String name, ChannelGroup channelGroup, double offValue, double onValue) { - this(id, name, channelGroup, offValue, onValue, null); - } - - /** - * constructor for channels with write access enabled - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - * @param writeApiUrl API URL for channel updates - */ - SwitchChannel(String id, String name, ChannelGroup channelGroup, @Nullable String writeApiUrl) { - this(id, name, channelGroup, DEFAULT_OFF, DEFAULT_ON, writeApiUrl); - } - - /** - * constructor for channels without write access - * - * @param id identifier of the channel - * @param name human readable name - * @param channelGroup group of the channel - */ - SwitchChannel(String id, String name, ChannelGroup channelGroup) { - this(id, name, channelGroup, null); - } - - public OnOffType mapValue(double value) { - if (value == offValue) { - return OnOffType.OFF; - } else { - return OnOffType.ON; - } - } - - public String mapValue(OnOffType value) { - if (value.equals(OnOffType.OFF)) { - return String.valueOf(offValue); - } else { - return String.valueOf(onValue); - } - } - -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/VVM310Channels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/VVM310Channels.java deleted file mode 100644 index 3a44330ffbc49..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/VVM310Channels.java +++ /dev/null @@ -1,125 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.smarthome.core.library.unit.MetricPrefix; -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.openhab.binding.nibeuplink.internal.model.ScaledChannel.ScaleFactor; - -/** - * list of all available channels - * - * @author Alexander Friese - initial contribution - */ -public final class VVM310Channels extends BaseChannels { - - /** - * singleton - */ - private static final VVM310Channels INSTANCE = new VVM310Channels(); - - /** - * Returns the unique instance of this class. - * - * @return the Units instance. - */ - public static VVM310Channels getInstance() { - return INSTANCE; - } - - /** - * singleton should not be instantiated from outside - */ - private VVM310Channels() { - } - - // General - public static final Channel CH_44270 = INSTANCE.addChannel(new QuantityChannel("44270", "Calc. Cooling Supply S1", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40121 = INSTANCE.addChannel(new QuantityChannel("40121", "BT63 Add Supply Temp", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - - public static final Channel CH_44302 = INSTANCE - .addChannel(new QuantityChannel("44302", "Heat Meter - Cooling Cpr EP14", ChannelGroup.GENERAL, - ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - - public static final Channel CH_47011 = INSTANCE.addChannel( - new Channel("47011", "Heat Offset S1", ChannelGroup.GENERAL, "/Manage/1.9.1.1-S1", "[-1]*[0-9]")); - public static final Channel CH_47394 = INSTANCE - .addChannel(new SwitchChannel("47394", "Room Sensor", ChannelGroup.GENERAL, "/Manage/1.9.4")); - public static final Channel CH_47402 = INSTANCE.addChannel(new ScaledChannel("47402", "Room sensor factor", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, "/Manage/1.9.4", "[0123456]*[0-9]")); - public static final Channel CH_48793 = INSTANCE.addChannel(new ScaledChannel("48793", "Room sensor cool factor", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, "/Manage/1.9.4", "[0123456]*[0-9]")); - - // Compressor - public static final Channel CH_44362 = INSTANCE.addChannel(new QuantityChannel("44362", - "EB101-EP14-BT28 Outdoor Temp", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44396 = INSTANCE.addChannel( - new QuantityChannel("44396", "EB101 Speed charge pump", ChannelGroup.COMPRESSOR, SmartHomeUnits.PERCENT)); - public static final Channel CH_44703 = INSTANCE - .addChannel(new Channel("44703", "EB101-EP14 Defrosting Outdoor Unit", ChannelGroup.COMPRESSOR)); - public static final Channel CH_44073 = INSTANCE.addChannel(new QuantityChannel("44073", - "EB101-EP14 Tot. HW op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_40737 = INSTANCE.addChannel(new QuantityChannel("40737", - "EB101-EP14 Tot. Cooling op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_44071 = INSTANCE.addChannel(new QuantityChannel("44071", - "EB101-EP14 Tot. op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_44069 = INSTANCE - .addChannel(new Channel("44069", "EB101-EP14 Compressor starts", ChannelGroup.COMPRESSOR)); - public static final Channel CH_44061 = INSTANCE.addChannel(new QuantityChannel("44061", "EB101-EP14-BT17 Suction", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44060 = INSTANCE.addChannel(new QuantityChannel("44060", - "EB101-EP14-BT15 Liquid Line", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44059 = INSTANCE.addChannel(new QuantityChannel("44059", - "EB101-EP14-BT14 Hot Gas Temp", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44058 = INSTANCE.addChannel(new QuantityChannel("44058", - "EB101-EP14-BT12 Condensor Out", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44055 = INSTANCE.addChannel(new QuantityChannel("44055", - "EB101-EP14-BT3 Return Temp.", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44363 = INSTANCE.addChannel(new QuantityChannel("44363", - "EB101-EP14-BT16 Evaporator", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44699 = INSTANCE.addChannel(new QuantityChannel("44699", - "EB101-EP14-BP4 Pressure Sensor", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.BAR)); - public static final Channel CH_40782 = INSTANCE.addChannel(new QuantityChannel("40782", - "EB101 Cpr Frequency Desired F2040", ChannelGroup.COMPRESSOR, SmartHomeUnits.HERTZ)); - public static final Channel CH_44701 = INSTANCE - .addChannel(new QuantityChannel("44701", "EB101-EP14 Actual Cpr Frequency Outdoor Unit", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.HERTZ)); - public static final Channel CH_44702 = INSTANCE.addChannel( - new SwitchChannel("44702", "EB101-EP14 Protection Status Register Outdoor Unit", ChannelGroup.COMPRESSOR)); - public static final Channel CH_44700 = INSTANCE - .addChannel(new QuantityChannel("44700", "EB101-EP14 Low Pressure Sensor Outdoor Unit", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.BAR)); - public static final Channel CH_44457 = INSTANCE - .addChannel(new Channel("44457", "EB101-EP14 Compressor State", ChannelGroup.COMPRESSOR)); - - // Airsupply - public static final Channel CH_40025 = INSTANCE.addChannel(new QuantityChannel("40025", "BT20 Exhaust air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40026 = INSTANCE.addChannel(new QuantityChannel("40026", "BT21 Vented air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40075 = INSTANCE.addChannel(new QuantityChannel("40075", "BT22 Supply air temp.", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40183 = INSTANCE.addChannel(new QuantityChannel("40183", - "AZ30-BT23 Outdoor temp. ERS", ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40311 = INSTANCE.addChannel(new QuantityChannel("40311", - "External ERS accessory GQ2 speed", ChannelGroup.AIRSUPPLY, SmartHomeUnits.PERCENT)); - public static final Channel CH_40312 = INSTANCE.addChannel(new QuantityChannel("40312", - "External ERS accessory GQ3speed", ChannelGroup.AIRSUPPLY, SmartHomeUnits.PERCENT)); - public static final Channel CH_40942 = INSTANCE - .addChannel(new SwitchChannel("40942", "External ERS accessory blockstatus", ChannelGroup.AIRSUPPLY)); - public static final Channel CH_47260 = INSTANCE - .addChannel(new Channel("47260", "Selected Fan speed", ChannelGroup.AIRSUPPLY, "/Manage/1.2", "[01234]")); -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/VVM320Channels.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/VVM320Channels.java deleted file mode 100644 index 14c79989724c1..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/VVM320Channels.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.nibeuplink.internal.model; - -import org.eclipse.smarthome.core.library.unit.MetricPrefix; -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; -import org.openhab.binding.nibeuplink.internal.model.ScaledChannel.ScaleFactor; - -/** - * list of all available channels - * - * @author Alexander Friese - initial contribution - */ -public final class VVM320Channels extends BaseChannels { - - /** - * singleton - */ - private static final VVM320Channels INSTANCE = new VVM320Channels(); - - /** - * Returns the unique instance of this class. - * - * @return the Units instance. - */ - public static VVM320Channels getInstance() { - return INSTANCE; - } - - /** - * singleton should not be instantiated from outside - */ - private VVM320Channels() { - } - - // General - public static final Channel CH_44270 = INSTANCE.addChannel(new QuantityChannel("44270", "Calc. Cooling Supply S1", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40121 = INSTANCE.addChannel(new QuantityChannel("40121", "BT63 Add Supply Temp", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - - public static final Channel CH_44302 = INSTANCE - .addChannel(new QuantityChannel("44302", "Heat Meter - Cooling Cpr EP14", ChannelGroup.GENERAL, - ScaleFactor.DIV_10, MetricPrefix.KILO(SmartHomeUnits.WATT_HOUR))); - - public static final Channel CH_47011 = INSTANCE.addChannel( - new Channel("47011", "Heat Offset S1", ChannelGroup.GENERAL, "/Manage/1.9.1.1-S1", "[-1]*[0-9]")); - public static final Channel CH_47394 = INSTANCE - .addChannel(new SwitchChannel("47394", "Room Sensor", ChannelGroup.GENERAL, "/Manage/1.9.4")); - public static final Channel CH_47402 = INSTANCE.addChannel(new ScaledChannel("47402", "Room sensor factor", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, "/Manage/1.9.4", "[0123456]*[0-9]")); - public static final Channel CH_48793 = INSTANCE.addChannel(new ScaledChannel("48793", "Room sensor cool factor", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, "/Manage/1.9.4", "[0123456]*[0-9]")); - - public static final Channel CH_47374 = INSTANCE.addChannel(new ScaledChannel("47374", "Start Temperature Cooling", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, "/Manage/4.9.2", "[0-9]*[0-9]")); - public static final Channel CH_47375 = INSTANCE.addChannel(new ScaledChannel("47375", "Stop Temperature Heating", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, "/Manage/4.9.2", "[0-9]*[0-9]")); - public static final Channel CH_47376 = INSTANCE.addChannel(new ScaledChannel("47376", "Stop Temperature Additive", - ChannelGroup.GENERAL, ScaleFactor.DIV_10, "/Manage/4.9.2", "[0-9]*[0-9]")); - public static final Channel CH_47377 = INSTANCE.addChannel( - new Channel("47377", "Outdoor Filter Time", ChannelGroup.GENERAL, "/Manage/4.9.2", "[0-4]*[0-9]")); - - // Compressor - public static final Channel CH_44362 = INSTANCE.addChannel(new QuantityChannel("44362", - "EB101-EP14-BT28 Outdoor Temp", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44396 = INSTANCE.addChannel( - new QuantityChannel("44396", "EB101 Speed charge pump", ChannelGroup.COMPRESSOR, SmartHomeUnits.PERCENT)); - public static final Channel CH_44703 = INSTANCE - .addChannel(new Channel("44703", "EB101-EP14 Defrosting Outdoor Unit", ChannelGroup.COMPRESSOR)); - public static final Channel CH_44073 = INSTANCE.addChannel(new QuantityChannel("44073", - "EB101-EP14 Tot. HW op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_40737 = INSTANCE.addChannel(new QuantityChannel("40737", - "EB101-EP14 Tot. Cooling op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_44071 = INSTANCE.addChannel(new QuantityChannel("44071", - "EB101-EP14 Tot. op.time compr", ChannelGroup.COMPRESSOR, SmartHomeUnits.HOUR)); - public static final Channel CH_44069 = INSTANCE - .addChannel(new Channel("44069", "EB101-EP14 Compressor starts", ChannelGroup.COMPRESSOR)); - public static final Channel CH_44061 = INSTANCE.addChannel(new QuantityChannel("44061", "EB101-EP14-BT17 Suction", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44060 = INSTANCE.addChannel(new QuantityChannel("44060", - "EB101-EP14-BT15 Liquid Line", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44059 = INSTANCE.addChannel(new QuantityChannel("44059", - "EB101-EP14-BT14 Hot Gas Temp", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44058 = INSTANCE.addChannel(new QuantityChannel("44058", - "EB101-EP14-BT12 Condensor Out", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44055 = INSTANCE.addChannel(new QuantityChannel("44055", - "EB101-EP14-BT3 Return Temp.", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44363 = INSTANCE.addChannel(new QuantityChannel("44363", - "EB101-EP14-BT16 Evaporator", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_44699 = INSTANCE.addChannel(new QuantityChannel("44699", - "EB101-EP14-BP4 Pressure Sensor", ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.BAR)); - public static final Channel CH_40782 = INSTANCE.addChannel(new QuantityChannel("40782", - "EB101 Cpr Frequency Desired F2040", ChannelGroup.COMPRESSOR, SmartHomeUnits.HERTZ)); - public static final Channel CH_44701 = INSTANCE - .addChannel(new QuantityChannel("44701", "EB101-EP14 Actual Cpr Frequency Outdoor Unit", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.HERTZ)); - public static final Channel CH_44702 = INSTANCE.addChannel( - new SwitchChannel("44702", "EB101-EP14 Protection Status Register Outdoor Unit", ChannelGroup.COMPRESSOR)); - public static final Channel CH_44700 = INSTANCE - .addChannel(new QuantityChannel("44700", "EB101-EP14 Low Pressure Sensor Outdoor Unit", - ChannelGroup.COMPRESSOR, ScaleFactor.DIV_10, SmartHomeUnits.BAR)); - public static final Channel CH_44457 = INSTANCE - .addChannel(new Channel("44457", "EB101-EP14 Compressor State", ChannelGroup.COMPRESSOR)); - - // Airsupply - public static final Channel CH_40025 = INSTANCE.addChannel(new QuantityChannel("40025", "BT20 Exhaust air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40026 = INSTANCE.addChannel(new QuantityChannel("40026", "BT21 Vented air temp. 1", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40075 = INSTANCE.addChannel(new QuantityChannel("40075", "BT22 Supply air temp.", - ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40183 = INSTANCE.addChannel(new QuantityChannel("40183", - "AZ30-BT23 Outdoor temp. ERS", ChannelGroup.AIRSUPPLY, ScaleFactor.DIV_10, SIUnits.CELSIUS)); - public static final Channel CH_40311 = INSTANCE.addChannel(new QuantityChannel("40311", - "External ERS accessory GQ2 speed", ChannelGroup.AIRSUPPLY, SmartHomeUnits.PERCENT)); - public static final Channel CH_40312 = INSTANCE.addChannel(new QuantityChannel("40312", - "External ERS accessory GQ3speed", ChannelGroup.AIRSUPPLY, SmartHomeUnits.PERCENT)); - public static final Channel CH_40942 = INSTANCE - .addChannel(new SwitchChannel("40942", "External ERS accessory blockstatus", ChannelGroup.AIRSUPPLY)); - public static final Channel CH_47260 = INSTANCE - .addChannel(new Channel("47260", "Selected Fan speed", ChannelGroup.AIRSUPPLY, "/Manage/1.2", "[01234]")); -} diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ValidationException.java b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ValidationException.java index cafae67295c22..8a43a66371291 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ValidationException.java +++ b/bundles/org.openhab.binding.nibeuplink/src/main/java/org/openhab/binding/nibeuplink/internal/model/ValidationException.java @@ -12,11 +12,14 @@ */ package org.openhab.binding.nibeuplink.internal.model; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * exception whichs is used to state a validation error * * @author Alexander Friese - initial contribution */ +@NonNullByDefault public class ValidationException extends RuntimeException { private static final long serialVersionUID = 1L; @@ -35,5 +38,4 @@ public ValidationException(Throwable cause) { public ValidationException(String message, Throwable cause) { super(message, cause); } - } diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/binding/binding.xml index 32c6b33f86b37..9f58695d77d3d 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - NibeUplink Binding diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/config/config.xml index 1531e9dfc79a4..3fd80dbe61716 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/config/config.xml @@ -41,46 +41,6 @@ Interval in which data is polled from Nibe Uplink (in seconds). 60 - - - ID of an additional custom channel - - - - ID of an additional custom channel - - - - ID of an additional custom channel - - - - ID of an additional custom channel - - - - ID of an additional custom channel - - - - ID of an additional custom channel - - - - ID of an additional custom channel - - - - ID of an additional custom channel - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/i18n/nibeuplink_de.properties b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/i18n/nibeuplink_de.properties index 79bd18ecee911..043f010858ed0 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/i18n/nibeuplink_de.properties +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/i18n/nibeuplink_de.properties @@ -24,19 +24,3 @@ thing-type.config.nibeuplink.web.nibeId.label = Nibe ID thing-type.config.nibeuplink.web.nibeId.description = ID der Wrmepumpeninstallation bei Nibe Uplink. thing-type.config.nibeuplink.web.pollingInterval.label = Abfrageintervall thing-type.config.nibeuplink.web.pollingInterval.description = Intervall in welchem Abfragen an Nibe Uplink geschickt werden. -thing-type.config.nibeuplink.web.customChannel01.label = Kanal 01 -thing-type.config.nibeuplink.web.customChannel01.description = benutzerdefinierter Kanal 01 -thing-type.config.nibeuplink.web.customChannel02.label = Kanal 02 -thing-type.config.nibeuplink.web.customChannel02.description = benutzerdefinierter Kanal 02 -thing-type.config.nibeuplink.web.customChannel03.label = Kanal 03 -thing-type.config.nibeuplink.web.customChannel03.description = benutzerdefinierter Kanal 03 -thing-type.config.nibeuplink.web.customChannel03.label = Kanal 04 -thing-type.config.nibeuplink.web.customChannel03.description = benutzerdefinierter Kanal 04 -thing-type.config.nibeuplink.web.customChannel03.label = Kanal 05 -thing-type.config.nibeuplink.web.customChannel03.description = benutzerdefinierter Kanal 05 -thing-type.config.nibeuplink.web.customChannel03.label = Kanal 06 -thing-type.config.nibeuplink.web.customChannel03.description = benutzerdefinierter Kanal 06 -thing-type.config.nibeuplink.web.customChannel03.label = Kanal 07 -thing-type.config.nibeuplink.web.customChannel03.description = benutzerdefinierter Kanal 07 -thing-type.config.nibeuplink.web.customChannel03.label = Kanal 08 -thing-type.config.nibeuplink.web.customChannel03.description = benutzerdefinierter Kanal 08 diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/base-channel-groups.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/base-channel-groups.xml index 6cf7c16a94d58..882db8c08f5c5 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/base-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/base-channel-groups.xml @@ -6,48 +6,190 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + Current outdoor temperature + + + + EB100-BT1 Outdoor temperature average + + + + Degree minutes, 16bit value (-32768 < x < 32767). Values outside valid values are rounded to the + closest valid value. + + /Manage/4.9.3 + -?[0-9]+ + + + + + Calculated supply temperature for the climate system + + + + External supply temperature, BT25 + + + + Room Temperature S1 (BT50) + + + + External Adjustment Activated Via Input S1 + + 0 + 1 + + + + + Supply temperature for system 1 + + + + Return temperature + + + + Current flow EP14|Current flow EP15 + + + + BE3 Current + + + + BE2 Current + + + + BE1 Current + + + + states if internal electric additional heater is blocked + + 0 + 1 + + + + + Total electric additive operation time + + + + Current power from the internal electrical addition + + + + Maximum power from the internal electrical addition + + + + Maximum power from the internal electrical addition in SG-Ready Mode + + + + Accumulated energy production as calculated by the heat meter + + + + Accumulated energy production as calculated by the heat meter + + + + Accumulated energy production as calculated by the heat meter + + + + states if Holiday mode is activated + + /Manage/4.7 + .* + 0 + 10 + + + + + states if the compressor is blocked + + 0 + 1 + + + + + Supply Pump Speed, EP14 (GP6) + - - - - - - - - - - - - - + + + Hot water top temperature, BT7 + + + + Hot water load temperature, BT6 + + + + Accumulated energy production as calculated by the heat meter + + + + Accumulated energy production as calculated by the heat meter + + + + Temporary hot water lux mode + + /Manage/2.1 + [01234] + + + + + The currently active hotwater mode + + /Manage/2.2 + [012] + + + + + Start temperature for heating water in Economy mode + + + + Stop temperature for heating water in Economy mode + + + + Start temperature for heating water in Normal mode + + + + Stop temperature for heating water in Normal mode + + + + Start temperature for heating water in Luxury mode + + + + Stop temperature for heating water in Luxory mode + + + + Stop temperature for heating water in periodic heating + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/base-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/base-channel-types.xml deleted file mode 100644 index e088b84955291..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/base-channel-types.xml +++ /dev/null @@ -1,272 +0,0 @@ - - - - Switch - - states if the compressor is blocked - - - - Switch - - states if internal electric additional heater is blocked - - - - Number:Temperature - - Current outdoor temperature - - - - - Number:Temperature - - Supply temperature for system 1 - - - - - Number:Temperature - - Return temperature - - - - - Number:Temperature - - Hot water top temperature, BT7 - - - - - Number:Temperature - - Hot water load temperature, BT6 - - - - - Number:Temperature - - - - - - - Number:Temperature - - EB100-BT1 Outdoor temperature average - - - - - Number:Temperature - - External supply temperature, BT25 - - - - - Number:Dimensionless - - Current flow EP14|Current flow EP15 - - - - - Number:ElectricCurrent - - - - - - - Number:ElectricCurrent - - - - - - - Number:ElectricCurrent - - - - - - - Number - - Degree minutes, 16bit value (-32768 < x < 32767). Values outside valid values are rounded to the closest valid value. - - - - - Number:Temperature - - Calculated supply temperature for the climate system - - - - - Number:Time - - Total electric additive operation time - - - - - Number:Power - - Current power from the internal electrical addition - - - - - Switch - - - - - - Number:Dimensionless - - Supply Pump Speed, EP14 (GP6) - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - - Number - - The currently active hotwater mode - - - - - - - - - - Number:Temperature - - Start temperature for heating water in Luxury mode - - - - - Number:Temperature - - Start temperature for heating water in Normal mode - - - - - Number:Temperature - - Start temperature for heating water in Economy mode - - - - - Number:Temperature - - Stop temperature for heating water in periodic heating - - - - - Number:Temperature - - Stop temperature for heating water in Luxory mode - - - - - Number:Temperature - - Stop temperature for heating water in Normal mode - - - - - Number:Temperature - - Stop temperature for heating water in Economy mode - - - - - Number:Power - - - - - - - Switch - - - - - Number - - Temporary hot water lux mode - - - - - - - - - - - - Number:Power - - - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/custom-channel-groups.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/custom-channel-groups.xml deleted file mode 100644 index a2d2d17d66346..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/custom-channel-groups.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/custom-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/custom-channel-types.xml deleted file mode 100644 index b3a8674d85276..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/custom-channel-types.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - Number - - - - - - - Number - - - - - - - Number - - - - - - - Number - - - - - - - Number - - - - - - - Number - - - - - - - Number - - - - - - - Number - - - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-channel-groups.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-channel-groups.xml index 56d3612ed74bd..51ad662b1b137 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-channel-groups.xml @@ -6,32 +6,76 @@ - - - + + + Accumulated energy production as calculated by the heat meter + + + + Calculated supply temperature in cooling mode for the climate system + + + + State of the HPAC accessory + - - - - - - - - - - + + + Total compressor operation time in hot water mode + + + + Total compressor operation time + + + + Number of compressor starts + + + + Suction temperature, BT17 + + + + Liquid line temperature, BT15 + + + + Hot gas temperature, BT14 + + + + Condensor out temperature, BT12 + + + + Brine in temperature, BT10 + + + + Brine out temperature, BT11 + + + + Brine pump speed EP14 (GP2) + - - - + + + Exhaust Air Temperature (BT20) + + + + Vented Air Temperature (BT21) + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-channel-types.xml deleted file mode 100644 index f07a86c2b531e..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-channel-types.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - Number:Temperature - - Condensor out temperature, BT12 - - - - - Number:Temperature - - Hot gas temperature, BT14 - - - - - Number:Temperature - - Liquid line temperature, BT15 - - - - - Number:Temperature - - Suction temperature, BT17 - - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Temperature - - Brine in temperature, BT10 - - - - - Number:Temperature - - Brine out temperature, BT11 - - - - - Number:Temperature - - Calculated supply temperature in cooling mode for the climate system - - - - - Number - - Number of compressor starts - - - - - Number - - State of the HPAC accessory - - - - - - - - - - - - - - Number:Dimensionless - - Brine pump speed EP14 (GP2) - - - - - Number:Time - - Total compressor operation time - - - - - Number:Time - - Total compressor operation time in hot water mode - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-thing.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-thing.xml index 9f663cab7feb7..c9d0f37e53121 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-thing.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1145-thing.xml @@ -3,17 +3,16 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + Nibe F1145 heat pump connected through Nibe UpLink - - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-channel-groups.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-channel-groups.xml index 4d601a8928a58..7eb14bb338aa5 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-channel-groups.xml @@ -6,32 +6,80 @@ - + + + Accumulated energy production as calculated by the heat meter + - - - - - - - - - - - - - + + + Total compressor operation time in hot water mode + + + + Total compressor operation time + + + + Number of compressor starts + + + + Suction temperature, BT17 + + + + Liquid line temperature, BT15 + + + + Hot gas temperature, BT14 + + + + Condensor out temperature, BT12 + + + + The compressor frequency the compressor is currently running at + + + + The current minimum frequency of the compressor + + + + The current maximum frequency of the compressor + + + + Brine in temperature, BT10 + + + + Brine out temperature, BT11 + + + + Brine pump speed EP14 (GP2) + - - + + + Exhaust Air Temperature (BT20) + + + + Vented Air Temperature (BT21) + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-channel-types.xml deleted file mode 100644 index 465441d03f982..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-channel-types.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - Number:Temperature - - Condensor out temperature, BT12 - - - - - Number:Temperature - - Hot gas temperature, BT14 - - - - - Number:Temperature - - Liquid line temperature, BT15 - - - - - Number:Temperature - - Suction temperature, BT17 - - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Frequency - - The current minimum frequency of the compressor - - - - - Number:Frequency - - The current maximum frequency of the compressor - - - - - Number:Frequency - - The compressor frequency the compressor is currently running at - - - - - Number - - Number of compressor starts - - - - - Number:Time - - Total compressor operation time - - - - - Number:Time - - Total compressor operation time in hot water mode - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - - Number:Dimensionless - - Brine pump speed EP14 - - - - - Number:Temperature - - Brine in temperature, BT10 - - - - - Number:Temperature - - Brine out temperature, BT11 - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-thing.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-thing.xml index 39797efc21935..941c99fcfb19f 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-thing.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f1155-thing.xml @@ -3,17 +3,16 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + Nibe F1155 heat pump connected through Nibe UpLink - - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-channel-groups.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-channel-groups.xml index 1def76d77f310..cd93a16f57b1d 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-channel-groups.xml @@ -6,32 +6,95 @@ - - - - - - - - - - - - - + + + Chargepump Speed + + + + Total compressor operation time in hot water mode + + + + Total compressor operation time + + + + Number of compressor starts + + + + Suction temperature, BT17 + + + + Liquid line temperature, BT15 + + + + Hot gas temperature, BT14 + + + + Condensor out temperature, BT12 + + + + Evaporator Temp (BT16) + + + + The compressor frequency the compressor is currently running at + + + + The current minimum frequency of the compressor + + + + The current maximum frequency of the compressor + + + + Defrosting time, no defrosting heater in the product + - - - - - - - - + + + The current fan speed + + + + Exhaust Air Temperature (BT20) + + + + Vented Air Temperature (BT21) + + + + Reference value for the airflow. + + + + Adjusted BS1 Air Flow (BT100) + + + + Airflow Reduction + + + + Air Mix + + + + External airmix temperature BT28 + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-channel-types.xml deleted file mode 100644 index c2381392307d3..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-channel-types.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - - Number:Dimensionless - - The current fan speed - - - - - Number:Temperature - - Condensor out temperature, BT12 - - - - - Number:Temperature - - Hot gas temperature, BT14 - - - - - Number:Temperature - - Liquid line temperature, BT15 - - - - - Number:Temperature - - - - - - - Number:Temperature - - Suction temperature, BT17 - - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Temperature - - External airmix temperature BT28 - - - - - Number - - - - - - - Number - - - - - - - Number:Time - - Defrosting time, no defrosting heater in the product - - - - - Number:Frequency - - The current minimum frequency of the compressor - - - - - Number:Frequency - - The current maximum frequency of the compressor - - - - - Number - - Reference value for the airflow. - - - - - Number - - - - - - - Number:Frequency - - The compressor frequency the compressor is currently running at - - - - - Number:Dimensionless - - - - - - - Number - - Number of compressor starts - - - - - Number:Time - - Total compressor operation time - - - - - Number:Time - - Total compressor operation time in hot water mode - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-thing.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-thing.xml index 950ea80751773..c1062e24e1b66 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-thing.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f730-thing.xml @@ -3,16 +3,15 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + Nibe F730 heat pump connected through Nibe UpLink - - - - - + + + + - + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-channel-groups.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-channel-groups.xml index 76de534d8ca02..e0ef79d532a75 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-channel-groups.xml @@ -6,28 +6,83 @@ - - - - - - - - - - - - + + + Chargepump Speed + + + + Total compressor operation time in hot water mode + + + + Total compressor operation time + + + + Number of compressor starts + + + + Suction temperature, BT17 + + + + Liquid line temperature, BT15 + + + + Hot gas temperature, BT14 + + + + Condensor out temperature, BT12 + + + + Evaporator Temp (BT16) + + + + The compressor frequency the compressor is currently running at + + + + The current minimum frequency of the compressor + + + + The current maximum frequency of the compressor + - - - - - + + + Exhaust Air Temperature (BT20) + + + + Vented Air Temperature (BT21) + + + + Reference value for the airflow. + + + + Adjusted BS1 Air Flow (BT100) + + + + Currently selected fan speed + + /Manage/1.2 + [01234] + + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-channel-types.xml deleted file mode 100644 index 84d25f2723b64..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-channel-types.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - Number:Temperature - - Condensor out temperature, BT12 - - - - - Number:Temperature - - Hot gas temperature, BT14 - - - - - Number:Temperature - - Liquid line temperature, BT15 - - - - - Number:Temperature - - - - - - - Number:Temperature - - Suction temperature, BT17 - - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number - - - - - - - Number - - Currently selected fan speed - - - - - - - - - - - - Number:Frequency - - The current minimum frequency of the compressor - - - - - Number:Frequency - - The current maximum frequency of the compressor - - - - - Number - - Reference value for the airflow. - - - - - Number:Frequency - - The compressor frequency the compressor is currently running at - - - - - Number:Dimensionless - - - - - - - Number - - Number of compressor starts - - - - - Number:Time - - Total compressor operation time - - - - - Number:Time - - Total compressor operation time in hot water mode - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-thing.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-thing.xml index 5f467ac077921..fced2ca8f8018 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-thing.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/f750-thing.xml @@ -3,16 +3,15 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + Nibe F750 heat pump connected through Nibe UpLink - - - - - + + + + - + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/readonly-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/readonly-channel-types.xml new file mode 100644 index 0000000000000..e8af9a8cbc42f --- /dev/null +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/readonly-channel-types.xml @@ -0,0 +1,122 @@ + + + + + Number + + + + + + Number + + + + + + Number + + + + + + Switch + + + + + Number:Temperature + + + + + + Number:Dimensionless + + + + + + Number:ElectricCurrent + + + + + + Number:Time + + + + + + Number:Time + + + + + + Number:Frequency + + + + + + Number:Frequency + + + + + + Number:Power + + + + + + Number:Energy + + + + + + Number:Pressure + + + + + + Number:Dimensionless + + + + + + Number + + + + + + + + + + + Number + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/readwrite-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/readwrite-channel-types.xml new file mode 100644 index 0000000000000..1168b49dccee6 --- /dev/null +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/readwrite-channel-types.xml @@ -0,0 +1,91 @@ + + + + + Number + + + + + + Number + + + + + + Number + + + + + + Number + + + + + + Number + + + + + + Number + + + + + + Switch + + + + + Number + + + + + + Number + + + + + + + + + + + + + Number + + + + + + + + + + + Number + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-channel-groups.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-channel-groups.xml index 10e886db764c1..b016c897889f9 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-channel-groups.xml @@ -6,50 +6,184 @@ - - - - - - - + + + Calculated supply temperature in cooling mode for the climate system + + + + Supply Temp at internal additional heater (BT63) + + + + Accumulated energy production as calculated by the heat meter + + + + Offset of the heat curve, see manual for more information + + /Manage/1.9.1.1-S1 + [-1]*[0-9] + + + + + When activated the system uses the room sensor 0=Off 1=On + + /Manage/1.9.4 + .* + 0 + 1 + + + + + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. + + /Manage/1.9.4 + [0123456]*[0-9] + + + + + Setting of how much the difference between set and actual room temperature should affect the supply + temperature in cooling mode. + + /Manage/1.9.4 + [0123456]*[0-9] + + - - - - - - - - - - - - - - - - - - - + + + Current outdoor temperature, BT28 + + + + Speed Charge Pump + + + + Defrosting state of the outdoor unit + + + + Total operation time of compressor in hotwater mode + + + + Total operation time of compressor in cooling mode + + + + Total operation time of compressor + + + + Total compressor starts + + + + Suction temperature, BT17 + + + + Liquid line temperature, BT15 + + + + Hot gas temperature, BT14 + + + + Condensor temperature, BT12 + + + + Return temperature, BT3 + + + + Evaporator temperature, BT16 + + + + Pressure Sensor (BT4) + + + + The desired frequency as shown in service info + + + + Actual compressor frequency of the outdoor unit + + + + rotection status register of the outdoor unit + + 0 + 1 + + + + + Low pressure sensor outdoor unit + + + + Compressor state + - - - - - - - - + + + Exhaust Air Temperature (BT20) + + + + Vented Air Temperature (BT21) + + + + Supply Air Temperature (BT22) + + + + Outdoor Temperature (BT23) + + + + Indicates the speed of the GQ2 fan speed on the ERS accessory. + + + + Indicates the speed of the GQ3 fan speed on the ERS accessory. + + + + Indicates if the ERS accessory is externaly blocked. + + 0 + 1 + + + + + Currently selected fan speed + + /Manage/1.2 + [01234] + + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-channel-types.xml deleted file mode 100644 index e72dfc2fa9c71..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-channel-types.xml +++ /dev/null @@ -1,253 +0,0 @@ - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Dimensionless - - Indicates the speed of the GQ2 fan speed on the ERS accessory. - - - - - Number:Dimensionless - - Indicates the speed of the GQ3 fan speed on the ERS accessory. - - - - - Number:Time - - - - - - - Number:Frequency - - The desired frequency as shown in service info - - - - - Number:Temperature - - - - - - - Switch - - Indicates if the ERS accessory is externaly blocked. - - - - Number:Temperature - - Return temperature, BT3 - - - - - Number:Temperature - - Condensor temperature, BT12 - - - - - Number:Temperature - - Hot gas temperature, BT14 - - - - - Number:Temperature - - Liquid line temperature, BT15 - - - - - Number:Temperature - - Suction temperature, BT17 - - - - - Number - - - - - - - Number:Time - - - - - - - Number:Time - - - - - - - Number:Temperature - - Calculated supply temperature in cooling mode for the climate system - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - - Number:Temperature - - Current outdoor temperature, BT28 - - - - - Number:Temperature - - Evaporator temperature, BT16 - - - - - Number:Dimensionless - - - - - - - Number - - - - - - - Number:Pressure - - - - - - - Number:Pressure - - - - - - - Number:Frequency - - - - - - - Switch - - - - - - Number - - Defrosting state of the outdoor unit - - - - - - - - - - Number - - Offset of the heat curve, see manual for more information - - - - - Number - - Currently selected fan speed - - - - - - - - - - - - Switch - - When activated the system uses the room sensor 0=Off 1=On - - - - Number - - Setting of how much the difference between set and actual room temperature should affect the supply temperature. - - - - - Number - - Setting of how much the difference between set and actual room temperature should affect the supply temperature in cooling mode. - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-thing.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-thing.xml index aa8e1fb15e6af..fba0986b6939e 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-thing.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm310-thing.xml @@ -3,17 +3,16 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + Nibe VVM310 / VVM500 heat pump connected through Nibe UpLink - - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-channel-groups.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-channel-groups.xml index d8979afae014c..4cb0467e34e70 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-channel-groups.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-channel-groups.xml @@ -6,54 +6,216 @@ - - - - - - - - - - - + + + Calculated supply temperature in cooling mode for the climate system + + + + Supply Temp at internal additional heater (BT63) + + + + Accumulated energy production as calculated by the heat meter + + + + Offset of the heat curve, see manual for more information + + /Manage/1.9.1.1-S1 + [-1]*[0-9] + + + + + When activated the system uses the room sensor 0=Off 1=On + + /Manage/1.9.4 + .* + 0 + 1 + + + + + Setting of how much the difference between set and actual room temperature should affect the supply + temperature. + + /Manage/1.9.4 + [0123456]*[0-9] + + + + + Setting of how much the difference between set and actual room temperature should affect the supply + temperature in cooling mode. + + /Manage/1.9.4 + [0123456]*[0-9] + + + + + Start Temperature Cooling in Auto mode + + /Manage/4.9.2 + [0-9]*[0-9] + + + + + Stop Temperature Heating in Auto mode + + /Manage/4.9.2 + [0-9]*[0-9] + + + + + Stop Temperature Additive heater in Auto mode + + /Manage/4.9.2 + [0-9]*[0-9] + + + + + Outdoor Filter Time in Auto mode + + /Manage/4.9.2 + [0-4]*[0-9] + + - - - - - - - - - - - - - - - - - - - + + + Current outdoor temperature, BT28 + + + + Speed Charge Pump + + + + Defrosting state of the outdoor unit + + + + Total operation time of compressor in hotwater mode + + + + Total operation time of compressor in cooling mode + + + + Total operation time of compressor + + + + Total compressor starts + + + + Suction temperature, BT17 + + + + Liquid line temperature, BT15 + + + + Hot gas temperature, BT14 + + + + Condensor temperature, BT12 + + + + Return temperature, BT3 + + + + Evaporator temperature, BT16 + + + + Pressure Sensor (BT4) + + + + The desired frequency as shown in service info + + + + Actual compressor frequency of the outdoor unit + + + + rotection status register of the outdoor unit + + 0 + 1 + + + + + Low pressure sensor outdoor unit + + + + Compressor state + - - - - - - - - + + + Exhaust Air Temperature (BT20) + + + + Vented Air Temperature (BT21) + + + + Supply Air Temperature (BT22) + + + + Outdoor Temperature (BT23) + + + + Indicates the speed of the GQ2 fan speed on the ERS accessory. + + + + Indicates the speed of the GQ3 fan speed on the ERS accessory. + + + + Indicates if the ERS accessory is externaly blocked. + + 0 + 1 + + + + + Currently selected fan speed + + /Manage/1.2 + [01234] + + diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-channel-types.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-channel-types.xml deleted file mode 100644 index ae163af65cb86..0000000000000 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-channel-types.xml +++ /dev/null @@ -1,281 +0,0 @@ - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Temperature - - - - - - - Number:Dimensionless - - Indicates the speed of the GQ2 fan speed on the ERS accessory. - - - - - Number:Dimensionless - - Indicates the speed of the GQ3 fan speed on the ERS accessory. - - - - - Number:Time - - - - - - - Number:Frequency - - The desired frequency as shown in service info - - - - - Number:Temperature - - - - - - - Switch - - Indicates if the ERS accessory is externaly blocked. - - - - Number:Temperature - - Return temperature, BT3 - - - - - Number:Temperature - - Condensor temperature, BT12 - - - - - Number:Temperature - - Hot gas temperature, BT14 - - - - - Number:Temperature - - Liquid line temperature, BT15 - - - - - Number:Temperature - - Suction temperature, BT17 - - - - - Number - - - - - - - Number:Time - - - - - - - Number:Time - - - - - - - Number:Temperature - - Calculated supply temperature in cooling mode for the climate system - - - - - Number:Energy - - Accumulated energy production as calculated by the heat meter - - - - - Number:Temperature - - Current outdoor temperature, BT28 - - - - - Number:Temperature - - Evaporator temperature, BT16 - - - - - Number:Dimensionless - - - - - - - Number - - - - - - - Number:Pressure - - - - - - - Number:Pressure - - - - - - - Number:Frequency - - - - - - - Switch - - - - - - Number - - Defrosting state of the outdoor unit - - - - - - - - - - Number - - Offset of the heat curve, see manual for more information - - - - - Number - - Currently selected fan speed - - - - - - - - - - - - Number - - Start Temperature Cooling in Auto mode - - - - - Number - - Stop Temperature Heating in Auto mode - - - - - Number - - Stop Temperature Additive heater in Auto mode - - - - - Number - - Outdoor Filter Time in Auto mode - - - - - Switch - - When activated the system uses the room sensor 0=Off 1=On - - - - Number - - Setting of how much the difference between set and actual room temperature should affect the supply temperature. - - - - - Number - - Setting of how much the difference between set and actual room temperature should affect the supply temperature in cooling mode. - - - - diff --git a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-thing.xml b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-thing.xml index 4825b926b584a..724e20caf4065 100644 --- a/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-thing.xml +++ b/bundles/org.openhab.binding.nibeuplink/src/main/resources/ESH-INF/thing/vvm320-thing.xml @@ -3,17 +3,16 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + Nibe VVM320 / VVM325 heat pump connected through Nibe UpLink - - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.nikobus/pom.xml b/bundles/org.openhab.binding.nikobus/pom.xml index ee1d1f9774b6b..f935ec87e7e07 100644 --- a/bundles/org.openhab.binding.nikobus/pom.xml +++ b/bundles/org.openhab.binding.nikobus/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.nikobus diff --git a/bundles/org.openhab.binding.nikobus/src/main/feature/feature.xml b/bundles/org.openhab.binding.nikobus/src/main/feature/feature.xml index 33cc08cfaf512..8eb000b93771b 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.nikobus/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.nikobus/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.nikobus/${project.version} + diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/NikobusBindingConstants.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/NikobusBindingConstants.java index bb52708ed396a..daf1fed1a09a3 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/NikobusBindingConstants.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/NikobusBindingConstants.java @@ -44,5 +44,4 @@ public class NikobusBindingConstants { public static final String CONFIG_IMPACTED_MODULES = "impactedModules"; public static final String CONFIG_ADDRESS = "address"; public static final String CONFIG_PORT_NAME = "port"; - } diff --git a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusPushButtonHandler.java b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusPushButtonHandler.java index 32166b9351337..926732ff64881 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusPushButtonHandler.java +++ b/bundles/org.openhab.binding.nikobus/src/main/java/org/openhab/binding/nikobus/internal/handler/NikobusPushButtonHandler.java @@ -97,7 +97,6 @@ SwitchModuleGroup getGroup() { protected int getMinimalNumberOfSegments() { return 3; } - } private static final String END_OF_TRANSMISSION = "\r#E1"; diff --git a/bundles/org.openhab.binding.nikobus/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.nikobus/src/main/resources/ESH-INF/thing/thing-types.xml index 10cccf2538347..955380fa2d87d 100644 --- a/bundles/org.openhab.binding.nikobus/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.nikobus/src/main/resources/ESH-INF/thing/thing-types.xml @@ -12,6 +12,7 @@ serial-port + false The serial port used to connect to the Nikobus PC Link. @@ -24,14 +25,14 @@ - + A single push button - + @@ -61,7 +62,7 @@ - + @@ -116,7 +117,7 @@ - + @@ -171,7 +172,7 @@ - + diff --git a/bundles/org.openhab.binding.nikohomecontrol/pom.xml b/bundles/org.openhab.binding.nikohomecontrol/pom.xml index 43709908c91be..ac0f66ae38c2f 100644 --- a/bundles/org.openhab.binding.nikohomecontrol/pom.xml +++ b/bundles/org.openhab.binding.nikohomecontrol/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.nikohomecontrol diff --git a/bundles/org.openhab.binding.nikohomecontrol/src/main/feature/feature.xml b/bundles/org.openhab.binding.nikohomecontrol/src/main/feature/feature.xml index c4c61bff03583..e26436045dd9e 100644 --- a/bundles/org.openhab.binding.nikohomecontrol/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.nikohomecontrol/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mqtt - mvn:org.openhab.addons.bundles/org.openhab.binding.nikohomecontrol/${project.version} - + + openhab-runtime-base + openhab-transport-mqtt + mvn:org.openhab.addons.bundles/org.openhab.binding.nikohomecontrol/${project.version} + diff --git a/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc1/NhcAction1.java b/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc1/NhcAction1.java index 3a02cb323a6d7..8ba8ab1f35d2f 100644 --- a/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc1/NhcAction1.java +++ b/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc1/NhcAction1.java @@ -65,9 +65,9 @@ private interface Action { * Sets state of action. This is the version for Niko Home Control I. * * @param newState - The allowed values depend on the action type. - * switch action: 0 or 100 - * dimmer action: between 0 and 100 - * rollershutter action: between 0 and 100 + * switch action: 0 or 100 + * dimmer action: between 0 and 100 + * rollershutter action: between 0 and 100 */ @Override public void setState(int newState) { @@ -235,7 +235,7 @@ private void executeRollershutterTask() { * position. * * @param currentValue current percent position - * @param newValue new percent position + * @param newValue new percent position * */ private void scheduleRollershutterStop(int currentValue, int newValue) { diff --git a/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc1/NhcThermostat1.java b/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc1/NhcThermostat1.java index 7554cecdf47d9..844908237d9b8 100644 --- a/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc1/NhcThermostat1.java +++ b/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc1/NhcThermostat1.java @@ -51,7 +51,7 @@ public void executeMode(int mode) { * Sends thermostat setpoint to Niko Home Control. * * @param overrule temperature to overrule the setpoint in 0.1°C multiples - * @param time time duration in min for overrule + * @param time time duration in min for overrule */ @Override public void executeOverrule(int overrule, int overruletime) { diff --git a/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc2/NhcAction2.java b/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc2/NhcAction2.java index c71910e8108af..a49a5367ba250 100644 --- a/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc2/NhcAction2.java +++ b/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc2/NhcAction2.java @@ -88,14 +88,19 @@ public void setBooleanState(boolean state) { * Sets state of action. This version is used for Niko Home Control II. * * @param state - The allowed values depend on the action type. - * switch action: 0 or 100 - * dimmer action: between 0 and 100 - * rollershutter action: between 0 and 100 + * switch action: 0 or 100 + * dimmer action: between 0 and 100 + * rollershutter action: between 0 and 100 */ @Override public void setState(int state) { this.state = state; - if (booleanState) { // only send the update to the event handler if on + if (getType().equals(ActionType.DIMMER)) { // for dimmers, only send the update to the event + // handler if on + if (booleanState) { + updateState(); + } + } else { updateState(); } } @@ -104,9 +109,9 @@ public void setState(int state) { * Sends action to Niko Home Control. This version is used for Niko Home Control II, that has extra status options. * * @param command - The allowed values depend on the action type. - * switch action: On or Off - * dimmer action: between 0 and 100, On or Off - * rollershutter action: between 0 and 100, Up, Down or Stop + * switch action: On or Off + * dimmer action: between 0 and 100, On or Off + * rollershutter action: between 0 and 100, Up, Down or Stop */ @Override public void execute(String command) { diff --git a/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc2/NikoHomeControlCommunication2.java b/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc2/NikoHomeControlCommunication2.java index 3055a99b4f476..4c7ebe3e6b721 100644 --- a/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc2/NikoHomeControlCommunication2.java +++ b/bundles/org.openhab.binding.nikohomecontrol/src/main/java/org/openhab/binding/nikohomecontrol/internal/protocol/nhc2/NikoHomeControlCommunication2.java @@ -407,10 +407,12 @@ private void addDevice(NhcDevice2 device) { thermostats.put(device.uuid, nhcThermostat); } } else if ("centralmeter".equals(device.type)) { - logger.debug("Niko Home Control: adding centralmeter device {}, {}", device.uuid, device.name); - NhcEnergyMeter2 nhcEnergyMeter = new NhcEnergyMeter2(device.uuid, device.name, device.model, - device.technology, this, scheduler); - energyMeters.put(device.uuid, nhcEnergyMeter); + if (!energyMeters.containsKey(device.uuid)) { + logger.debug("Niko Home Control: adding centralmeter device {}, {}", device.uuid, device.name); + NhcEnergyMeter2 nhcEnergyMeter = new NhcEnergyMeter2(device.uuid, device.name, device.model, + device.technology, this, scheduler); + energyMeters.put(device.uuid, nhcEnergyMeter); + } } else { logger.debug("Niko Home Control: device type {} not supported for {}, {}", device.type, device.uuid, device.name); @@ -482,10 +484,8 @@ private void updateLightState(NhcAction2 action, NhcDevice2 device) { private void updateRollershutterState(NhcAction2 action, NhcDevice2 device) { Optional positionProperty = device.properties.stream().filter(p -> (p.position != null)) .findFirst(); - Optional movingProperty = device.properties.stream().filter(p -> (p.moving != null)).findFirst(); - if (!(movingProperty.isPresent() && Boolean.parseBoolean(movingProperty.get().moving)) - && positionProperty.isPresent()) { + if (positionProperty.isPresent()) { action.setState(Integer.parseInt(positionProperty.get().position)); logger.debug("Niko Home Control: setting action {} internally to {}", action.getId(), positionProperty.get().position); @@ -559,7 +559,7 @@ private void updateEnergyMeterState(NhcEnergyMeter2 energyMeter, NhcDevice2 devi .ifPresent(electricalPower -> { try { energyMeter.setPower(Integer.parseInt(electricalPower)); - logger.debug("Niko Home Control: setting energy meter {} power to {}", energyMeter.getId(), + logger.trace("Niko Home Control: setting energy meter {} power to {}", energyMeter.getId(), electricalPower); } catch (NumberFormatException e) { energyMeter.setPower(null); @@ -567,7 +567,6 @@ private void updateEnergyMeterState(NhcEnergyMeter2 energyMeter, NhcDevice2 devi energyMeter.getId()); } }); - } @Override @@ -775,7 +774,7 @@ public void processMessage(String topic, byte[] payload) { logger.debug("Niko Home Control: received topic {}, payload {}", topic, message); notificationEvt(message); } else if ((profile + "/control/devices/evt").equals(topic)) { - logger.debug("Niko Home Control: received topic {}, payload {}", topic, message); + logger.trace("Niko Home Control: received topic {}, payload {}", topic, message); devicesEvt(message); } else if ((profile + "/control/devices/rsp").equals(topic)) { logger.debug("Niko Home Control: received topic {}, payload {}", topic, message); diff --git a/bundles/org.openhab.binding.nikohomecontrol/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.nikohomecontrol/src/main/resources/ESH-INF/thing/thing-types.xml index 15c4cf2add788..95ba063d7881a 100644 --- a/bundles/org.openhab.binding.nikohomecontrol/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.nikohomecontrol/src/main/resources/ESH-INF/thing/thing-types.xml @@ -8,8 +8,8 @@ This bridge represents a Niko Home Control I IP-interface - - + + @@ -26,7 +26,8 @@ - Refresh interval for connection with Niko Home Control IP-interface (min), default 300. If set to 0 or left empty, no refresh will be scheduled + Refresh interval for connection with Niko Home Control IP-interface (min), default 300. If set to 0 or + left empty, no refresh will be scheduled 300 true @@ -36,8 +37,8 @@ This bridge represents a Niko Home Control II Connected Controller - - + + @@ -60,12 +61,14 @@ - Token for Niko Home Control II hobby API, should not be empty. This token will have to be renewed after expiration (1 year after creation) + Token for Niko Home Control II hobby API, should not be empty. This token will have to be renewed after + expiration (1 year after creation) password - Refresh interval for connection with Connected Controller (min), default 300. If set to 0 or left empty, no refresh will be scheduled + Refresh interval for connection with Connected Controller (min), default 300. If set to 0 or left + empty, no refresh will be scheduled 300 true @@ -74,13 +77,13 @@ - - + + Pushbutton type action in Niko Home Control - + @@ -92,13 +95,13 @@ - - + + On/Off type action in Niko Home Control - + @@ -110,13 +113,13 @@ - - + + Dimmer type action in Niko Home Control - + @@ -134,13 +137,13 @@ - - + + Rollershutter type action in Niko Home Control - + @@ -152,16 +155,16 @@ - - + + Thermostat in the Niko Home Control system - - - - + + + + @@ -171,7 +174,8 @@ - Default overrule duration in minutes when an overrule temperature is set without providing overrule time, 60 minutes by default + Default overrule duration in minutes when an overrule temperature is set without providing overrule + time, 60 minutes by default 60 true @@ -179,12 +183,12 @@ - + Energy meter in the Niko Home Control system - + @@ -229,7 +233,7 @@ CurrentTemperature - + Number:Temperature @@ -239,14 +243,14 @@ TargetTemperature - + Number Time duration for overruling thermostat target temperature in min. Number - + Number @@ -271,7 +275,7 @@ Momentary power consumption/production (positive is consumption) Number - + diff --git a/bundles/org.openhab.binding.ntp/README.md b/bundles/org.openhab.binding.ntp/README.md index 0098aa6acc3ad..926dce9de8701 100644 --- a/bundles/org.openhab.binding.ntp/README.md +++ b/bundles/org.openhab.binding.ntp/README.md @@ -1,53 +1,53 @@ -# NTP Binding - -The NTP binding is used for displaying the local date and time based update from an NTP server. - -## Supported Things - -This binding supports one ThingType: ntp - -## Discovery - -Discovery is used to place one default item in the inbox as a convenient way to add a Thing for the local time. - -## Binding Configuration - -The binding has no configuration options, all configuration is done at Thing level. - -## Thing Configuration - -The thing has a few configuration options: - -| Option | Description | -|-----------------|--------------------------------------------------- | -| hostname | NTP host server, e.g. nl.pool.ntp.org | -| refreshInterval | Interval that new time updates are posted to the eventbus in seconds | -| refreshNtp | Number of updates between querying the NTP server (e.g. with refreshinterval = 60 (seconds) and refreshNtp = 30 the NTP server is queried each half hour. | -| timeZone | Timezone, can be left blank for using the default system one | -| locale | Locale, can be left blank for using the default system one | - - -## Channels - -The ntp binding has two channels: - -* `dateTime` which provides the data in a dateTime type -* `string` which provides the data in a string type. The string channel can be configured with the formatting of the date & time. This also allows proper representation of timezones other than the java machine default one. - -See the [java documentation](https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html) for the detailed information on the formatting - - - -## Full Example - -Things: - -``` -ntp:ntp:demo [ hostname="nl.pool.ntp.org", refreshInterval=60, refreshNtp=30 ] -``` - -Items: - -``` -DateTime Date "Date [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" { channel="ntp:ntp:demo:dateTime" } -``` +# NTP Binding + +The NTP binding is used for displaying the local date and time based update from an NTP server. + +## Supported Things + +This binding supports one ThingType: ntp + +## Discovery + +Discovery is used to place one default item in the inbox as a convenient way to add a Thing for the local time. + +## Binding Configuration + +The binding has no configuration options, all configuration is done at Thing level. + +## Thing Configuration + +The thing has a few configuration options: + +| Option | Description | +|-----------------|--------------------------------------------------- | +| hostname | NTP host server, e.g. nl.pool.ntp.org | +| refreshInterval | Interval that new time updates are posted to the eventbus in seconds | +| refreshNtp | Number of updates between querying the NTP server (e.g. with refreshinterval = 60 (seconds) and refreshNtp = 30 the NTP server is queried each half hour. | +| timeZone | Timezone, can be left blank for using the default system one | +| locale | Locale, can be left blank for using the default system one | + + +## Channels + +The ntp binding has two channels: + +* `dateTime` which provides the data in a dateTime type +* `string` which provides the data in a string type. The string channel can be configured with the formatting of the date & time. This also allows proper representation of timezones other than the java machine default one. + +See the [java documentation](https://docs.oracle.com/javase/8/docs/api/java/util/Formatter.html) for the detailed information on the formatting + + + +## Full Example + +Things: + +``` +ntp:ntp:demo [ hostname="nl.pool.ntp.org", refreshInterval=60, refreshNtp=30 ] +``` + +Items: + +``` +DateTime Date "Date [%1$tA, %1$td.%1$tm.%1$tY %1$tH:%1$tM]" { channel="ntp:ntp:demo:dateTime" } +``` diff --git a/bundles/org.openhab.binding.ntp/pom.xml b/bundles/org.openhab.binding.ntp/pom.xml index 3cb4f54ccb58e..9f8e3fd47e9f7 100644 --- a/bundles/org.openhab.binding.ntp/pom.xml +++ b/bundles/org.openhab.binding.ntp/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.ntp diff --git a/bundles/org.openhab.binding.ntp/src/main/feature/feature.xml b/bundles/org.openhab.binding.ntp/src/main/feature/feature.xml index 732776f8ae1f4..88ec1b45d7b23 100644 --- a/bundles/org.openhab.binding.ntp/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.ntp/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.ntp/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.ntp/${project.version} + diff --git a/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/NtpBindingConstants.java b/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/NtpBindingConstants.java index b7957e20eafce..1b559b2647001 100644 --- a/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/NtpBindingConstants.java +++ b/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/NtpBindingConstants.java @@ -1,51 +1,50 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.ntp.internal; - -import java.util.Collections; -import java.util.Set; - -import org.eclipse.smarthome.core.thing.ThingTypeUID; - -/** - * The {@link ntpBinding} class defines common constants, which are used across - * the whole binding. - * - * @author Marcel Verpaalen - Initial contribution - * - */ -public class NtpBindingConstants { - - private NtpBindingConstants() {} - - public static final String BINDING_ID = "ntp"; - - // List of all Thing Type UIDs - public static final ThingTypeUID THING_TYPE_NTP = new ThingTypeUID(BINDING_ID, "ntp"); - - // List of all Channel ids - public static final String CHANNEL_DATE_TIME = "dateTime"; - public static final String CHANNEL_STRING = "string"; - - // Custom Properties - public static final String PROPERTY_NTP_SERVER_HOST = "hostname"; - public static final String PROPERTY_REFRESH_INTERVAL = "refreshInterval"; - public static final String PROPERTY_REFRESH_NTP = "refreshNtp"; - public static final String PROPERTY_TIMEZONE = "timeZone"; - public static final String PROPERTY_LOCALE = "locale"; - public static final String PROPERTY_DATE_TIME_FORMAT = "DateTimeFormat"; - public static final String PROPERTY_NTP_SERVER_PORT = "serverPort"; - - public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_NTP); - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.ntp.internal; + +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link ntpBinding} class defines common constants, which are used across + * the whole binding. + * + * @author Marcel Verpaalen - Initial contribution + * + */ +@NonNullByDefault +public class NtpBindingConstants { + + public static final String BINDING_ID = "ntp"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_NTP = new ThingTypeUID(BINDING_ID, "ntp"); + + // List of all Channel ids + public static final String CHANNEL_DATE_TIME = "dateTime"; + public static final String CHANNEL_STRING = "string"; + + // Custom Properties + public static final String PROPERTY_NTP_SERVER_HOST = "hostname"; + public static final String PROPERTY_REFRESH_INTERVAL = "refreshInterval"; + public static final String PROPERTY_REFRESH_NTP = "refreshNtp"; + public static final String PROPERTY_TIMEZONE = "timeZone"; + public static final String PROPERTY_LOCALE = "locale"; + public static final String PROPERTY_DATE_TIME_FORMAT = "DateTimeFormat"; + public static final String PROPERTY_NTP_SERVER_PORT = "serverPort"; + + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_NTP); +} diff --git a/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/NtpHandlerFactory.java b/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/NtpHandlerFactory.java index 98fa35a67b2db..6e0ce58906f11 100644 --- a/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/NtpHandlerFactory.java +++ b/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/NtpHandlerFactory.java @@ -1,63 +1,63 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.ntp.internal; - -import static org.openhab.binding.ntp.internal.NtpBindingConstants.*; - -import org.eclipse.smarthome.core.i18n.LocaleProvider; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; -import org.openhab.binding.ntp.internal.handler.NtpHandler; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; - -/** - * The {@link NtpHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Marcel Verpaalen - Initial contribution - * @author Markus Rathgeb - Add locale provider support - */ -@Component(service = ThingHandlerFactory.class, configurationPid = "binding.ntp") -public class NtpHandlerFactory extends BaseThingHandlerFactory { - - private LocaleProvider localeProvider; - - @Reference - protected void setLocaleProvider(final LocaleProvider localeProvider) { - this.localeProvider = localeProvider; - } - - protected void unsetLocaleProvider(final LocaleProvider localeProvider) { - this.localeProvider = null; - } - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - - if (THING_TYPE_NTP.equals(thingTypeUID)) { - return new NtpHandler(thing, localeProvider); - } - - return null; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.ntp.internal; + +import static org.openhab.binding.ntp.internal.NtpBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.i18n.LocaleProvider; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.ntp.internal.handler.NtpHandler; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link NtpHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Marcel Verpaalen - Initial contribution + * @author Markus Rathgeb - Add locale provider support + */ +@NonNullByDefault +@Component(service = ThingHandlerFactory.class, configurationPid = "binding.ntp") +public class NtpHandlerFactory extends BaseThingHandlerFactory { + + private final LocaleProvider localeProvider; + + @Activate + public NtpHandlerFactory(final @Reference LocaleProvider localeProvider) { + this.localeProvider = localeProvider; + } + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_NTP.equals(thingTypeUID)) { + return new NtpHandler(thing, localeProvider); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/discovery/NtpDiscovery.java b/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/discovery/NtpDiscovery.java index 54cbcbca793fc..43ff128f22766 100644 --- a/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/discovery/NtpDiscovery.java +++ b/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/discovery/NtpDiscovery.java @@ -1,98 +1,97 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.ntp.internal.discovery; - -import static org.openhab.binding.ntp.internal.NtpBindingConstants.*; - -import java.util.HashMap; -import java.util.Map; -import java.util.TimeZone; -import java.util.concurrent.TimeUnit; - -import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; -import org.eclipse.smarthome.config.discovery.DiscoveryResult; -import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; -import org.eclipse.smarthome.config.discovery.DiscoveryService; -import org.eclipse.smarthome.core.i18n.LocaleProvider; -import org.eclipse.smarthome.core.i18n.TranslationProvider; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.osgi.service.component.annotations.Component; -import org.osgi.service.component.annotations.Reference; - -/** - * - * The {@link NtpDiscovery} is used to add a ntp Thing for the local time in the discovery inbox - * * - * - * @author Marcel Verpaalen - Initial contribution - */ -@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.ntp") -public class NtpDiscovery extends AbstractDiscoveryService { - - public NtpDiscovery() throws IllegalArgumentException { - super(SUPPORTED_THING_TYPES_UIDS, 2); - } - - @Override - protected void activate(Map configProperties) { - super.activate(configProperties); - } - - @Override - protected void modified(Map configProperties) { - super.modified(configProperties); - } - - @Override - protected void startBackgroundDiscovery() { - scheduler.schedule(() -> { - discoverNtp(); - }, 1, TimeUnit.SECONDS); - } - - @Override - protected void startScan() { - discoverNtp(); - } - - /** - * Add a ntp Thing for the local time in the discovery inbox - */ - private void discoverNtp() { - Map properties = new HashMap<>(4); - properties.put(PROPERTY_TIMEZONE, TimeZone.getDefault().getID()); - ThingUID uid = new ThingUID(THING_TYPE_NTP, "local"); - DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel("Local Time") - .build(); - thingDiscovered(result); - } - - @Reference - protected void setLocaleProvider(final LocaleProvider localeProvider) { - this.localeProvider = localeProvider; - } - - protected void unsetLocaleProvider(final LocaleProvider localeProvider) { - this.localeProvider = null; - } - - @Reference - protected void setTranslationProvider(TranslationProvider i18nProvider) { - this.i18nProvider = i18nProvider; - } - - protected void unsetTranslationProvider(TranslationProvider i18nProvider) { - this.i18nProvider = null; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.ntp.internal.discovery; + +import static org.openhab.binding.ntp.internal.NtpBindingConstants.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.TimeZone; +import java.util.concurrent.TimeUnit; + +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.core.i18n.LocaleProvider; +import org.eclipse.smarthome.core.i18n.TranslationProvider; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * + * The {@link NtpDiscovery} is used to add a ntp Thing for the local time in the discovery inbox + * * + * + * @author Marcel Verpaalen - Initial contribution + */ +@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.ntp") +public class NtpDiscovery extends AbstractDiscoveryService { + + public NtpDiscovery() throws IllegalArgumentException { + super(SUPPORTED_THING_TYPES_UIDS, 2); + } + + @Override + protected void activate(Map configProperties) { + super.activate(configProperties); + } + + @Override + protected void modified(Map configProperties) { + super.modified(configProperties); + } + + @Override + protected void startBackgroundDiscovery() { + scheduler.schedule(() -> { + discoverNtp(); + }, 1, TimeUnit.SECONDS); + } + + @Override + protected void startScan() { + discoverNtp(); + } + + /** + * Add a ntp Thing for the local time in the discovery inbox + */ + private void discoverNtp() { + Map properties = new HashMap<>(4); + properties.put(PROPERTY_TIMEZONE, TimeZone.getDefault().getID()); + ThingUID uid = new ThingUID(THING_TYPE_NTP, "local"); + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel("Local Time") + .build(); + thingDiscovered(result); + } + + @Reference + protected void setLocaleProvider(final LocaleProvider localeProvider) { + this.localeProvider = localeProvider; + } + + protected void unsetLocaleProvider(final LocaleProvider localeProvider) { + this.localeProvider = null; + } + + @Reference + protected void setTranslationProvider(TranslationProvider i18nProvider) { + this.i18nProvider = i18nProvider; + } + + protected void unsetTranslationProvider(TranslationProvider i18nProvider) { + this.i18nProvider = null; + } +} diff --git a/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/handler/NtpHandler.java b/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/handler/NtpHandler.java index c2d4369a097d0..dcd2569549b33 100644 --- a/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/handler/NtpHandler.java +++ b/bundles/org.openhab.binding.ntp/src/main/java/org/openhab/binding/ntp/internal/handler/NtpHandler.java @@ -1,271 +1,270 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.ntp.internal.handler; - -import static org.openhab.binding.ntp.internal.NtpBindingConstants.*; - -import java.io.IOException; -import java.math.BigDecimal; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.time.Instant; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - -import org.apache.commons.net.ntp.NTPUDPClient; -import org.apache.commons.net.ntp.TimeInfo; -import org.eclipse.smarthome.config.core.Configuration; -import org.eclipse.smarthome.core.i18n.LocaleProvider; -import org.eclipse.smarthome.core.library.types.DateTimeType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.Channel; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; -import org.eclipse.smarthome.core.types.Command; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * The NTP Refresh Service polls the configured timeserver with a configurable - * interval and posts a new event of type ({@link DateTimeType}. - * - * The {@link NtpHandler} is responsible for handling commands, which are sent - * to one of the channels. - * - * @author Marcel Verpaalen - Initial contribution OH2 ntp binding - * @author Thomas.Eichstaedt-Engelen OH1 ntp binding (getTime routine) - * @author Markus Rathgeb - Add locale provider - * @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType - */ - -public class NtpHandler extends BaseThingHandler { - - private final Logger logger = LoggerFactory.getLogger(NtpHandler.class); - - /** timeout for requests to the NTP server */ - private static final int NTP_TIMEOUT = 30000; - - public static final String DATE_PATTERN_WITH_TZ = "yyyy-MM-dd HH:mm:ss z"; - - /** for logging purposes */ - private final DateFormat SDF = new SimpleDateFormat(DATE_PATTERN_WITH_TZ); - - /** for publish purposes */ - private DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern(DATE_PATTERN_WITH_TZ); - - private final LocaleProvider localeProvider; - - ScheduledFuture refreshJob; - - /** NTP host */ - private String hostname; - /** NTP server port */ - private BigDecimal port; - /** refresh interval */ - private BigDecimal refreshInterval; - /** NTP refresh frequency */ - private BigDecimal refreshNtp = new BigDecimal(0); - /** Timezone */ - private TimeZone timeZone; - /** Locale */ - private Locale locale; - - /** NTP refresh counter */ - private int refreshNtpCount = 0; - /** NTP system time delta */ - private long timeOffset; - - private ChannelUID dateTimeChannelUID; - private ChannelUID stringChannelUID; - - public NtpHandler(final Thing thing, final LocaleProvider localeProvider) { - super(thing); - this.localeProvider = localeProvider; - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - // No specific commands tied to this, but we will trigger an update - this.refreshNtpCount = 0; - refreshTimeDate(); - } - - @Override - public void initialize() { - try { - logger.debug("Initializing NTP handler for '{}'.", getThing().getUID()); - - Configuration config = getThing().getConfiguration(); - hostname = config.get(PROPERTY_NTP_SERVER_HOST).toString(); - port = (BigDecimal) config.get(PROPERTY_NTP_SERVER_PORT); - refreshInterval = (BigDecimal) config.get(PROPERTY_REFRESH_INTERVAL); - refreshNtp = (BigDecimal) config.get(PROPERTY_REFRESH_NTP); - refreshNtpCount = 0; - - try { - Object timeZoneConfigValue = config.get(PROPERTY_TIMEZONE); - if (timeZoneConfigValue != null) { - timeZone = TimeZone.getTimeZone(timeZoneConfigValue.toString()); - } else { - timeZone = TimeZone.getDefault(); - logger.debug("{} using default TZ '{}', because configuration property '{}' is null.", - getThing().getUID(), timeZone, PROPERTY_TIMEZONE); - } - } catch (Exception e) { - timeZone = TimeZone.getDefault(); - logger.debug("{} using default TZ '{}' due to an occurred exception: ", getThing().getUID(), timeZone, - e); - } - - try { - Object localeStringConfigValue = config.get(PROPERTY_LOCALE); - if (localeStringConfigValue != null) { - locale = new Locale(localeStringConfigValue.toString()); - } else { - locale = localeProvider.getLocale(); - logger.debug("{} using default locale '{}', because configuration property '{}' is null.", - getThing().getUID(), locale, PROPERTY_LOCALE); - } - } catch (Exception e) { - locale = localeProvider.getLocale(); - logger.debug("{} using default locale '{}' due to an occurred exception: ", getThing().getUID(), locale, - e); - } - dateTimeChannelUID = new ChannelUID(getThing().getUID(), CHANNEL_DATE_TIME); - stringChannelUID = new ChannelUID(getThing().getUID(), CHANNEL_STRING); - try { - Channel stringChannel = getThing().getChannel(stringChannelUID.getId()); - if (stringChannel != null) { - Configuration cfg = stringChannel.getConfiguration(); - String dateTimeFormatString = cfg.get(PROPERTY_DATE_TIME_FORMAT).toString(); - if (!(dateTimeFormatString == null || dateTimeFormatString.isEmpty())) { - dateTimeFormat = DateTimeFormatter.ofPattern(dateTimeFormatString); - } else { - logger.debug("No format set in channel config for {}. Using default format.", stringChannelUID); - dateTimeFormat = DateTimeFormatter.ofPattern(DATE_PATTERN_WITH_TZ); - } - } else { - logger.debug("Missing channel: '{}'", stringChannelUID.getId()); - } - } catch (RuntimeException ex) { - logger.debug("No channel config or invalid format for {}. Using default format. ({})", stringChannelUID, - ex.getMessage()); - dateTimeFormat = DateTimeFormatter.ofPattern(DATE_PATTERN_WITH_TZ); - } - SDF.setTimeZone(timeZone); - dateTimeFormat.withZone(timeZone.toZoneId()); - - logger.debug( - "Initialized NTP handler '{}' with configuration: host '{}', refresh interval {}, timezone {}, locale {}.", - getThing().getUID(), hostname, refreshInterval, timeZone, locale); - startAutomaticRefresh(); - } catch (Exception ex) { - logger.error("Error occurred while initializing NTP handler: {}", ex.getMessage(), ex); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "@text/offline.conf-error-init-handler"); - } - } - - @Override - public void dispose() { - refreshJob.cancel(true); - super.dispose(); - } - - private void startAutomaticRefresh() { - refreshJob = scheduler.scheduleWithFixedDelay(() -> { - try { - refreshTimeDate(); - } catch (Exception e) { - logger.debug("Exception occurred during refresh: {}", e.getMessage(), e); - } - }, 0, refreshInterval.intValue(), TimeUnit.SECONDS); - } - - private synchronized void refreshTimeDate() { - if (timeZone != null && locale != null) { - long networkTimeInMillis; - if (refreshNtpCount <= 0) { - networkTimeInMillis = getTime(hostname); - timeOffset = networkTimeInMillis - System.currentTimeMillis(); - logger.debug("{} delta system time: {}", getThing().getUID(), timeOffset); - refreshNtpCount = refreshNtp.intValue(); - } else { - networkTimeInMillis = System.currentTimeMillis() + timeOffset; - refreshNtpCount--; - } - - ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(networkTimeInMillis), - timeZone.toZoneId()); - updateState(dateTimeChannelUID, new DateTimeType(zoned)); - updateState(stringChannelUID, new StringType(dateTimeFormat.format(zoned))); - } else { - logger.debug("Not refreshing, since we do not seem to be initialized yet"); - } - } - - /** - * Queries the given timeserver hostname and returns the time - * in milliseconds. - * - * @param hostname the timeserver to query - * @return the time in milliseconds or the current time of the system if an - * error occurs. - */ - public long getTime(String hostname) { - try { - NTPUDPClient timeClient = new NTPUDPClient(); - timeClient.setDefaultTimeout(NTP_TIMEOUT); - InetAddress inetAddress = InetAddress.getByName(hostname); - TimeInfo timeInfo = timeClient.getTime(inetAddress, port.intValue()); - timeInfo.computeDetails(); - - long serverMillis = timeInfo.getReturnTime() + timeInfo.getOffset(); - logger.debug("{} Got time update from host '{}': {}.", getThing().getUID(), hostname, - SDF.format(new Date(serverMillis))); - updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); - return serverMillis; - } catch (UnknownHostException uhe) { - logger.debug( - "{} The given hostname '{}' of the timeserver is unknown -> returning current sytem time instead. ({})", - getThing().getUID(), hostname, uhe.getMessage()); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "@text/offline.comm-error-unknown-host [\"" + (hostname == null ? "null" : hostname) + "\"]"); - } catch (IOException ioe) { - logger.debug( - "{} Couldn't establish network connection to host '{}' -> returning current sytem time instead. ({})", - getThing().getUID(), hostname, ioe.getMessage()); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "@text/offline.comm-error-connection [\"" + (hostname == null ? "null" : hostname) + "\"]"); - } - - return System.currentTimeMillis(); - } - - @Override - public void channelLinked(ChannelUID channelUID) { - refreshTimeDate(); - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.ntp.internal.handler; + +import static org.openhab.binding.ntp.internal.NtpBindingConstants.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.net.ntp.NTPUDPClient; +import org.apache.commons.net.ntp.TimeInfo; +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.i18n.LocaleProvider; +import org.eclipse.smarthome.core.library.types.DateTimeType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * The NTP Refresh Service polls the configured timeserver with a configurable + * interval and posts a new event of type ({@link DateTimeType}. + * + * The {@link NtpHandler} is responsible for handling commands, which are sent + * to one of the channels. + * + * @author Marcel Verpaalen - Initial contribution OH2 ntp binding + * @author Thomas.Eichstaedt-Engelen OH1 ntp binding (getTime routine) + * @author Markus Rathgeb - Add locale provider + * @author Erdoan Hadzhiyusein - Adapted the class to work with the new DateTimeType + */ + +public class NtpHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(NtpHandler.class); + + /** timeout for requests to the NTP server */ + private static final int NTP_TIMEOUT = 30000; + + public static final String DATE_PATTERN_WITH_TZ = "yyyy-MM-dd HH:mm:ss z"; + + /** for logging purposes */ + private final DateFormat SDF = new SimpleDateFormat(DATE_PATTERN_WITH_TZ); + + /** for publish purposes */ + private DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern(DATE_PATTERN_WITH_TZ); + + private final LocaleProvider localeProvider; + + ScheduledFuture refreshJob; + + /** NTP host */ + private String hostname; + /** NTP server port */ + private BigDecimal port; + /** refresh interval */ + private BigDecimal refreshInterval; + /** NTP refresh frequency */ + private BigDecimal refreshNtp = new BigDecimal(0); + /** Timezone */ + private TimeZone timeZone; + /** Locale */ + private Locale locale; + + /** NTP refresh counter */ + private int refreshNtpCount = 0; + /** NTP system time delta */ + private long timeOffset; + + private ChannelUID dateTimeChannelUID; + private ChannelUID stringChannelUID; + + public NtpHandler(final Thing thing, final LocaleProvider localeProvider) { + super(thing); + this.localeProvider = localeProvider; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + // No specific commands tied to this, but we will trigger an update + this.refreshNtpCount = 0; + refreshTimeDate(); + } + + @Override + public void initialize() { + try { + logger.debug("Initializing NTP handler for '{}'.", getThing().getUID()); + + Configuration config = getThing().getConfiguration(); + hostname = config.get(PROPERTY_NTP_SERVER_HOST).toString(); + port = (BigDecimal) config.get(PROPERTY_NTP_SERVER_PORT); + refreshInterval = (BigDecimal) config.get(PROPERTY_REFRESH_INTERVAL); + refreshNtp = (BigDecimal) config.get(PROPERTY_REFRESH_NTP); + refreshNtpCount = 0; + + try { + Object timeZoneConfigValue = config.get(PROPERTY_TIMEZONE); + if (timeZoneConfigValue != null) { + timeZone = TimeZone.getTimeZone(timeZoneConfigValue.toString()); + } else { + timeZone = TimeZone.getDefault(); + logger.debug("{} using default TZ '{}', because configuration property '{}' is null.", + getThing().getUID(), timeZone, PROPERTY_TIMEZONE); + } + } catch (Exception e) { + timeZone = TimeZone.getDefault(); + logger.debug("{} using default TZ '{}' due to an occurred exception: ", getThing().getUID(), timeZone, + e); + } + + try { + Object localeStringConfigValue = config.get(PROPERTY_LOCALE); + if (localeStringConfigValue != null) { + locale = new Locale(localeStringConfigValue.toString()); + } else { + locale = localeProvider.getLocale(); + logger.debug("{} using default locale '{}', because configuration property '{}' is null.", + getThing().getUID(), locale, PROPERTY_LOCALE); + } + } catch (Exception e) { + locale = localeProvider.getLocale(); + logger.debug("{} using default locale '{}' due to an occurred exception: ", getThing().getUID(), locale, + e); + } + dateTimeChannelUID = new ChannelUID(getThing().getUID(), CHANNEL_DATE_TIME); + stringChannelUID = new ChannelUID(getThing().getUID(), CHANNEL_STRING); + try { + Channel stringChannel = getThing().getChannel(stringChannelUID.getId()); + if (stringChannel != null) { + Configuration cfg = stringChannel.getConfiguration(); + String dateTimeFormatString = cfg.get(PROPERTY_DATE_TIME_FORMAT).toString(); + if (!(dateTimeFormatString == null || dateTimeFormatString.isEmpty())) { + dateTimeFormat = DateTimeFormatter.ofPattern(dateTimeFormatString); + } else { + logger.debug("No format set in channel config for {}. Using default format.", stringChannelUID); + dateTimeFormat = DateTimeFormatter.ofPattern(DATE_PATTERN_WITH_TZ); + } + } else { + logger.debug("Missing channel: '{}'", stringChannelUID.getId()); + } + } catch (RuntimeException ex) { + logger.debug("No channel config or invalid format for {}. Using default format. ({})", stringChannelUID, + ex.getMessage()); + dateTimeFormat = DateTimeFormatter.ofPattern(DATE_PATTERN_WITH_TZ); + } + SDF.setTimeZone(timeZone); + dateTimeFormat.withZone(timeZone.toZoneId()); + + logger.debug( + "Initialized NTP handler '{}' with configuration: host '{}', refresh interval {}, timezone {}, locale {}.", + getThing().getUID(), hostname, refreshInterval, timeZone, locale); + startAutomaticRefresh(); + } catch (Exception ex) { + logger.error("Error occurred while initializing NTP handler: {}", ex.getMessage(), ex); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error-init-handler"); + } + } + + @Override + public void dispose() { + refreshJob.cancel(true); + super.dispose(); + } + + private void startAutomaticRefresh() { + refreshJob = scheduler.scheduleWithFixedDelay(() -> { + try { + refreshTimeDate(); + } catch (Exception e) { + logger.debug("Exception occurred during refresh: {}", e.getMessage(), e); + } + }, 0, refreshInterval.intValue(), TimeUnit.SECONDS); + } + + private synchronized void refreshTimeDate() { + if (timeZone != null && locale != null) { + long networkTimeInMillis; + if (refreshNtpCount <= 0) { + networkTimeInMillis = getTime(hostname); + timeOffset = networkTimeInMillis - System.currentTimeMillis(); + logger.debug("{} delta system time: {}", getThing().getUID(), timeOffset); + refreshNtpCount = refreshNtp.intValue(); + } else { + networkTimeInMillis = System.currentTimeMillis() + timeOffset; + refreshNtpCount--; + } + + ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(networkTimeInMillis), + timeZone.toZoneId()); + updateState(dateTimeChannelUID, new DateTimeType(zoned)); + updateState(stringChannelUID, new StringType(dateTimeFormat.format(zoned))); + } else { + logger.debug("Not refreshing, since we do not seem to be initialized yet"); + } + } + + /** + * Queries the given timeserver hostname and returns the time + * in milliseconds. + * + * @param hostname the timeserver to query + * @return the time in milliseconds or the current time of the system if an + * error occurs. + */ + public long getTime(String hostname) { + try { + NTPUDPClient timeClient = new NTPUDPClient(); + timeClient.setDefaultTimeout(NTP_TIMEOUT); + InetAddress inetAddress = InetAddress.getByName(hostname); + TimeInfo timeInfo = timeClient.getTime(inetAddress, port.intValue()); + timeInfo.computeDetails(); + + long serverMillis = timeInfo.getReturnTime() + timeInfo.getOffset(); + logger.debug("{} Got time update from host '{}': {}.", getThing().getUID(), hostname, + SDF.format(new Date(serverMillis))); + updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); + return serverMillis; + } catch (UnknownHostException uhe) { + logger.debug( + "{} The given hostname '{}' of the timeserver is unknown -> returning current sytem time instead. ({})", + getThing().getUID(), hostname, uhe.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "@text/offline.comm-error-unknown-host [\"" + (hostname == null ? "null" : hostname) + "\"]"); + } catch (IOException ioe) { + logger.debug( + "{} Couldn't establish network connection to host '{}' -> returning current sytem time instead. ({})", + getThing().getUID(), hostname, ioe.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "@text/offline.comm-error-connection [\"" + (hostname == null ? "null" : hostname) + "\"]"); + } + + return System.currentTimeMillis(); + } + + @Override + public void channelLinked(ChannelUID channelUID) { + refreshTimeDate(); + } +} diff --git a/bundles/org.openhab.binding.ntp/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.ntp/src/main/resources/ESH-INF/binding/binding.xml index 990db7d38302d..b21b695a9cd81 100644 --- a/bundles/org.openhab.binding.ntp/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.ntp/src/main/resources/ESH-INF/binding/binding.xml @@ -1,9 +1,10 @@ - - - - NTP Binding - The NTP Binding polls the configured timeserver and post the current date and time. - Marcel Verpaalen - - + + + + NTP Binding + The NTP Binding polls the configured timeserver and post the current date and time. + Marcel Verpaalen + + diff --git a/bundles/org.openhab.binding.ntp/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.ntp/src/main/resources/ESH-INF/thing/thing-types.xml index 7ab3b456380d7..737df4afc15f0 100644 --- a/bundles/org.openhab.binding.ntp/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.ntp/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,71 +1,70 @@ - - - - - - An NTP server that provides current date and time - - - - - - - network-address - - The NTP server hostname. - 0.pool.ntp.org - - - - - Interval that new time updates are posted to the event bus in seconds. - - 60 - - - - - Number of updates before querying the NTP server. - - 30 - - - - The port that the NTP server could use. - 123 - - - - The configured timezone. - - - - The configured locale. - - - - - DateTime - - NTP refreshed date & time - Date - - - - String - - NTP refreshed date & time - Date - - - - - Formattting of the date & time. - yyyy-MM-dd HH:mm:ss z - - - - + + + + + + An NTP server that provides current date and time + + + + + + + network-address + + The NTP server hostname. + 0.pool.ntp.org + + + + + Interval that new time updates are posted to the event bus in seconds. + + 60 + + + + + Number of updates before querying the NTP server. + + 30 + + + + The port that the NTP server could use. + 123 + + + + The configured timezone. + + + + The configured locale. + + + + + DateTime + + NTP refreshed date & time + Date + + + + String + + NTP refreshed date & time + Date + + + + + Formattting of the date & time. + yyyy-MM-dd HH:mm:ss z + + + + diff --git a/bundles/org.openhab.binding.nuki/pom.xml b/bundles/org.openhab.binding.nuki/pom.xml index 177981db2ae41..9fa0d7369ae80 100644 --- a/bundles/org.openhab.binding.nuki/pom.xml +++ b/bundles/org.openhab.binding.nuki/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.nuki diff --git a/bundles/org.openhab.binding.nuki/src/main/feature/feature.xml b/bundles/org.openhab.binding.nuki/src/main/feature/feature.xml index a62823a42c65f..0d3ab61bc9f85 100644 --- a/bundles/org.openhab.binding.nuki/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.nuki/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - mvn:org.openhab.addons.bundles/org.openhab.binding.nuki/${project.version} - + + openhab-runtime-base + openhab-transport-http + mvn:org.openhab.addons.bundles/org.openhab.binding.nuki/${project.version} + diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/NukiBindingConstants.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/NukiBindingConstants.java index 4ce675eca5e92..df94bbb2b84f1 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/NukiBindingConstants.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/NukiBindingConstants.java @@ -86,5 +86,4 @@ public class NukiBindingConstants { // Nuki Binding additional Lock States public static final int LOCK_STATES_UNLOCKING_LOCKNGO = 1002; public static final int LOCK_STATES_UNLATCHING_LOCKNGO = 1007; - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/NukiHandlerFactory.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/NukiHandlerFactory.java index 204f3e27401cb..baf5acdbba440 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/NukiHandlerFactory.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/NukiHandlerFactory.java @@ -139,5 +139,4 @@ private String createCallbackUrl() { logger.trace("callbackUrl[{}]", callbackUrl); return callbackUrl; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/converter/LockActionConverter.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/converter/LockActionConverter.java index 4c9e31849676a..5e6093cd3fcd0 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/converter/LockActionConverter.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/converter/LockActionConverter.java @@ -55,5 +55,4 @@ public static int getLockStateFor(int lockAction) { } return 0; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackAddResponse.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackAddResponse.java index 02b22b841d3bd..773b57aa06c07 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackAddResponse.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackAddResponse.java @@ -34,5 +34,4 @@ public BridgeCallbackAddResponse(int status, String message, BridgeApiCallbackAd public BridgeCallbackAddResponse(NukiBaseResponse nukiBaseResponse) { super(nukiBaseResponse.getStatus(), nukiBaseResponse.getMessage()); } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackListResponse.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackListResponse.java index 61abedf070611..fa46e3f34351f 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackListResponse.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackListResponse.java @@ -45,5 +45,4 @@ public List getCallbacks() { public void setCallbacks(List callbacks) { this.callbacks = callbacks; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackRemoveResponse.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackRemoveResponse.java index a6cd8b26483e4..871ec43b945a5 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackRemoveResponse.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeCallbackRemoveResponse.java @@ -35,5 +35,4 @@ public BridgeCallbackRemoveResponse(int status, String message, public BridgeCallbackRemoveResponse(NukiBaseResponse nukiBaseResponse) { super(nukiBaseResponse.getStatus(), nukiBaseResponse.getMessage()); } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeInfoResponse.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeInfoResponse.java index aff974e7a26fa..24b10e7aa4800 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeInfoResponse.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeInfoResponse.java @@ -124,5 +124,4 @@ public List getScanResults() { public void setScanResults(List scanResults) { this.scanResults = scanResults; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeLockActionResponse.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeLockActionResponse.java index 56842afc40f51..b728ad9238719 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeLockActionResponse.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeLockActionResponse.java @@ -42,5 +42,4 @@ public boolean isBatteryCritical() { public void setBatteryCritical(boolean batteryCritical) { this.batteryCritical = batteryCritical; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeLockStateResponse.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeLockStateResponse.java index 922e5dfa31ba7..0c8ef5aa1152b 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeLockStateResponse.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/BridgeLockStateResponse.java @@ -62,5 +62,4 @@ public boolean isBatteryCritical() { public void setBatteryCritical(boolean batteryCritical) { this.batteryCritical = batteryCritical; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/NukiApiServlet.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/NukiApiServlet.java index 246e30998596a..b42e59b60ad96 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/NukiApiServlet.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/NukiApiServlet.java @@ -210,5 +210,4 @@ private void setHeaders(HttpServletResponse response) { response.setCharacterEncoding(CHARSET); response.setContentType(APPLICATION_JSON); } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/NukiHttpClient.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/NukiHttpClient.java index f84c332d1a1cf..04018826c3794 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/NukiHttpClient.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dataexchange/NukiHttpClient.java @@ -261,5 +261,4 @@ public BridgeCallbackRemoveResponse getBridgeCallbackRemove(int id) { return new BridgeCallbackRemoveResponse(handleException(e)); } } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackAddDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackAddDto.java index d6e15683f19a1..a556a951300d8 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackAddDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackAddDto.java @@ -38,5 +38,4 @@ public String getMessage() { public void setMessage(String message) { this.message = message; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackListCallbackDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackListCallbackDto.java index 72c808841cca5..08a76437ad5b1 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackListCallbackDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackListCallbackDto.java @@ -38,5 +38,4 @@ public String getUrl() { public void setUrl(String url) { this.url = url; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackListDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackListDto.java index 8b9fbd4685e5f..c19ea2759e93f 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackListDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackListDto.java @@ -31,5 +31,4 @@ public List getCallbacks() { public void setCallbacks(List callbacks) { this.callbacks = callbacks; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackRemoveDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackRemoveDto.java index e7367b63a051f..26e49d3497ff9 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackRemoveDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiCallbackRemoveDto.java @@ -38,5 +38,4 @@ public String getMessage() { public void setMessage(String message) { this.message = message; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoDto.java index 592397622124b..861ba25b465c0 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoDto.java @@ -84,5 +84,4 @@ public List getScanResults() { public void setScanResults(List scanResults) { this.scanResults = scanResults; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoIdDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoIdDto.java index 219e18c58267a..274f67c745139 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoIdDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoIdDto.java @@ -38,5 +38,4 @@ public int getServerId() { public void setServerId(int serverId) { this.serverId = serverId; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoScanResultDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoScanResultDto.java index af493d17d8bfd..ff9f30a67b4ad 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoScanResultDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoScanResultDto.java @@ -57,5 +57,4 @@ public boolean isPaired() { public void setPaired(boolean paired) { this.paired = paired; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoVersionDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoVersionDto.java index 43343ba1004f1..372c391c6384e 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoVersionDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiInfoVersionDto.java @@ -39,5 +39,4 @@ public String getWifiFirmwareVersion() { public void setWifiFirmwareVersion(String wifiFirmwareVersion) { this.wifiFirmwareVersion = wifiFirmwareVersion; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockActionDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockActionDto.java index 93de49d2d6839..36cd1b352fb6f 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockActionDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockActionDto.java @@ -38,5 +38,4 @@ public boolean isBatteryCritical() { public void setBatteryCritical(boolean batteryCritical) { this.batteryCritical = batteryCritical; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockStateDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockStateDto.java index 4e278f49d6d17..7bc4865516fc9 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockStateDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockStateDto.java @@ -56,5 +56,4 @@ public boolean isSuccess() { public void setSuccess(boolean success) { this.success = success; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockStateRequestDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockStateRequestDto.java index faa3367e066c9..cbf7cd5b72466 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockStateRequestDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/BridgeApiLockStateRequestDto.java @@ -56,5 +56,4 @@ public boolean isBatteryCritical() { public void setBatteryCritical(boolean batteryCritical) { this.batteryCritical = batteryCritical; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/NukiHttpServerStatusResponseDto.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/NukiHttpServerStatusResponseDto.java index 640dd892f5d93..5a62b09641508 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/NukiHttpServerStatusResponseDto.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/dto/NukiHttpServerStatusResponseDto.java @@ -35,5 +35,4 @@ public String getStatus() { public void setStatus(String status) { this.status = status; } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/handler/NukiBridgeHandler.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/handler/NukiBridgeHandler.java index 644261fe8e381..b583eb6d10260 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/handler/NukiBridgeHandler.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/handler/NukiBridgeHandler.java @@ -191,5 +191,4 @@ private void manageNukiBridgeCallbacks() { } } } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/handler/NukiSmartLockHandler.java b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/handler/NukiSmartLockHandler.java index bf00780751ff6..d8f5e39704295 100644 --- a/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/handler/NukiSmartLockHandler.java +++ b/bundles/org.openhab.binding.nuki/src/main/java/org/openhab/binding/nuki/internal/handler/NukiSmartLockHandler.java @@ -275,5 +275,4 @@ public void handleApiServletUpdate(ChannelUID channelUID, State newState) { logger.trace("handleApiServletUpdate({}, {})", channelUID, newState); updateState(channelUID, newState); } - } diff --git a/bundles/org.openhab.binding.nuki/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.nuki/src/main/resources/ESH-INF/binding/binding.xml index ba8c20b5a1a37..c5d51821f7871 100644 --- a/bundles/org.openhab.binding.nuki/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.nuki/src/main/resources/ESH-INF/binding/binding.xml @@ -1,11 +1,11 @@ - + Nuki Binding - The Nuki Binding allows simple and fast integration of Nuki Smart Locks into OpenHAB. This binding needs the Nuki Smart Lock(s) to be paired via Bluetooth with a Nuki Bridge to function correctly. + The Nuki Binding allows simple and fast integration of Nuki Smart Locks into OpenHAB. This binding needs + the Nuki Smart Lock(s) to be paired via Bluetooth with a Nuki Bridge to function correctly. Markus Katter diff --git a/bundles/org.openhab.binding.nuki/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.nuki/src/main/resources/ESH-INF/thing/thing-types.xml index 232859ee74283..e26905d90093b 100644 --- a/bundles/org.openhab.binding.nuki/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.nuki/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,28 +1,32 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - This bridge represents a Nuki Bridge on your local network. Nuki Smart Locks have to be paired via Bluetooth with it. + This bridge represents a Nuki Bridge on your local network. Nuki Smart Locks have to be paired via + Bluetooth with it. network-address - The IP address of the Nuki Bridge. Look it up on your router. It is recommended to set a static IP address lease for the Nuki Bridge (and for your openHAB server too) on your router. + The IP address of the Nuki Bridge. Look it up on your router. It is recommended to set a static IP + address lease for the Nuki Bridge (and for your openHAB server too) on your router. - The Port which you configured during Initial Bridge setup (https://nuki.io/en/support/bridge/bridge-setup/initial-bridge-setup/). + The Port which you configured during Initial Bridge setup + (https://nuki.io/en/support/bridge/bridge-setup/initial-bridge-setup/). 8080 password - The API Token which you configured during Initial Bridge setup (https://nuki.io/en/support/bridge/bridge-setup/initial-bridge-setup/). + The API Token which you configured during Initial Bridge setup + (https://nuki.io/en/support/bridge/bridge-setup/initial-bridge-setup/). @@ -35,23 +39,25 @@ - + Nuki Smart Lock which is paired via Bluetooth to a Nuki Bridge. - - - + + + - The 8-digit hexadecimal string that identifies the Nuki Smart Lock. Look it up on the sticker on the back of the Nuki Smart Lock (remove mounting plate). + The 8-digit hexadecimal string that identifies the Nuki Smart Lock. Look it up on the sticker on the + back of the Nuki Smart Lock (remove mounting plate). - If switched to On (or set to true) the Nuki Smart Lock will unlock the door but then also automatically pull the latch of the door lock. Usually, if the door hinges are correctly adjusted, the door will then swing open. + If switched to On (or set to true) the Nuki Smart Lock will unlock the door but then also automatically + pull the latch of the door lock. Usually, if the door hinges are correctly adjusted, the door will then swing open. false @@ -61,7 +67,8 @@ Switch - Use this channel with a Switch Item to unlock and lock the door. Configure "Unlatch" to true if your Nuki Smart Lock is mounted on a door lock with a knob on the outside. + Use this channel with a Switch Item to unlock and lock the door. Configure "Unlatch" to true if your Nuki + Smart Lock is mounted on a door lock with a knob on the outside. Door @@ -74,7 +81,8 @@ Number - Use this channel if you want to execute other supported lock actions or to display the current lock state. + Use this channel if you want to execute other supported lock actions or to display the current lock + state. Door diff --git a/bundles/org.openhab.binding.oceanic/pom.xml b/bundles/org.openhab.binding.oceanic/pom.xml index 7d5a345137336..aa4155bd92205 100644 --- a/bundles/org.openhab.binding.oceanic/pom.xml +++ b/bundles/org.openhab.binding.oceanic/pom.xml @@ -1,15 +1,21 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.oceanic openHAB Add-ons :: Bundles :: Oceanic Binding + + gnu.io;version="[3.12,6)" + + diff --git a/bundles/org.openhab.binding.oceanic/src/main/feature/feature.xml b/bundles/org.openhab.binding.oceanic/src/main/feature/feature.xml index a67bfb5216eb6..4e51c25d6e34b 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.oceanic/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.oceanic/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.oceanic/${project.version} + diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/NetworkOceanicBindingConfiguration.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/NetworkOceanicBindingConfiguration.java index 0e17bfe95b0fd..be0347ef7bc8a 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/NetworkOceanicBindingConfiguration.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/NetworkOceanicBindingConfiguration.java @@ -20,5 +20,4 @@ public class NetworkOceanicBindingConfiguration { public String ipAddress; public Integer portNumber; public Integer interval; - } diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicBindingConstants.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicBindingConstants.java index 3289652380b1f..4922b4d0c6c3a 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicBindingConstants.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/OceanicBindingConstants.java @@ -291,7 +291,6 @@ public static ValueSelectorType getValueSelectorType(String valueSelectorText) t } throw new IllegalArgumentException("Not valid value selector"); - } public String convertValue(String value) { @@ -302,7 +301,5 @@ public enum ValueSelectorType { GET, SET } - } - } diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/SerialOceanicBindingConfiguration.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/SerialOceanicBindingConfiguration.java index 64a0b2bd04291..7b76bd36641a3 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/SerialOceanicBindingConfiguration.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/SerialOceanicBindingConfiguration.java @@ -19,5 +19,4 @@ public class SerialOceanicBindingConfiguration { public String port; public Integer interval; - } diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java index 2d1a3a3a15266..3ae12b956de41 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/NetworkOceanicThingHandler.java @@ -21,7 +21,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; @@ -83,8 +82,6 @@ public void initialize() { public void dispose() { NetworkOceanicBindingConfiguration config = getConfigAs(NetworkOceanicBindingConfiguration.class); - IOUtils.closeQuietly(inputStream); - IOUtils.closeQuietly(outputStream); if (socket != null) { try { socket.close(); @@ -93,6 +90,8 @@ public void dispose() { config.portNumber, e.getMessage()); } finally { socket = null; + outputStream = null; + inputStream = null; } } diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/OceanicThingHandler.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/OceanicThingHandler.java index 382fc3aee0ce5..d897b0d5d3919 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/OceanicThingHandler.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/OceanicThingHandler.java @@ -166,5 +166,4 @@ private State createStateForType(OceanicChannelSelector selector, String value) } protected abstract String requestResponse(String commandAsString); - } diff --git a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java index 550ffa6e4fa51..9945c8a05a612 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java +++ b/bundles/org.openhab.binding.oceanic/src/main/java/org/openhab/binding/oceanic/internal/handler/SerialOceanicThingHandler.java @@ -19,7 +19,6 @@ import java.util.Arrays; import java.util.Enumeration; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; @@ -149,12 +148,29 @@ public void dispose() { } } - IOUtils.closeQuietly(inputStream); - IOUtils.closeQuietly(outputStream); + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + logger.debug("Error while closing the input stream: {}", e.getMessage()); + } + } + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + logger.debug("Error while closing the output stream: {}", e.getMessage()); + } + } if (serialPort != null) { serialPort.close(); } + readerThread = null; + inputStream = null; + outputStream = null; + serialPort = null; + super.dispose(); } @@ -224,7 +240,6 @@ public void interrupt() { logger.trace("Interrupting the SerialPortReader"); interrupted = true; super.interrupt(); - IOUtils.closeQuietly(inputStream); } @Override diff --git a/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/binding/binding.xml index fce26fd72a228..5872ea89007c8 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - openHAB Oceanic Binding diff --git a/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/channel-types.xml index 192077b1343b0..b64d32099fe6f 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/channel-types.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/network.xml b/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/network.xml index 7e7603bab94a2..9fc10fc31e81a 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/network.xml +++ b/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/network.xml @@ -1,5 +1,6 @@ - @@ -8,46 +9,46 @@ Oceanic Water Softener connected through a network proxy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/serial.xml b/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/serial.xml index 70fb0e2ea4ec4..4d9e5bbc031c8 100644 --- a/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/serial.xml +++ b/bundles/org.openhab.binding.oceanic/src/main/resources/ESH-INF/thing/serial.xml @@ -1,5 +1,6 @@ - @@ -8,52 +9,53 @@ Oceanic Water Softener connected through a serial port - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + serial-port + false Serial Port the Oceanic Water Softener is connected to diff --git a/bundles/org.openhab.binding.omnikinverter/pom.xml b/bundles/org.openhab.binding.omnikinverter/pom.xml index e5c1017ddd4d2..ffb66c989e7f7 100644 --- a/bundles/org.openhab.binding.omnikinverter/pom.xml +++ b/bundles/org.openhab.binding.omnikinverter/pom.xml @@ -1,10 +1,12 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.omnikinverter diff --git a/bundles/org.openhab.binding.omnikinverter/src/main/feature/feature.xml b/bundles/org.openhab.binding.omnikinverter/src/main/feature/feature.xml index 0a7f08569c43b..eea18accccff0 100644 --- a/bundles/org.openhab.binding.omnikinverter/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.omnikinverter/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.omnikinverter/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.omnikinverter/${project.version} + diff --git a/bundles/org.openhab.binding.omnikinverter/src/main/java/org/openhab/binding/omnikinverter/internal/OmnikInverterBindingConstants.java b/bundles/org.openhab.binding.omnikinverter/src/main/java/org/openhab/binding/omnikinverter/internal/OmnikInverterBindingConstants.java index e84a73105a7d5..62c19e65f498a 100644 --- a/bundles/org.openhab.binding.omnikinverter/src/main/java/org/openhab/binding/omnikinverter/internal/OmnikInverterBindingConstants.java +++ b/bundles/org.openhab.binding.omnikinverter/src/main/java/org/openhab/binding/omnikinverter/internal/OmnikInverterBindingConstants.java @@ -35,5 +35,4 @@ public class OmnikInverterBindingConstants { public static final String CHANNEL_ENERGY_TODAY = "energyToday"; public static final String CHANNEL_ENERGY_TOTAL = "energyTotal"; - } diff --git a/bundles/org.openhab.binding.omnikinverter/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.omnikinverter/src/main/resources/ESH-INF/binding/binding.xml index 0ea7ca89e8ecd..420df3f3d7b42 100644 --- a/bundles/org.openhab.binding.omnikinverter/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.omnikinverter/src/main/resources/ESH-INF/binding/binding.xml @@ -4,6 +4,8 @@ xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd"> OmnikInverter Binding - This is the binding for the Omnik solar grid inverters. The integration is based on the undocumented API, which is reverse engineered at https://github.com/Woutrrr/Omnik-Data-Logger. As such, the known supported inverters are known to work with inverters with wifi bridge which start with the serial number '602' and '606'. + This is the binding for the Omnik solar grid inverters. The integration is based on the undocumented API, + which is reverse engineered at https://github.com/Woutrrr/Omnik-Data-Logger. As such, the known supported inverters + are known to work with inverters with wifi bridge which start with the serial number '602' and '606'. Hans van den Bogert diff --git a/bundles/org.openhab.binding.omnikinverter/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.omnikinverter/src/main/resources/ESH-INF/thing/thing-types.xml index 03f325fcab8ad..12ec7a4de08bf 100644 --- a/bundles/org.openhab.binding.omnikinverter/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.omnikinverter/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,9 +9,9 @@ Thing for OmnikInverter Binding - - - + + + @@ -37,19 +37,19 @@ Number:Power The instantaneous power generation - + Number:Energy The amount of energy generated today - + Number:Energy The amount of generated energy in total - + diff --git a/bundles/org.openhab.binding.omnikinverter/src/test/java/org/openhab/binding/omnikinverter/internal/test/OmnikInverterMessageTest.java b/bundles/org.openhab.binding.omnikinverter/src/test/java/org/openhab/binding/omnikinverter/internal/test/OmnikInverterMessageTest.java index 4e0a58d06c5d9..7adc85ae7c6b0 100644 --- a/bundles/org.openhab.binding.omnikinverter/src/test/java/org/openhab/binding/omnikinverter/internal/test/OmnikInverterMessageTest.java +++ b/bundles/org.openhab.binding.omnikinverter/src/test/java/org/openhab/binding/omnikinverter/internal/test/OmnikInverterMessageTest.java @@ -49,5 +49,4 @@ public void testGetTotalEnergy() { public void testGetEnergyToday() { assertEquals(11.13, message.getEnergyToday(), 0.01); } - } diff --git a/bundles/org.openhab.binding.onebusaway/pom.xml b/bundles/org.openhab.binding.onebusaway/pom.xml index 26c988352b0f9..84ca3e58a50a5 100644 --- a/bundles/org.openhab.binding.onebusaway/pom.xml +++ b/bundles/org.openhab.binding.onebusaway/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.onebusaway diff --git a/bundles/org.openhab.binding.onebusaway/src/main/feature/feature.xml b/bundles/org.openhab.binding.onebusaway/src/main/feature/feature.xml index 42e41222c7d22..86770fda6e989 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.onebusaway/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.onebusaway/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.onebusaway/${project.version} + diff --git a/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/config/ApiConfiguration.java b/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/config/ApiConfiguration.java index 8022ce31ad028..0500ea4f4dd66 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/config/ApiConfiguration.java +++ b/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/config/ApiConfiguration.java @@ -58,5 +58,4 @@ public String toString() { return new ToStringBuilder(this).append(API_CONFIG_API_KEY, this.getApiKey()) .append(API_CONFIG_API_SERVER, this.getApiServer()).toString(); } - } diff --git a/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/handler/ApiHandler.java b/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/handler/ApiHandler.java index 63ba83acec92d..1a58e7ede6a44 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/handler/ApiHandler.java +++ b/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/handler/ApiHandler.java @@ -77,5 +77,4 @@ private ApiConfiguration loadAndCheckConfiguration() { } return config; } - } diff --git a/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/handler/ObaStopArrivalResponse.java b/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/handler/ObaStopArrivalResponse.java index dc7398935b844..5ecafa432a4d3 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/handler/ObaStopArrivalResponse.java +++ b/bundles/org.openhab.binding.onebusaway/src/main/java/org/openhab/binding/onebusaway/internal/handler/ObaStopArrivalResponse.java @@ -55,6 +55,5 @@ public int compareTo(ArrivalAndDeparture other) { return (int) ((predicted ? predictedArrivalTime : scheduledArrivalTime) - (other.predicted ? other.predictedArrivalTime : other.scheduledArrivalTime)); } - } } diff --git a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/binding/binding.xml index 23d2a3c5758fa..aaa35b41608d9 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + OneBusAway Binding This is the binding for OneBusAway, an open system to provide transit data. diff --git a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/config/config.xml index 6b8fe996151c5..677fc75508ee1 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/api.xml b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/api.xml index 068e75334f6d0..dc5e413bf3d3d 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/api.xml +++ b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/api.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> diff --git a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/channels.xml index 2771503a5ab3f..7dbe3c75849e3 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/channels.xml @@ -1,23 +1,23 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> DateTime The arrival time - - + + DateTime The departure time - - + + @@ -30,13 +30,13 @@ - + DateTime The last time information was updated - + diff --git a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/route.xml b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/route.xml index d0f4fc90ea694..37b31fe4c1c87 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/route.xml +++ b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/route.xml @@ -1,21 +1,21 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + Provides data about a route at a specific stop. - - - - + + + + diff --git a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/stop.xml b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/stop.xml index 8a9508da4ab67..fbdf3fb4887bf 100644 --- a/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/stop.xml +++ b/bundles/org.openhab.binding.onebusaway/src/main/resources/ESH-INF/thing/stop.xml @@ -1,12 +1,12 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + Provides data about different routes at a specific stop. diff --git a/bundles/org.openhab.binding.onewire/pom.xml b/bundles/org.openhab.binding.onewire/pom.xml index 028b87c13e355..e8190cd88296c 100644 --- a/bundles/org.openhab.binding.onewire/pom.xml +++ b/bundles/org.openhab.binding.onewire/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.onewire diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/OwPageBuffer.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/OwPageBuffer.java index 7bec7ae0e8899..2e1c919955a6c 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/OwPageBuffer.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/OwPageBuffer.java @@ -144,5 +144,4 @@ public String toString() { s.append(new String("]")); return s.toString(); } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/AbstractDigitalOwDevice.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/AbstractDigitalOwDevice.java index 97c2dccf7ed25..3cf7c35727ae0 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/AbstractDigitalOwDevice.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/AbstractDigitalOwDevice.java @@ -103,8 +103,12 @@ public void configureChannels() throws OwException { isConfigured = true; } + /** + * refreshes this sensor - note that the update interval check is not performed as its and i/o device + */ @Override public void refresh(OwserverBridgeHandler bridgeHandler, Boolean forcedRefresh) throws OwException { + logger.trace("refresh of sensor {} started", sensorId); if (isConfigured) { State state; @@ -151,5 +155,4 @@ public boolean writeChannel(OwserverBridgeHandler bridgeHandler, Integer ioChann throw new IllegalArgumentException("channel number out of range"); } } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/AbstractOwDevice.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/AbstractOwDevice.java index b9f31b6244957..a846b455433db 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/AbstractOwDevice.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/AbstractOwDevice.java @@ -137,5 +137,4 @@ public OwSensorType getSensorType(OwserverBridgeHandler bridgeHandler) throws Ow } return sensorType; } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/BAE0910.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/BAE0910.java index 4be4855c39d51..80351a82cd17f 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/BAE0910.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/BAE0910.java @@ -213,6 +213,7 @@ public void configureChannels(OwserverBridgeHandler bridgeHandler) throws OwExce @Override public void refresh(OwserverBridgeHandler bridgeHandler, Boolean forcedRefresh) throws OwException { if (isConfigured) { + logger.trace("refresh of sensor {} started", sensorId); // Counter if (enabledChannels.contains(CHANNEL_COUNTER)) { State counterValue = bridgeHandler.readDecimalType(sensorId, pin1CounterParameter); diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS18x20.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS18x20.java index 2f0d5db532ddc..7164bf7b4be83 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS18x20.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS18x20.java @@ -76,6 +76,7 @@ public void configureChannels() throws OwException { @Override public void refresh(OwserverBridgeHandler bridgeHandler, Boolean forcedRefresh) throws OwException { if (isConfigured && enabledChannels.contains(CHANNEL_TEMPERATURE)) { + logger.trace("refresh of sensor {} started", sensorId); QuantityType temperature = new QuantityType<>( (DecimalType) bridgeHandler.readDecimalType(sensorId, temperatureParameter), SIUnits.CELSIUS); logger.trace("read temperature {} from {}", temperature, sensorId); diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS1923.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS1923.java index e979216eb80f7..eeab671d19436 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS1923.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS1923.java @@ -28,6 +28,8 @@ import org.openhab.binding.onewire.internal.handler.OwBaseThingHandler; import org.openhab.binding.onewire.internal.handler.OwserverBridgeHandler; import org.openhab.binding.onewire.internal.owserver.OwserverDeviceParameter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The {@link DS1923} class defines an DS1923 device @@ -37,6 +39,7 @@ */ @NonNullByDefault public class DS1923 extends AbstractOwDevice { + private final Logger logger = LoggerFactory.getLogger(DS1923.class); private final OwserverDeviceParameter temperatureParameter = new OwserverDeviceParameter("/temperature"); private final OwserverDeviceParameter humidityParameter = new OwserverDeviceParameter("/humidity"); @@ -52,6 +55,7 @@ public void configureChannels() throws OwException { @Override public void refresh(OwserverBridgeHandler bridgeHandler, Boolean forcedRefresh) throws OwException { if (isConfigured) { + logger.trace("refresh of sensor {} started", sensorId); if (enabledChannels.contains(CHANNEL_TEMPERATURE) || enabledChannels.contains(CHANNEL_HUMIDITY) || enabledChannels.contains(CHANNEL_ABSOLUTE_HUMIDITY) || enabledChannels.contains(CHANNEL_DEWPOINT)) { diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2405.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2405.java index 20e376e92ac47..4e9b1378471ef 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2405.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2405.java @@ -42,5 +42,4 @@ public void configureChannels() throws OwException { super.configureChannels(); } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2406_DS2413.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2406_DS2413.java index ea818ddb3d0ab..9eeda453455ac 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2406_DS2413.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2406_DS2413.java @@ -33,15 +33,14 @@ public DS2406_DS2413(SensorId sensorId, OwBaseThingHandler callback) { @Override public void configureChannels() throws OwException { ioConfig.clear(); - ioConfig.add(new DigitalIoConfig(callback.getThing(), 0, new OwserverDeviceParameter("/sensed.A"), + ioConfig.add(new DigitalIoConfig(callback.getThing(), 0, new OwserverDeviceParameter("uncached/", "/sensed.A"), new OwserverDeviceParameter("/PIO.A"))); - ioConfig.add(new DigitalIoConfig(callback.getThing(), 1, new OwserverDeviceParameter("/sensed.B"), + ioConfig.add(new DigitalIoConfig(callback.getThing(), 1, new OwserverDeviceParameter("uncached/", "/sensed.B"), new OwserverDeviceParameter("/PIO.B"))); - fullInParam = new OwserverDeviceParameter("/sensed.BYTE"); + fullInParam = new OwserverDeviceParameter("uncached/", "/sensed.BYTE"); fullOutParam = new OwserverDeviceParameter("/PIO.BYTE"); super.configureChannels(); } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2423.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2423.java index cf38eb77dafbf..badc2492f91db 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2423.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2423.java @@ -23,6 +23,8 @@ import org.openhab.binding.onewire.internal.handler.OwBaseThingHandler; import org.openhab.binding.onewire.internal.handler.OwserverBridgeHandler; import org.openhab.binding.onewire.internal.owserver.OwserverDeviceParameter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The {@link DS2423} class defines an DS2423 device @@ -31,6 +33,7 @@ */ @NonNullByDefault public class DS2423 extends AbstractOwDevice { + private final Logger logger = LoggerFactory.getLogger(DS2423.class); private final OwserverDeviceParameter counterParameter = new OwserverDeviceParameter("/counters.ALL"); public DS2423(SensorId sensorId, OwBaseThingHandler callback) { @@ -45,6 +48,7 @@ public void configureChannels() throws OwException { @Override public void refresh(OwserverBridgeHandler bridgeHandler, Boolean forcedRefresh) throws OwException { if (isConfigured) { + logger.trace("refresh of sensor {} started", sensorId); List states = bridgeHandler.readDecimalTypeArray(sensorId, counterParameter); if (states.size() != 2) { diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2438.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2438.java index dde9bed80f789..388773968db3c 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2438.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/DS2438.java @@ -90,6 +90,7 @@ public void configureChannels() { @Override public void refresh(OwserverBridgeHandler bridgeHandler, Boolean forcedRefresh) throws OwException { if (isConfigured) { + logger.trace("refresh of sensor {} started", sensorId); double Vcc = 5.0; if (enabledChannels.contains(CHANNEL_TEMPERATURE) || enabledChannels.contains(CHANNEL_HUMIDITY) @@ -218,5 +219,4 @@ public void setLightSensorType(LightSensorType lightSensorType) { public void setCurrentSensorType(CurrentSensorType currentSensorType) { this.currentSensorType = currentSensorType; } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/EDS006x.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/EDS006x.java index da41e606d03aa..25106e15f3c41 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/EDS006x.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/device/EDS006x.java @@ -31,6 +31,8 @@ import org.openhab.binding.onewire.internal.handler.OwBaseThingHandler; import org.openhab.binding.onewire.internal.handler.OwserverBridgeHandler; import org.openhab.binding.onewire.internal.owserver.OwserverDeviceParameter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * The {@link EDS006x} class defines an EDS006x device @@ -39,6 +41,7 @@ */ @NonNullByDefault public class EDS006x extends AbstractOwDevice { + private final Logger logger = LoggerFactory.getLogger(EDS006x.class); private OwserverDeviceParameter temperatureParameter = new OwserverDeviceParameter("/temperature"); private OwserverDeviceParameter humidityParameter = new OwserverDeviceParameter("/humidity"); private OwserverDeviceParameter pressureParameter = new OwserverDeviceParameter("/pressure"); @@ -62,6 +65,7 @@ public void configureChannels() { @Override public void refresh(OwserverBridgeHandler bridgeHandler, Boolean forcedRefresh) throws OwException { if (isConfigured) { + logger.trace("refresh of sensor {} started", sensorId); if (enabledChannels.contains(CHANNEL_TEMPERATURE) || enabledChannels.contains(CHANNEL_HUMIDITY) || enabledChannels.contains(CHANNEL_ABSOLUTE_HUMIDITY) || enabledChannels.contains(CHANNEL_DEWPOINT)) { diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/discovery/OwDiscoveryService.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/discovery/OwDiscoveryService.java index a5520eb8f9e26..a49f9530b97f2 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/discovery/OwDiscoveryService.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/discovery/OwDiscoveryService.java @@ -137,5 +137,4 @@ protected synchronized void stopScan() { public void deactivate() { removeOlderResults(new Date().getTime()); } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/handler/BasicMultisensorThingHandler.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/handler/BasicMultisensorThingHandler.java index ef9f82f8096f8..4de533f4c18a0 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/handler/BasicMultisensorThingHandler.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/handler/BasicMultisensorThingHandler.java @@ -117,5 +117,4 @@ public void updateSensorProperties(OwserverBridgeHandler bridgeHandler) throws O updateProperties(properties); } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/handler/OwserverBridgeHandler.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/handler/OwserverBridgeHandler.java index 594b4aaea44f5..33b53e68dfd6c 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/handler/OwserverBridgeHandler.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/handler/OwserverBridgeHandler.java @@ -15,7 +15,13 @@ import static org.openhab.binding.onewire.internal.OwBindingConstants.*; import java.math.BigDecimal; -import java.util.*; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Queue; +import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -25,7 +31,13 @@ import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.*; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.State; @@ -106,7 +118,9 @@ public void initialize() { updateStatus(ThingStatus.UNKNOWN); scheduler.execute(() -> { - owserverConnection.start(); + synchronized (owserverConnection) { + owserverConnection.start(); + } }); if (refreshTask.isCancelled()) { @@ -119,56 +133,69 @@ public void initialize() { */ private void refresh() { try { - if (refreshable) { - long now = System.currentTimeMillis(); - - // refresh thing channels - List thingList = getThing().getThings(); - int thingCount = thingList.size(); - Iterator childListIterator = thingList.iterator(); - logger.trace("refreshTask starts at {}, {} childs", now, thingCount); - while (childListIterator.hasNext() && refreshable) { - Thing owThing = childListIterator.next(); - - logger.trace("refresh: getting handler for {} ({} to go)", owThing.getUID(), thingCount); - OwBaseThingHandler owHandler = (OwBaseThingHandler) owThing.getHandler(); - if (owHandler != null) { - if (owHandler.isRefreshable()) { - logger.trace("{} initialized, refreshing", owThing.getUID()); - owHandler.refresh(OwserverBridgeHandler.this, now); - } else { - logger.trace("{} not initialized, skipping refresh", owThing.getUID()); - } + long now = System.currentTimeMillis(); + if (!refreshable) { + logger.trace("refresh requested by thread ID {} denied, as not refresheable", + Thread.currentThread().getId()); + return; + } + + // refresh thing channels + List thingList = getThing().getThings(); + int thingCount = thingList.size(); + Iterator childListIterator = thingList.iterator(); + logger.trace("refreshTask with thread ID {} starts at {}, {} childs", Thread.currentThread().getId(), now, + thingCount); + while (childListIterator.hasNext() && refreshable) { + Thing owThing = childListIterator.next(); + + logger.trace("refresh: getting handler for {} ({} to go)", owThing.getUID(), thingCount); + OwBaseThingHandler owHandler = (OwBaseThingHandler) owThing.getHandler(); + if (owHandler != null) { + if (owHandler.isRefreshable()) { + logger.trace("{} initialized, refreshing", owThing.getUID()); + owHandler.refresh(OwserverBridgeHandler.this, now); } else { - logger.debug("{} handler missing", owThing.getUID()); + logger.trace("{} not initialized, skipping refresh", owThing.getUID()); } - thingCount--; + } else { + logger.debug("{} handler missing", owThing.getUID()); } + thingCount--; + } - refreshBridgeChannels(now); - - // update thing properties (only one per refresh cycle) - Thing updateThing = thingPropertiesUpdateQueue.poll(); - if (updateThing != null) { - logger.trace("update: getting handler for {} ({} total in list)", updateThing.getUID(), - thingPropertiesUpdateQueue.size()); - OwBaseThingHandler owHandler = (OwBaseThingHandler) updateThing.getHandler(); - if (owHandler != null) { - try { - owHandler.updateSensorProperties(this); - owHandler.initialize(); - logger.debug("{} sucessfully updated properties, removing from property update list", - updateThing.getUID()); - } catch (OwException e) { - thingPropertiesUpdateQueue.add(updateThing); - logger.debug("updating thing properties for {} failed: {}, adding to end of list", - updateThing.getUID(), e.getMessage()); - } - } else { - logger.debug("{} is missing handler, removing from property update list", updateThing.getUID()); + if (!refreshable) { + logger.trace("refresh aborted, as brige became non-refresheable."); + return; + } + refreshBridgeChannels(now); + + // update thing properties (only one per refresh cycle) + if (!refreshable) { + logger.trace("refresh aborted, as brige became non-refresheable."); + return; + } + Thing updateThing = thingPropertiesUpdateQueue.poll(); + if (updateThing != null) { + logger.trace("update: getting handler for {} ({} total in list)", updateThing.getUID(), + thingPropertiesUpdateQueue.size()); + OwBaseThingHandler owHandler = (OwBaseThingHandler) updateThing.getHandler(); + if (owHandler != null) { + try { + owHandler.updateSensorProperties(this); + owHandler.initialize(); + logger.debug("{} sucessfully updated properties, removing from property update list", + updateThing.getUID()); + } catch (OwException e) { + thingPropertiesUpdateQueue.add(updateThing); + logger.debug("updating thing properties for {} failed: {}, adding to end of list", + updateThing.getUID(), e.getMessage()); } + } else { + logger.debug("{} is missing handler, removing from property update list", updateThing.getUID()); } } + } catch (RuntimeException e) { // catching RuntimeException because scheduled tasks finish once an exception occurs logger.error("refresh encountered exception of {}: {}, please report bug", e.getClass(), e.getMessage()); @@ -342,12 +369,15 @@ public boolean isRefreshable() { * @param connectionState current connection state */ public void reportConnectionState(OwserverConnectionState connectionState) { + logger.debug("Updating owserverconnectionstate to {}", connectionState); switch (connectionState) { case FAILED: refreshable = false; updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); scheduler.schedule(() -> { - owserverConnection.start(); + synchronized (owserverConnection) { + owserverConnection.start(); + } }, RECONNECT_AFTER_FAIL_TIME, TimeUnit.MILLISECONDS); break; case STOPPED: diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverConnection.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverConnection.java index 4c0097abe18c0..13b82709638bc 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverConnection.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverConnection.java @@ -37,7 +37,19 @@ import org.slf4j.LoggerFactory; /** - * The {@link OwserverConnection} defines the protocol for connections to owservers + * The {@link OwserverConnection} defines the protocol for connections to owservers. + * + * Data is requested by using one of the read / write methods. In case of errors, an {@link OwException} + * is thrown. All other exceptions are caught and handled. + * + * The data request methods follow a general pattern: + * * build the appropriate {@link OwserverPacket} for the request + * * call {@link #request(OwserverPacket)} to ask for the data, which then + * * uses {@link #write(OwserverPacket)} to get the request to the server and + * * uses {@link #read(boolean)} to get the result + * + * Hereby, the resulting packet is examined on an appropriate return code (!= -1) and whether the + * expected payload is attached. If not, an {@link OwException} is thrown. * * @author Jan N. Klug - Initial contribution */ @@ -59,6 +71,7 @@ public class OwserverConnection { private @Nullable DataInputStream owserverInputStream = null; private @Nullable DataOutputStream owserverOutputStream = null; private OwserverConnectionState owserverConnectionState = OwserverConnectionState.STOPPED; + private boolean tryingConnectionRecovery = false; // reset to 0 after successful request private int connectionErrorCounter = 0; @@ -95,16 +108,21 @@ public void setPort(int port) { * start the owserver connection */ public void start() { + logger.debug("Trying to (re)start OW server connection - previous state: {}", + owserverConnectionState.toString()); connectionErrorCounter = 0; - owserverConnectionState = OwserverConnectionState.CLOSED; + tryingConnectionRecovery = true; boolean success = false; do { success = open(); - } while (!success && owserverConnectionState != OwserverConnectionState.FAILED); + if (success && owserverConnectionState != OwserverConnectionState.FAILED) { + tryingConnectionRecovery = false; + } + } while (!success && (owserverConnectionState != OwserverConnectionState.FAILED || tryingConnectionRecovery)); } /** - * stop the owserver connection + * stop the owserver connection and report new {@link OwserverConnectionState} to {@link #thingHandlerCallback}. */ public void stop() { close(); @@ -122,11 +140,10 @@ public void stop() { OwserverPacket returnPacket = request(requestPacket); if ((returnPacket.getReturnCode() != -1) && returnPacket.hasPayload()) { - connectionErrorCounter = 0; return Arrays.stream(returnPacket.getPayloadString().split(",")).map(this::stringToSensorId) .filter(Objects::nonNull).collect(Collectors.toList()); } else { - throw new OwException("invalid of empty packet"); + throw new OwException("invalid of empty packet when requesting directory"); } } @@ -141,11 +158,12 @@ public void stop() { /** * check sensor presence * + * Errors are caught and interpreted as sensor not present. + * * @param path full owfs path to sensor * @return OnOffType, ON=present, OFF=not present - * @throws OwException */ - public State checkPresence(String path) throws OwException { + public State checkPresence(String path) { State returnValue = OnOffType.OFF; try { OwserverPacket requestPacket; @@ -182,7 +200,7 @@ public State readDecimalType(String path) throws OwException { throw new OwException("could not parse '" + returnPacket.getPayloadString().trim() + "' to a number"); } } else { - throw new OwException("invalid or empty packet"); + throw new OwException("invalid or empty packet when requesting decimal type"); } return returnState; @@ -203,7 +221,7 @@ public List readDecimalTypeArray(String path) throws OwException { Arrays.stream(returnPacket.getPayloadString().split(",")) .forEach(v -> returnList.add(DecimalType.valueOf(v.trim()))); } else { - throw new OwException("invalid or empty packet"); + throw new OwException("invalid or empty packet when requesting decimal type array"); } return returnList; @@ -223,7 +241,7 @@ public String readString(String path) throws OwException { if ((returnPacket.getReturnCode() != -1) && returnPacket.hasPayload()) { return returnPacket.getPayloadString().trim(); } else { - throw new OwException("invalid or empty packet"); + throw new OwException("invalid or empty packet when requesting string type"); } } @@ -240,7 +258,7 @@ public OwPageBuffer readPages(String path) throws OwException { if ((returnPacket.getReturnCode() != -1) && returnPacket.hasPayload()) { return returnPacket.getPayload(); } else { - throw new OwException("invalid or empty packet"); + throw new OwException("invalid or empty packet when requesting pages"); } } @@ -255,6 +273,7 @@ public void writeDecimalType(String path, DecimalType value) throws OwException OwserverPacket requestPacket = new OwserverPacket(OwserverMessageType.WRITE, path); requestPacket.appendPayload(String.valueOf(value)); + // request method throws an OwException in case of issues... OwserverPacket returnPacket = request(requestPacket); logger.trace("wrote: {}, got: {} ", requestPacket, returnPacket); @@ -269,10 +288,15 @@ public void writeDecimalType(String path, DecimalType value) throws OwException */ private OwserverPacket request(OwserverPacket requestPacket) throws OwException { OwserverPacket returnPacket = new OwserverPacket(OwserverPacketType.RETURN); + // answer to value write is always empty boolean payloadExpected = requestPacket.getMessageType() != OwserverMessageType.WRITE; + try { + // write request - error may be thrown write(requestPacket); + + // try to read data as long as we don't get any feedback and no error is thrown... do { if (requestPacket.getMessageType() == OwserverMessageType.PRESENT || requestPacket.getMessageType() == OwserverMessageType.NOP) { @@ -281,6 +305,7 @@ private OwserverPacket request(OwserverPacket requestPacket) throws OwException returnPacket = read(false); } } while (returnPacket.isPingPacket() || !(returnPacket.hasPayload() == payloadExpected)); + } catch (OwException e) { logger.debug("failed requesting {}->{} [{}]", requestPacket, returnPacket, e.getMessage()); throw e; @@ -291,6 +316,7 @@ private OwserverPacket request(OwserverPacket requestPacket) throws OwException close(); } + // Success! Reset error counter. connectionErrorCounter = 0; return returnPacket; } @@ -298,11 +324,14 @@ private OwserverPacket request(OwserverPacket requestPacket) throws OwException /** * open/reopen the connection to the owserver * + * In case of issues, the connection is closed using {@link #closeOnError()} and false is returned. + * If the {@link #owserverConnectionState} is in STOPPED or FAILED, the method directly returns false. + * * @return true if open */ private boolean open() { try { - if (owserverConnectionState == OwserverConnectionState.CLOSED) { + if (owserverConnectionState == OwserverConnectionState.CLOSED || tryingConnectionRecovery) { // open socket & set timeout to 3000ms final Socket owserverSocket = new Socket(owserverAddress, owserverPort); owserverSocket.setSoTimeout(3000); @@ -314,7 +343,7 @@ private boolean open() { owserverConnectionState = OwserverConnectionState.OPENED; thingHandlerCallback.reportConnectionState(owserverConnectionState); - logger.debug("opened OwServerConnection to {}:{}", owserverAddress, owserverPort); + logger.debug("OW connection state: opened to {}:{}", owserverAddress, owserverPort); return true; } else if (owserverConnectionState == OwserverConnectionState.OPENED) { // socket already open, clear input buffer @@ -340,13 +369,24 @@ private boolean open() { } /** - * close the connection to the owserver instance + * close connection and report connection state to callback */ private void close() { + this.close(true); + } + + /** + * close the connection to the owserver instance. + * + * @param reportConnectionState true, if connection state shall be reported to callback + */ + private void close(boolean reportConnectionState) { final Socket owserverSocket = this.owserverSocket; if (owserverSocket != null) { try { owserverSocket.close(); + owserverConnectionState = OwserverConnectionState.CLOSED; + logger.debug("closed connection"); } catch (IOException e) { owserverConnectionState = OwserverConnectionState.FAILED; logger.warn("could not close connection: {}", e.getMessage()); @@ -357,10 +397,9 @@ private void close() { this.owserverInputStream = null; this.owserverOutputStream = null; - logger.debug("closed connection"); - owserverConnectionState = OwserverConnectionState.CLOSED; - - thingHandlerCallback.reportConnectionState(owserverConnectionState); + if (reportConnectionState) { + thingHandlerCallback.reportConnectionState(owserverConnectionState); + } } /** @@ -377,13 +416,20 @@ private void checkConnection() { } /** - * close the connection to the owserver instance after an error occured + * close the connection to the owserver instance after an error occured. + * if {@link #CONNECTION_MAX_RETRY} is exceeded, {@link #owserverConnectionState} is set to FAILED + * and state is reported to callback. */ private void closeOnError() { connectionErrorCounter++; - close(); + close(false); if (connectionErrorCounter > CONNECTION_MAX_RETRY) { + logger.debug("OW connection state: set to failed as max retries exceeded."); owserverConnectionState = OwserverConnectionState.FAILED; + tryingConnectionRecovery = false; + thingHandlerCallback.reportConnectionState(owserverConnectionState); + } else if (!tryingConnectionRecovery) { + // as close did not report connections state and we are not trying to recover ... thingHandlerCallback.reportConnectionState(owserverConnectionState); } } @@ -391,6 +437,9 @@ private void closeOnError() { /** * write to the owserver * + * In case of issues, the connection is closed using {@link #closeOnError()} and an + * {@link OwException} is thrown. + * * @param requestPacket data to write * @throws OwException */ @@ -405,8 +454,10 @@ private void write(OwserverPacket requestPacket) throws OwException { } else { logger.debug("output stream not available on write"); closeOnError(); + throw new OwException("I/O Error: output stream not available on write"); } } else { + // was not opened throw new OwException("I/O error: could not open connection to send request packet"); } } catch (IOException e) { @@ -419,38 +470,49 @@ private void write(OwserverPacket requestPacket) throws OwException { /** * read from owserver * + * In case of errors (which may also be due to an erroneous path), the connection is checked and potentially closed + * using {@link #checkConnection()}. + * + * @param noTimeoutException retry in case of read time outs instead of exiting with an {@link OwException}. * @return the read packet * @throws OwException */ private OwserverPacket read(boolean noTimeoutException) throws OwException { OwserverPacket returnPacket = new OwserverPacket(OwserverPacketType.RETURN); - try { - final DataInputStream owserverInputStream = this.owserverInputStream; - if (owserverInputStream != null) { - DataInputStream inputStream = owserverInputStream; + final DataInputStream owserverInputStream = this.owserverInputStream; + if (owserverInputStream != null) { + DataInputStream inputStream = owserverInputStream; + try { returnPacket = new OwserverPacket(inputStream, OwserverPacketType.RETURN); - logger.trace("read: {}", returnPacket); - } else { - logger.debug("input stream not available on read"); - closeOnError(); - } - } catch (EOFException e) { - // nothing to read - } catch (OwException e) { - checkConnection(); - throw e; - } catch (IOException e) { - if (e.getMessage().equals("Read timed out") && noTimeoutException) { - logger.trace("timeout - setting error code to -1"); - returnPacket.setPayload("timeout"); - returnPacket.setReturnCode(-1); - } else { + } catch (EOFException e) { + // Read suddenly ended .... + logger.warn("EOFException: exception while reading packet - {}", e.getMessage()); checkConnection(); - throw new OwException("I/O error: exception while reading packet - " + e.getMessage()); + throw new OwException("EOFException: exception while reading packet - " + e.getMessage()); + } catch (OwException e) { + // Some other issue + checkConnection(); + throw e; + } catch (IOException e) { + // Read time out + if (e.getMessage().equals("Read timed out") && noTimeoutException) { + logger.trace("timeout - setting error code to -1"); + // will lead to re-try reading in request method!!! + returnPacket.setPayload("timeout"); + returnPacket.setReturnCode(-1); + } else { + // Other I/O issue + checkConnection(); + throw new OwException("I/O error: exception while reading packet - " + e.getMessage()); + } } + logger.trace("read: {}", returnPacket); + } else { + logger.debug("input stream not available on read"); + closeOnError(); + throw new OwException("I/O Error: input stream not available on read"); } return returnPacket; } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverConnectionState.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverConnectionState.java index 6dcce21e81f06..e225c540ef100 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverConnectionState.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverConnectionState.java @@ -19,8 +19,23 @@ */ public enum OwserverConnectionState { + /** + * The {@link OwserverConnection} is being torn down (mostly due to dispose of handler). + * No refresh, etc. are possible. + */ STOPPED, + /** + * The connection is open. + */ OPENED, + /** + * The connection is closed. On next read / write it will be opened. + */ CLOSED, + /** + * The connection is erroneous and was closed by the {@link OwserverConnection}. After due wait time, it + * is tried to reopen it by a scheduled task of + * {@link OwserverBridgeHandler#reportConnectionState(OwserverConnectionState)}. + */ FAILED } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverControlFlag.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverControlFlag.java index 0048e43c9703e..cff23e29297b2 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverControlFlag.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverControlFlag.java @@ -54,5 +54,4 @@ public int getValue() { public boolean isSet(int controlFlags) { return (this.getValue() & controlFlags) == this.getValue(); } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverPacket.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverPacket.java index 128b357bc2c30..86fe8a3073a63 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverPacket.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverPacket.java @@ -13,6 +13,7 @@ package org.openhab.binding.onewire.internal.owserver; import java.io.DataInputStream; +import java.io.EOFException; import java.io.IOException; import java.nio.ByteBuffer; @@ -62,7 +63,7 @@ public OwserverPacket(OwserverPacketType packetType) { * @throws OwExeption */ public OwserverPacket(DataInputStream owInputStream, OwserverPacketType packetType) - throws IOException, OwException { + throws IOException, OwException, EOFException { this.packetType = packetType; // header @@ -342,7 +343,5 @@ public String toString() { return String.format("%s, size %d, controlFlags 0x%08x, payload '%s'", prefix, HEADER_SIZE + payloadLength, controlFlags, getPayloadString().replaceAll("\\p{C}", "?")); - } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverTemperatureScale.java b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverTemperatureScale.java index 93c528cc0b885..0a0ca352cc4e9 100644 --- a/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverTemperatureScale.java +++ b/bundles/org.openhab.binding.onewire/src/main/java/org/openhab/binding/onewire/internal/owserver/OwserverTemperatureScale.java @@ -73,5 +73,4 @@ public static OwserverTemperatureScale getFlag(int flags) { } return CENTIGRADE; } - } diff --git a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/bae09x.xml b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/bae09x.xml index 3f226e91f0238..38973babbbab5 100644 --- a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/bae09x.xml +++ b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/bae09x.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + 1-wire multisensor (BAE0910-based) @@ -150,7 +150,7 @@ Number:ElectricPotential Analog input (ADC) - + @@ -163,6 +163,6 @@ Number - + diff --git a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/basic.xml b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/basic.xml index 64dc53527e972..6e777f208a953 100644 --- a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/basic.xml +++ b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/basic.xml @@ -5,9 +5,9 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + - + diff --git a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/bridge.xml index 6e888da8de448..0c0f85075e227 100644 --- a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/bridge.xml @@ -25,7 +25,7 @@ String Allows direct access to the OWFS - + @@ -45,7 +45,7 @@ Number Allows direct access to the OWFS - + diff --git a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/common.xml b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/common.xml index 00c517ba9a3b3..54c01c5abd67a 100644 --- a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/common.xml +++ b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/common.xml @@ -8,20 +8,20 @@ Switch ON if device present on OneWire bus - + Number:Temperature temperature value of this sensor - + Number:Temperature temperature value of this sensor - + @@ -35,7 +35,7 @@ Number:Temperature temperature value of this sensor - + @@ -62,20 +62,20 @@ Number:Temperature dewpoint (calculated from temperature and relative humidity) - + Number:Dimensionless relative humidity (0-100%) - + Number:Dimensionless relative humidity (0-100%) - + @@ -96,35 +96,35 @@ Number:Density absolute humidity (calculated from temperature and relative humidity) - + Number:ElectricPotential The voltage measured by the sensor - + Number:ElectricPotential The sensor's supply voltage - + Number:Illuminance Ambient light - + Number:ElectricCurrent The current measured by the sensor - + @@ -156,13 +156,13 @@ Number:Pressure The pressure measured by the sensor - + Number A single counter (reset on power loss) - + diff --git a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/multisensor.xml b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/multisensor.xml index 7ca785683b996..3af91defdcf0e 100644 --- a/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/multisensor.xml +++ b/bundles/org.openhab.binding.onewire/src/main/resources/ESH-INF/thing/multisensor.xml @@ -5,15 +5,15 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + A 1-wire multisensor (DS1923/DS2438-based) - + - + 1-wire multisensor (DS2438-based) @@ -44,7 +44,7 @@ - + 1-wire multisensor (DS2438-based) @@ -82,7 +82,7 @@ - + A 1-wire multisensor (EDS00xx-based) diff --git a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/OwserverDeviceParameterTest.java b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/OwserverDeviceParameterTest.java index 1eb0664c7d089..9dfe7de596c57 100644 --- a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/OwserverDeviceParameterTest.java +++ b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/OwserverDeviceParameterTest.java @@ -57,7 +57,5 @@ public void withPrefixTest() { owserverDeviceParameter = new OwserverDeviceParameter("uncached/", "/humidity"); assertEquals("/uncached/1F.0123456789ab/main/00.1234567890ab/humidity", owserverDeviceParameter.getPath(sensorId)); - } - } diff --git a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/SensorIdTest.java b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/SensorIdTest.java index bc6148a4d9751..50fc6eb425516 100644 --- a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/SensorIdTest.java +++ b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/SensorIdTest.java @@ -74,5 +74,4 @@ public void equalsTest() { assertTrue(sensorId1.equals(sensorId2)); assertFalse(sensorId1.equals(sensorId3)); } - } diff --git a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/UtilTest.java b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/UtilTest.java index 91df99cea6974..8e7601d16dda0 100644 --- a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/UtilTest.java +++ b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/UtilTest.java @@ -40,7 +40,6 @@ public void convertAbsoluteHumidityTest() { QuantityType absoluteHumidity = (QuantityType) Util.calculateAbsoluteHumidity(temperature, relativeHumidity); assertEquals(12.93, absoluteHumidity.doubleValue(), 0.01); - } @Test diff --git a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/internal/OwserverBridgeHandlerTest.java b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/internal/OwserverBridgeHandlerTest.java index c16d11c8c1ed7..b1715089fc4ac 100644 --- a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/internal/OwserverBridgeHandlerTest.java +++ b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/internal/OwserverBridgeHandlerTest.java @@ -168,5 +168,4 @@ public void testInitializationReportsNotRefreshableOnFailedConnection() { waitForAssert(() -> assertFalse(bridgeHandler.isRefreshable())); } - } diff --git a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/owserver/OwserverConnectionTest.java b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/owserver/OwserverConnectionTest.java index 38a4ddf8b7522..18fe1026e25b4 100644 --- a/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/owserver/OwserverConnectionTest.java +++ b/bundles/org.openhab.binding.onewire/src/test/java/org/openhab/binding/onewire/owserver/OwserverConnectionTest.java @@ -12,10 +12,8 @@ */ package org.openhab.binding.onewire.owserver; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.timeout; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; import static org.mockito.MockitoAnnotations.initMocks; import java.io.IOException; @@ -148,15 +146,11 @@ public void testCheckPresence() { return; } owserverConnection.start(); - try { - State presence = owserverConnection.checkPresence("present"); - assertEquals(OnOffType.ON, presence); + State presence = owserverConnection.checkPresence("present"); + assertEquals(OnOffType.ON, presence); - presence = owserverConnection.checkPresence("notpresent"); - assertEquals(OnOffType.OFF, presence); - } catch (OwException e) { - Assert.fail("caught unexpected OwException"); - } + presence = owserverConnection.checkPresence("notpresent"); + assertEquals(OnOffType.OFF, presence); } @Test diff --git a/bundles/org.openhab.binding.onewiregpio/pom.xml b/bundles/org.openhab.binding.onewiregpio/pom.xml index b3f8495a743c4..98802d98bde26 100644 --- a/bundles/org.openhab.binding.onewiregpio/pom.xml +++ b/bundles/org.openhab.binding.onewiregpio/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.onewiregpio diff --git a/bundles/org.openhab.binding.onewiregpio/src/main/feature/feature.xml b/bundles/org.openhab.binding.onewiregpio/src/main/feature/feature.xml index 72bbd6c917d32..c572505c1838d 100644 --- a/bundles/org.openhab.binding.onewiregpio/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.onewiregpio/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.onewiregpio/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.onewiregpio/${project.version} + diff --git a/bundles/org.openhab.binding.onewiregpio/src/main/java/org/openhab/binding/onewiregpio/internal/OneWireGPIOBindingConstants.java b/bundles/org.openhab.binding.onewiregpio/src/main/java/org/openhab/binding/onewiregpio/internal/OneWireGPIOBindingConstants.java index ae76eb490815b..a78f5145ff7c4 100644 --- a/bundles/org.openhab.binding.onewiregpio/src/main/java/org/openhab/binding/onewiregpio/internal/OneWireGPIOBindingConstants.java +++ b/bundles/org.openhab.binding.onewiregpio/src/main/java/org/openhab/binding/onewiregpio/internal/OneWireGPIOBindingConstants.java @@ -38,5 +38,4 @@ public class OneWireGPIOBindingConstants { public static final int MAX_PRECISION_VALUE = 3; public static final String FILE_TEMP_MARKER = "t="; - } diff --git a/bundles/org.openhab.binding.onewiregpio/src/main/java/org/openhab/binding/onewiregpio/internal/handler/OneWireGPIOHandler.java b/bundles/org.openhab.binding.onewiregpio/src/main/java/org/openhab/binding/onewiregpio/internal/handler/OneWireGPIOHandler.java index 85bdf7cb7a250..c387d8d7fa4cc 100644 --- a/bundles/org.openhab.binding.onewiregpio/src/main/java/org/openhab/binding/onewiregpio/internal/handler/OneWireGPIOHandler.java +++ b/bundles/org.openhab.binding.onewiregpio/src/main/java/org/openhab/binding/onewiregpio/internal/handler/OneWireGPIOHandler.java @@ -173,7 +173,6 @@ private BigDecimal readSensorTemperature(String gpioFile) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error reading GPIO bus file."); return null; } - } private BigDecimal calculateValue(Integer intTemp) { diff --git a/bundles/org.openhab.binding.onewiregpio/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.onewiregpio/src/main/resources/ESH-INF/binding/binding.xml index 8b0639b6d200d..2eab172daf09d 100644 --- a/bundles/org.openhab.binding.onewiregpio/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.onewiregpio/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - OneWireGPIO Binding Use GPIO in various devices like RaspberryPi to communicate the OneWire protocol diff --git a/bundles/org.openhab.binding.onewiregpio/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.onewiregpio/src/main/resources/ESH-INF/thing/thing-types.xml index cde2988b4008b..2f4278b99dbe9 100644 --- a/bundles/org.openhab.binding.onewiregpio/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.onewiregpio/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -8,7 +9,7 @@ OneWire GPIO Temperature sensor - + @@ -36,7 +37,7 @@ Number:Temperature Indicates the temperature read from one wire gpio sensor - + diff --git a/bundles/org.openhab.binding.onkyo/pom.xml b/bundles/org.openhab.binding.onkyo/pom.xml index 0afe3d8321d06..6bc133235b644 100644 --- a/bundles/org.openhab.binding.onkyo/pom.xml +++ b/bundles/org.openhab.binding.onkyo/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.onkyo diff --git a/bundles/org.openhab.binding.onkyo/src/main/feature/feature.xml b/bundles/org.openhab.binding.onkyo/src/main/feature/feature.xml index 3d6bda88646f1..270b51c09222b 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.onkyo/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.onkyo/${project.version} + diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoBindingConstants.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoBindingConstants.java index 18b03b08b9b10..cc781866b02ac 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoBindingConstants.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoBindingConstants.java @@ -92,5 +92,4 @@ public class OnkyoBindingConstants { // Used for Discovery service public static final String MANUFACTURER = "ONKYO"; public static final String UPNP_DEVICE_TYPE = "MediaRenderer"; - } diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoModel.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoModel.java index 3605c57c54e86..ae3a2cd80571e 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoModel.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoModel.java @@ -63,5 +63,4 @@ private OnkyoModel(String id) { public String getId() { return id; } - } diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoStateDescriptionProvider.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoStateDescriptionProvider.java index 07330cc96de04..ce33774e0063e 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoStateDescriptionProvider.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/OnkyoStateDescriptionProvider.java @@ -52,7 +52,8 @@ public void setStateOptions(ChannelUID channelUID, List options) { return null; } - StateDescriptionFragmentBuilder builder = (original == null) ? StateDescriptionFragmentBuilder.create() : StateDescriptionFragmentBuilder.create(original); + StateDescriptionFragmentBuilder builder = (original == null) ? StateDescriptionFragmentBuilder.create() + : StateDescriptionFragmentBuilder.create(original); return builder.withOptions(options).build().toStateDescription(); } diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/discovery/OnkyoUpnpDiscoveryParticipant.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/discovery/OnkyoUpnpDiscoveryParticipant.java index aff8e8d8e08f5..b46d555324699 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/discovery/OnkyoUpnpDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/discovery/OnkyoUpnpDiscoveryParticipant.java @@ -146,5 +146,4 @@ private boolean isSupportedDeviceModel(final @Nullable String deviceModel) { return StringUtils.isNotBlank(deviceModel) && Arrays.stream(OnkyoModel.values()) .anyMatch(model -> StringUtils.startsWithIgnoreCase(deviceModel, model.getId())); } - } diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/eiscp/EiscpException.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/eiscp/EiscpException.java index 3ca9b6f3e7aed..f588cf826153d 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/eiscp/EiscpException.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/eiscp/EiscpException.java @@ -36,5 +36,4 @@ public EiscpException(String message, Throwable cause) { public EiscpException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/handler/OnkyoHandler.java b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/handler/OnkyoHandler.java index f908625b627bd..7608eeb44f149 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/handler/OnkyoHandler.java +++ b/bundles/org.openhab.binding.onkyo/src/main/java/org/openhab/binding/onkyo/internal/handler/OnkyoHandler.java @@ -90,7 +90,7 @@ public class OnkyoHandler extends UpnpAudioSinkHandler implements OnkyoEventList private State volumeLevelZone2 = UnDefType.UNDEF; private State volumeLevelZone3 = UnDefType.UNDEF; private State lastPowerState = OnOffType.OFF; - + private final OnkyoStateDescriptionProvider stateDescriptionProvider; private final OnkyoAlbumArt onkyoAlbumArt = new OnkyoAlbumArt(); @@ -509,7 +509,6 @@ private void processInfo(String infoXML) { } catch (ParserConfigurationException | SAXException | IOException e) { logger.debug("Error occured during Info XML parsing.", e); } - } @Override @@ -620,7 +619,6 @@ private void updateAlbumArt(String data) { logger.debug("Not supported album art URL type: {}", data.substring(0, 2)); updateState(CHANNEL_ALBUM_ART_URL, UnDefType.UNDEF); } - } private void updateNetTitle(String data) { @@ -635,7 +633,6 @@ private void updateNetTitle(String data) { updateState(CHANNEL_NET_MENU_TITLE, new StringType(service.toString() + ((title.length() > 0) ? ": " + title : ""))); - } private void updateNetMenu(String data) { diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/binding/binding.xml index 72069e85296f2..35e690fcd23b4 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Onkyo Binding diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/config/config.xml index 45efc073ed5b6..0d76748e77b50 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/config/config.xml @@ -24,7 +24,9 @@ - The refresh interval in seconds for polling the receiver (0=disable). Binding receive automatically updates from + The refresh interval in seconds for polling the receiver (0=disable). Binding receive automatically + updates from + 0 true diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/channel-groups.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/channel-groups.xml index e9a5e55597852..03bb270fcd336 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/channel-groups.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/channel-groups.xml @@ -1,5 +1,6 @@ - @@ -8,53 +9,53 @@ - - - - + + + + - - - - + + + + - - - - + + + + - - - - - - - - - + + + + + + + + + - - + + Net/USB menu item at position 0 @@ -95,7 +96,7 @@ Net/USB menu item at position 9 - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/ht-rc560.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/ht-rc560.xml index fb74846def4ca..9d6b1cb46a6dd 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/ht-rc560.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/ht-rc560.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/onkyoAVR.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/onkyoAVR.xml index 711136acfba98..556de328f7c8e 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/onkyoAVR.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/onkyoAVR.xml @@ -1,5 +1,6 @@ - @@ -9,14 +10,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/onkyoUnsupported.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/onkyoUnsupported.xml index 412dcede5b220..5ef600e688a96 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/onkyoUnsupported.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/onkyoUnsupported.xml @@ -1,20 +1,22 @@ - - Network enabled Onkyo AV Receivers for models that are not officially supported. You may experience some odd behaviors. + Network enabled Onkyo AV Receivers for models that are not officially supported. You may experience some + odd behaviors. - - - + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr3007.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr3007.xml index 624190a219219..75c6437d8433b 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr3007.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr3007.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr414.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr414.xml index 480fc1a2fc210..3e6913fb71bf4 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr414.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr414.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr474.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr474.xml index cb1f5d2b57d6c..b6f1d1a6041ba 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr474.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr474.xml @@ -1,19 +1,20 @@ - - - - - - Network enabled Onkyo AV Receiver - - - - - - - - - - - + + + + + + Network enabled Onkyo AV Receiver + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr509.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr509.xml index b573c4ed36f4e..65aa6f66af8e0 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr509.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr509.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr515.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr515.xml index 5e42e4ea03fe4..088a172b8d218 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr515.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr515.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr525.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr525.xml index 1902e8b787642..45ff4bc2acfc1 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr525.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr525.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr535.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr535.xml index 1894b6d3cb0f4..bd29ac88e5a3f 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr535.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr535.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr545.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr545.xml index 271dad2781909..b50e0c88f0930 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr545.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr545.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr555.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr555.xml index 8071b87451b5d..2865b309c1fa2 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr555.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr555.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr575.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr575.xml index f17ca0ff264a3..5ec7af800d5c6 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr575.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr575.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr575e.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr575e.xml index c24b3ef17964e..bfe837cf80bd3 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr575e.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr575e.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr616.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr616.xml index 4ddca4779a923..fc808e1149eac 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr616.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr616.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr626.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr626.xml index 254551da3fa42..ef0a088397f65 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr626.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr626.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr636.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr636.xml index af65f7a1ca0a7..758ff2e58564f 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr636.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr636.xml @@ -1,20 +1,21 @@ - - - - - - Network enabled Onkyo AV Receiver - - - - - - - - - - - - + + + + + + Network enabled Onkyo AV Receiver + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr646.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr646.xml index aacc14266186b..13018e87c744d 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr646.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr646.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr656.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr656.xml index 9d05b5dad9ffa..b555ff761d008 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr656.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr656.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr676.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr676.xml index 9f36ee2c5784e..1732a70b24917 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr676.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr676.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr686.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr686.xml index 25208ddb0e74f..72b35531b1a2d 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr686.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr686.xml @@ -1,20 +1,21 @@ - - - - - - Network enabled Onkyo AV Receiver - - - - - - - - - - - - + + + + + + Network enabled Onkyo AV Receiver + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr708.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr708.xml index 11a4303a63ad5..26de65a9d12ee 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr708.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr708.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr717.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr717.xml index 89da3644832b6..a78297a4d01f4 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr717.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr717.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr727.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr727.xml index e51c3b6603a86..b3fe2ba56d721 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr727.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr727.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr737.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr737.xml index edbf382442e3e..3dfb36053227e 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr737.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr737.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr747.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr747.xml index 7561a9427ff34..375661dc86679 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr747.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr747.xml @@ -1,5 +1,6 @@ - @@ -8,13 +9,13 @@ Network enabled Onkyo AV Receiver - - - - + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr809.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr809.xml index 9204cb73b502b..f7ace621d525c 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr809.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr809.xml @@ -9,14 +9,14 @@ Network enabled Onkyo AV Receivers - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr818.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr818.xml index dcb1e889fe000..0e23b22485e60 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr818.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr818.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr828.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr828.xml index ef5323e048ab3..fc3317abc3b22 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr828.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr828.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr838.xml b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr838.xml index 77a56cbc1ec5e..b48fef1f68963 100644 --- a/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr838.xml +++ b/bundles/org.openhab.binding.onkyo/src/main/resources/ESH-INF/thing/tx-nr838.xml @@ -1,5 +1,6 @@ - @@ -8,14 +9,14 @@ Network enabled Onkyo AV Receiver - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.opengarage/README.md b/bundles/org.openhab.binding.opengarage/README.md index 20bb840c8b20f..e7c4525ae0cdf 100644 --- a/bundles/org.openhab.binding.opengarage/README.md +++ b/bundles/org.openhab.binding.opengarage/README.md @@ -23,11 +23,13 @@ As a minimum, the IP address is needed: ## Channels -| channel | type | description | -|----------|--------|--------------------------------------------------------| -| distance | Number:Length | Distance reading from the OpenGarage controller (default in cm) | -| status | Switch | Door status OFF = Closed, ON = Open | -| vehicle | String | Report vehicle presence from the OpenGarage controller | +| channel | type | description | +|----------------------|---------------|---------------------------------------------------------------------------------------| +| distance | Number:Length | Distance reading from the OpenGarage controller (default in cm) | +| status-switch | Switch | Door status (OFF = Closed, ON = Open), set "invert=true" on channel to invert switch | +| status-contact | Contact | Door status (Open or Closed) | +| status-rollershutter | Rollershutter | Door status (DOWN = Closed, UP = Open) | +| vehicle-status | Number | Report vehicle presence (0=Not Detected, 1=Detected, 2=Unknown) | ## Full Example @@ -41,6 +43,8 @@ opengarage.items: ``` Switch OpenGarage_Status { channel="opengarage:opengarage:OpenGarage:status" } +Contact OpenGarage_Status_Contact { channel="opengarage:opengarage:OpenGarage:status-contact" } +Rollershutter OpenGarage_Status_Rollershutter { channel="opengarage:opengarage:OpenGarage:status-rollershutter" } Number:Length OpenGarage_Distance { channel="opengarage:opengarage:OpenGarage:setpoint" } String OpenGarage_Vehicle { channel="opengarage:opengarage:OpenGarage:vehicle" } ``` @@ -48,9 +52,11 @@ String OpenGarage_Vehicle { channel="opengarage:opengarage:OpenGarage:vehicle" } opengarage.sitemap: ``` -Switch item=OpenGarage_Status icon="garagedoorclosed" mappings=[ON=Open] visibility=[OpenGarage_Status == CLOSED] -Switch item=OpenGarage_Status icon="garagedooropen" mappings=[OFF=Close] visibility=[OpenGarage_Status == OPEN] +Switch item=OpenGarage_Status icon="garagedoorclosed" mappings=[ON=Open] visibility=[OpenGarage_Status == OFF] +Switch item=OpenGarage_Status icon="garagedooropen" mappings=[OFF=Close] visibility=[OpenGarage_Status == ON] Switch item=OpenGarage_Status icon="garage" +Contact item=OpenGarage_Status_Contact icon="garage" +Rollershutter item=OpenGarage_Status_Rollershutter icon="garage" Text item=OpenGarage_Distance label="OG distance" Text item=OpenGarage_Vehicle label="Vehicle Presence" ``` diff --git a/bundles/org.openhab.binding.opengarage/pom.xml b/bundles/org.openhab.binding.opengarage/pom.xml index e6250ecb5fc1a..bb09c84478678 100644 --- a/bundles/org.openhab.binding.opengarage/pom.xml +++ b/bundles/org.openhab.binding.opengarage/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.opengarage diff --git a/bundles/org.openhab.binding.opengarage/src/main/feature/feature.xml b/bundles/org.openhab.binding.opengarage/src/main/feature/feature.xml index d9c8efe80bae3..19e65804f48ff 100644 --- a/bundles/org.openhab.binding.opengarage/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.opengarage/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.opengarage/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.opengarage/${project.version} + diff --git a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageBindingConstants.java b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageBindingConstants.java index af9bd360a1fbd..8159508a47e5e 100644 --- a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageBindingConstants.java +++ b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageBindingConstants.java @@ -30,12 +30,16 @@ public class OpenGarageBindingConstants { private static final String BINDING_ID = "opengarage"; // List of all Thing Type UIDs - public static final ThingTypeUID OPENGARAGE_THING = new ThingTypeUID(BINDING_ID, "opengarage"); + public static final ThingTypeUID OPENGARAGE_THING = new ThingTypeUID(BINDING_ID, "opengarage"); // List of all Channel ids public static final String CHANNEL_OG_DISTANCE = "distance"; - public static final String CHANNEL_OG_STATUS = "status"; - public static final String CHANNEL_OG_VEHICLE = "vehicle"; + public static final String CHANNEL_OG_STATUS = "status"; // now deprecated + public static final String CHANNEL_OG_STATUS_SWITCH = "status-switch"; + public static final String CHANNEL_OG_STATUS_CONTACT = "status-contact"; + public static final String CHANNEL_OG_STATUS_ROLLERSHUTTER = "status-rollershutter"; + public static final String CHANNEL_OG_VEHICLE = "vehicle"; // now deprecated + public static final String CHANNEL_OG_VEHICLE_STATUS = "vehicle-status"; public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(OPENGARAGE_THING); } diff --git a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageChannelConfiguration.java b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageChannelConfiguration.java new file mode 100644 index 0000000000000..1b608f50679e2 --- /dev/null +++ b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageChannelConfiguration.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.opengarage.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The OpenGarageChannelConfiguration class contains fields mapping thing configuration parameters. + * + * @author Dan Cunningham - Initial contribution + */ +@NonNullByDefault +public class OpenGarageChannelConfiguration { + public boolean invert = false; +} diff --git a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageHandler.java b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageHandler.java index 5ebbe453687c9..bcdeea2c30ac9 100644 --- a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageHandler.java +++ b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageHandler.java @@ -12,35 +12,40 @@ */ package org.openhab.binding.opengarage.internal; +import java.io.IOException; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.types.StopMoveType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.library.types.UpDownType; +import org.eclipse.smarthome.core.library.unit.MetricPrefix; +import org.eclipse.smarthome.core.library.unit.SIUnits; +import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.QuantityType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.MetricPrefix; +import org.openhab.binding.opengarage.internal.api.ControllerVariables; +import org.openhab.binding.opengarage.internal.api.Enums.OpenGarageCommand; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.openhab.binding.opengarage.internal.OpenGarageWebTargets; -import org.openhab.binding.opengarage.internal.api.ControllerVariables; -import org.openhab.binding.opengarage.internal.OpenGarageConfiguration; - -import java.io.IOException; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; /** * The {@link OpenGarageHandler} is responsible for handling commands, which are * sent to one of the channels. * * @author Paul Smedley - Initial contribution + * @author Dan Cunningham - Minor improvements to vehicle state and invert option */ @NonNullByDefault public class OpenGarageHandler extends BaseThingHandler { @@ -59,20 +64,26 @@ public OpenGarageHandler(Thing thing) { @Override public void handleCommand(ChannelUID channelUID, Command command) { try { - logger.warn("Received command {} for thing '{}' on channel {}", command, thing.getUID().getAsString(), - channelUID.getId()); + logger.debug("Received command {} for thing '{}' on channel {}", command, thing.getUID().getAsString(), + channelUID.getId()); + boolean invert = isChannelInverted(channelUID.getId()); switch (channelUID.getId()) { case OpenGarageBindingConstants.CHANNEL_OG_STATUS: - if (command instanceof OnOffType) { - changeStatus(((OnOffType) command).equals(OnOffType.ON)); + case OpenGarageBindingConstants.CHANNEL_OG_STATUS_SWITCH: + case OpenGarageBindingConstants.CHANNEL_OG_STATUS_ROLLERSHUTTER: + if (command.equals(OnOffType.ON) || command.equals(UpDownType.UP)) { + changeStatus(invert ? OpenGarageCommand.CLOSE : OpenGarageCommand.OPEN); + return; + } else if (command.equals(OnOffType.OFF) || command.equals(UpDownType.DOWN)) { + changeStatus(invert ? OpenGarageCommand.OPEN : OpenGarageCommand.CLOSE); + return; + } else if (command.equals(StopMoveType.STOP) || command.equals(StopMoveType.MOVE)) { + changeStatus(OpenGarageCommand.CLICK); return; } break; default: } - - logger.debug("Received command {} of wrong type for thing '{}' on channel {}", command, thing.getUID().getAsString(), - channelUID.getId()); } catch (OpenGarageCommunicationException ex) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, ex.getMessage()); } @@ -131,24 +142,52 @@ private void pollStatus() throws IOException { ControllerVariables controllerVariables = webTargets.getControllerVariables(); updateStatus(ThingStatus.ONLINE); if (controllerVariables != null) { - updateState(OpenGarageBindingConstants.CHANNEL_OG_DISTANCE, new QuantityType<>(controllerVariables.dist, MetricPrefix.CENTI(SIUnits.METRE))); - if (controllerVariables.door == 0) { - updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS, OnOffType.OFF); - } else if (controllerVariables.door == 1) { - updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS, OnOffType.ON); + updateState(OpenGarageBindingConstants.CHANNEL_OG_DISTANCE, + new QuantityType<>(controllerVariables.dist, MetricPrefix.CENTI(SIUnits.METRE))); + boolean invert = isChannelInverted(OpenGarageBindingConstants.CHANNEL_OG_STATUS_SWITCH); + switch (controllerVariables.door) { + case 0: + updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS, invert ? OnOffType.ON : OnOffType.OFF); + updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS_SWITCH, + invert ? OnOffType.ON : OnOffType.OFF); + updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS_ROLLERSHUTTER, UpDownType.DOWN); + updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS_CONTACT, OpenClosedType.CLOSED); + break; + case 1: + updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS, invert ? OnOffType.OFF : OnOffType.ON); + updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS_SWITCH, + invert ? OnOffType.OFF : OnOffType.ON); + updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS_ROLLERSHUTTER, UpDownType.UP); + updateState(OpenGarageBindingConstants.CHANNEL_OG_STATUS_CONTACT, OpenClosedType.OPEN); + break; + default: + logger.warn("Received unknown door value: {}", controllerVariables.door); } - if (controllerVariables.vehicle == 0) { - updateState(OpenGarageBindingConstants.CHANNEL_OG_VEHICLE, new StringType("No vehicle detected")); - } else if (controllerVariables.vehicle == 1) { - updateState(OpenGarageBindingConstants.CHANNEL_OG_VEHICLE, new StringType("Vehicle detected")); - } else if (controllerVariables.vehicle == 3) { - updateState(OpenGarageBindingConstants.CHANNEL_OG_VEHICLE, new StringType("Vehicle Status Unknown")); + switch (controllerVariables.vehicle) { + case 0: + updateState(OpenGarageBindingConstants.CHANNEL_OG_VEHICLE, new StringType("No vehicle detected")); + break; + case 1: + updateState(OpenGarageBindingConstants.CHANNEL_OG_VEHICLE, new StringType("Vehicle detected")); + break; + case 2: + updateState(OpenGarageBindingConstants.CHANNEL_OG_VEHICLE, + new StringType("Vehicle status unknown")); + break; + default: + logger.warn("Received unknown vehicle value: {}", controllerVariables.vehicle); } + updateState(OpenGarageBindingConstants.CHANNEL_OG_VEHICLE_STATUS, + new DecimalType(controllerVariables.vehicle)); } } - private void changeStatus(boolean status) throws OpenGarageCommunicationException { + private void changeStatus(OpenGarageCommand status) throws OpenGarageCommunicationException { webTargets.setControllerVariables(status); } + private boolean isChannelInverted(String channelUID) { + Channel channel = getThing().getChannel(channelUID); + return channel != null && channel.getConfiguration().as(OpenGarageChannelConfiguration.class).invert; + } } diff --git a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageWebTargets.java b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageWebTargets.java index 2c5dcf744c4a9..d28b1481562f6 100644 --- a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageWebTargets.java +++ b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/OpenGarageWebTargets.java @@ -16,6 +16,7 @@ import org.eclipse.smarthome.io.net.http.HttpUtil; import org.openhab.binding.opengarage.internal.api.ControllerVariables; +import org.openhab.binding.opengarage.internal.api.Enums.OpenGarageCommand; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,17 +44,23 @@ public ControllerVariables getControllerVariables() throws OpenGarageCommunicati return ControllerVariables.parse(response); } - public void setControllerVariables(boolean request) throws OpenGarageCommunicationException { + public void setControllerVariables(OpenGarageCommand request) throws OpenGarageCommunicationException { logger.debug("Received request: {}", request); - if (request) { - logger.debug("Received request to open door"); - String queryParams = "&open=1"; - invoke(changeControllerVariablesUri, queryParams); - } else { - logger.debug("Received request to close door"); - String queryParams = "&close=1"; - invoke(changeControllerVariablesUri, queryParams); - } + String queryParams = null; + switch (request) { + case OPEN: + queryParams = "&open=1"; + break; + case CLOSE: + queryParams = "&close=1"; + break; + case CLICK: + queryParams = "&click=1"; + break; + } + if (queryParams != null) { + invoke(changeControllerVariablesUri, queryParams); + } } private String invoke(String uri) throws OpenGarageCommunicationException { diff --git a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/api/ControllerVariables.java b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/api/ControllerVariables.java index 1f14dc4f839fd..abed44d76e3b2 100644 --- a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/api/ControllerVariables.java +++ b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/api/ControllerVariables.java @@ -12,12 +12,12 @@ */ package org.openhab.binding.opengarage.internal.api; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + /** * Class for holding the set of parameters used to read the controller variables. * @@ -37,7 +37,6 @@ public class ControllerVariables { public String cid; public int rssi; - private ControllerVariables() { } @@ -57,5 +56,4 @@ public static ControllerVariables parse(String response) { info.rssi = jsonObject.get("rssi").getAsInt(); return info; } - } diff --git a/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/api/Enums.java b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/api/Enums.java new file mode 100644 index 0000000000000..039c73a0c2f51 --- /dev/null +++ b/bundles/org.openhab.binding.opengarage/src/main/java/org/openhab/binding/opengarage/internal/api/Enums.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.opengarage.internal.api; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Container class for enums related to opengarage + * + * @author Paul Smedley - Initial contribution + * + */ +public class Enums { + public enum OpenGarageCommand { + OPEN("open"), + CLOSE("close"), + CLICK("click"); + + private static final Logger LOGGER = LoggerFactory.getLogger(OpenGarageCommand.class); + private final String value; + + OpenGarageCommand(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + } +} diff --git a/bundles/org.openhab.binding.opengarage/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.opengarage/src/main/resources/ESH-INF/thing/thing-types.xml index 5708076ea9d54..b8f877d28f044 100644 --- a/bundles/org.openhab.binding.opengarage/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.opengarage/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,9 +9,13 @@ OpenGarage Controller - - - + + + + + + + @@ -43,18 +47,69 @@ Number:Length Distance Reading from the OG unit - + - + Switch - Status of the OG unit + On/Off Status of the OG unit (now deprecated, use status-switch instead) + + + + Invert switch to ON=Closed, OFF=Open + false + + + + + true + + - + + Switch + + On/Off Status of the OG unit + + + + Invert switch to ON=Closed, OFF=Open + false + + + + + true + + + + + Contact + + Contact Status of the OG unit + + + + Rollershutter + + Roller Shutter Status of the OG unit + + String - Is a vehicle present or not + Is a vehicle present or not (now deprecated, use vehicle-status instead) - + + Number + + Vehicle presence detection + + + + + + + + diff --git a/bundles/org.openhab.binding.opensprinkler/README.md b/bundles/org.openhab.binding.opensprinkler/README.md index d21a3e8b45d9f..e42ee82f8f634 100644 --- a/bundles/org.openhab.binding.opensprinkler/README.md +++ b/bundles/org.openhab.binding.opensprinkler/README.md @@ -22,7 +22,7 @@ Discovery needs to be run manually as this is a brute force method of finding de OpenSprinkler using the HTTP interface ``` -Bridge opensprinkler:http:http [hostname="127.0.0.1", port=80, pasword="opendoor", refresh=60] { +Bridge opensprinkler:http:http [hostname="127.0.0.1", port=80, password="opendoor", refresh=60] { Thing station 01 [stationIndex=1] } ``` @@ -61,9 +61,11 @@ When using the `nextDuration` channel, it is advised to setup persistence (e.g. The following is supported by the `device` thing, but only when connected using the http interface. -| Channel Type ID | Item Type | | Description | -|-----------------|-----------|----|-----------------------------------------------------------------------| -| rainsensor | Switch | RO | This channel indicates whether rain is detected by the device or not. | +| Channel Type ID | Item Type | | Description | +|-----------------|------------------------|----|---------------------------------------------------------------------------| +| rainsensor | Switch | RO | This channel indicates whether rain is detected by the device or not. | +| currentDraw | Number:ElectricCurrent | RO | Shows the current draw of the device. If the device does not have sensors | +| | | | for this metric, the channel will not be available. | ## Example @@ -95,6 +97,7 @@ Switch Station05 (stations) { channel="opensprinkler:station:http:05:stationStat Switch Station06 (stations) { channel="opensprinkler:station:http:06:stationState" } Switch RainSensor { channel="opensprinkler:station:http:device:rainsensor" } +Number:ElectricCurrent CurrentDraw {channel="opensprinkler:station:http:device:currentDraw"} ``` demo.sitemap: diff --git a/bundles/org.openhab.binding.opensprinkler/pom.xml b/bundles/org.openhab.binding.opensprinkler/pom.xml index e586ecbb2d70b..8ef8e463ea022 100644 --- a/bundles/org.openhab.binding.opensprinkler/pom.xml +++ b/bundles/org.openhab.binding.opensprinkler/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.opensprinkler diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/feature/feature.xml b/bundles/org.openhab.binding.opensprinkler/src/main/feature/feature.xml index fd736489ed72a..01b0205a35303 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.opensprinkler/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.opensprinkler/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.opensprinkler/${project.version} + diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerBindingConstants.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerBindingConstants.java index 51296d6d9308a..6231ef99fe0bf 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerBindingConstants.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/OpenSprinklerBindingConstants.java @@ -47,6 +47,7 @@ public class OpenSprinklerBindingConstants { // List of all Channel ids public static final String SENSOR_RAIN = "rainsensor"; + public static final String SENSOR_CURRENT_DRAW = "currentDraw"; public static final String STATION_STATE = "stationState"; public static final String STATION_QUEUED = "queued"; public static final String REMAINING_WATER_TIME = "remainingWaterTime"; diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApi.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApi.java index 1ecaa0bb85319..8273e8eb61d21 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApi.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerApi.java @@ -16,6 +16,7 @@ import org.openhab.binding.opensprinkler.internal.api.exception.CommunicationApiException; import org.openhab.binding.opensprinkler.internal.api.exception.GeneralApiException; +import org.openhab.binding.opensprinkler.internal.model.NoCurrentDrawSensorException; import org.openhab.binding.opensprinkler.internal.model.StationProgram; /** @@ -26,7 +27,7 @@ */ public interface OpenSprinklerApi { /** - * Whether the devie entered manual mode and accepts API requests to control the stations. + * Whether the device entered manual mode and accepts API requests to control the stations. * * @return True if this API interface is connected to the Open Sprinkler API. False otherwise. */ @@ -90,6 +91,15 @@ public abstract void openStation(int station, BigDecimal duration) */ public abstract boolean isRainDetected() throws CommunicationApiException; + /** + * Returns the current draw of all connected zones of the OpenSprinkler device in milliamperes. + * + * @return current draw in milliamperes + * @throws CommunicationApiException + * @throws + */ + public abstract int currentDraw() throws CommunicationApiException, NoCurrentDrawSensorException; + /** * Returns the number of total stations that are controllable from the OpenSprinkler * device. diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerHttpApiV100.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerHttpApiV100.java index 047ba2aa19c64..0d783418a2dee 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerHttpApiV100.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/api/OpenSprinklerHttpApiV100.java @@ -31,6 +31,7 @@ import org.openhab.binding.opensprinkler.internal.api.exception.CommunicationApiException; import org.openhab.binding.opensprinkler.internal.api.exception.GeneralApiException; import org.openhab.binding.opensprinkler.internal.config.OpenSprinklerHttpInterfaceConfig; +import org.openhab.binding.opensprinkler.internal.model.NoCurrentDrawSensorException; import org.openhab.binding.opensprinkler.internal.model.StationProgram; import org.openhab.binding.opensprinkler.internal.util.Parse; @@ -180,6 +181,15 @@ public boolean isRainDetected() throws CommunicationApiException { } } + @Override + public int currentDraw() throws CommunicationApiException, NoCurrentDrawSensorException { + JcResponse info = statusInfo(); + if (info.curr == null) { + throw new NoCurrentDrawSensorException(); + } + return info.curr; + } + @Override public int getNumberOfStations() throws CommunicationApiException { String returnContent; @@ -259,6 +269,7 @@ private static class JcResponse { public List> ps; @SerializedName(value = "sn1", alternate = "rs") public int rs; + public Integer curr; } /** diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseBridgeHandler.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseBridgeHandler.java index 633e3ee995783..336da25d6b0ce 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseBridgeHandler.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseBridgeHandler.java @@ -102,5 +102,4 @@ public void dispose() { public void handleCommand(ChannelUID channelUID, Command command) { // Nothing to do for the bridge handler } - } diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseHandler.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseHandler.java index aee9156e639cf..9a00aa3812cf9 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseHandler.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerBaseHandler.java @@ -70,5 +70,4 @@ public void updateChannels() { } protected abstract void updateChannel(ChannelUID uid); - } diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerDeviceHandler.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerDeviceHandler.java index afaeab6077e5f..0bb7bc0623811 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerDeviceHandler.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerDeviceHandler.java @@ -12,14 +12,24 @@ */ package org.openhab.binding.opensprinkler.internal.handler; -import static org.openhab.binding.opensprinkler.internal.OpenSprinklerBindingConstants.SENSOR_RAIN; +import static org.eclipse.smarthome.core.library.unit.MetricPrefix.MILLI; +import static org.openhab.binding.opensprinkler.internal.OpenSprinklerBindingConstants.*; + +import javax.measure.quantity.ElectricCurrent; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; +import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; +import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; import org.eclipse.smarthome.core.types.Command; import org.openhab.binding.opensprinkler.internal.api.exception.CommunicationApiException; +import org.openhab.binding.opensprinkler.internal.model.NoCurrentDrawSensorException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,25 +46,55 @@ public OpenSprinklerDeviceHandler(Thing thing) { @Override protected void updateChannel(ChannelUID channel) { - switch (channel.getIdWithoutGroup()) { - case SENSOR_RAIN: - try { + try { + switch (channel.getIdWithoutGroup()) { + case SENSOR_RAIN: if (getApi().isRainDetected()) { updateState(channel, OnOffType.ON); } else { updateState(channel, OnOffType.OFF); } - } catch (CommunicationApiException e) { - logger.debug("Could not update rainsensor", e); + break; + case SENSOR_CURRENT_DRAW: + updateState(channel, + new QuantityType(getApi().currentDraw(), MILLI(SmartHomeUnits.AMPERE))); + break; + default: + logger.debug("Not updating unknown channel {}", channel); + } + } catch (CommunicationApiException | NoCurrentDrawSensorException e) { + logger.debug("Could not update {}", channel, e); + } + } + + @Override + public void initialize() { + ChannelUID currentDraw = new ChannelUID(thing.getUID(), "currentDraw"); + if (thing.getChannel(currentDraw) == null) { + ThingBuilder thingBuilder = editThing(); + try { + getApi().currentDraw(); + + Channel currentDrawChannel = ChannelBuilder.create(currentDraw, "Number:ElectricCurrent") + .withType(new ChannelTypeUID(BINDING_ID, SENSOR_CURRENT_DRAW)).withLabel("Current Draw") + .withDescription("Provides the current draw.").build(); + thingBuilder.withChannel(currentDrawChannel); + + updateThing(thingBuilder.build()); + } catch (NoCurrentDrawSensorException e) { + if (thing.getChannel(currentDraw) != null) { + thingBuilder.withoutChannel(currentDraw); } - default: - logger.debug("Not updating unknown channel {}", channel); + updateThing(thingBuilder.build()); + } catch (CommunicationApiException e) { + logger.debug("Could not query current draw. Not removing channel as it could be temporary.", e); + } } + super.initialize(); } @Override public void handleCommand(ChannelUID channelUID, Command command) { // nothing to do here } - } diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerStationHandler.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerStationHandler.java index 6af81714626a5..97d8311d11c07 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerStationHandler.java +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/handler/OpenSprinklerStationHandler.java @@ -231,5 +231,4 @@ private int getStationIndex() { } return config.stationIndex; } - } diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/model/NoCurrentDrawSensorException.java b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/model/NoCurrentDrawSensorException.java new file mode 100644 index 0000000000000..c9e3df880d060 --- /dev/null +++ b/bundles/org.openhab.binding.opensprinkler/src/main/java/org/openhab/binding/opensprinkler/internal/model/NoCurrentDrawSensorException.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.opensprinkler.internal.model; + +/** + * Indicates, that a device is missing a sensor to measure the current draw of itself. + * + * @author Florian Schmidt - Initial contribution + */ +public class NoCurrentDrawSensorException extends Exception { + private static final long serialVersionUID = 2251925316743442346L; +} diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.opensprinkler/src/main/resources/ESH-INF/binding/binding.xml index 75fe8f102e1bd..46de684cdf263 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.opensprinkler/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + OpenSprinkler Binding This is the binding for OpenSprinkler. diff --git a/bundles/org.openhab.binding.opensprinkler/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.opensprinkler/src/main/resources/ESH-INF/thing/thing-types.xml index abaef0651d0e4..9a2e4cd5162f6 100644 --- a/bundles/org.openhab.binding.opensprinkler/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.opensprinkler/src/main/resources/ESH-INF/thing/thing-types.xml @@ -11,7 +11,8 @@ - The host name or IP address of the OpenSprinkler Web API interface. It may or may not start with the protocol, e.g. in order to use https:// instead of the default http://. + The host name or IP address of the OpenSprinkler Web API interface. It may or may not start with the + protocol, e.g. in order to use https:// instead of the default http://. localhost @@ -44,7 +45,7 @@ - + Controls a station connected to the OpenSprinkler device. @@ -66,7 +67,7 @@ - + A thing that receives data from the OpenSprinkler device directly. @@ -81,7 +82,7 @@ Provides feedback on whether the OpenSprinkler device has detected rain or not. Sensor - + @@ -94,7 +95,8 @@ Switch - Indicates if the station is queued to be turned on. Can be removed from the queue by turning off. ON is read-only. + Indicates if the station is queued to be turned on. Can be removed from the queue by turning off. ON is + read-only. Switch diff --git a/bundles/org.openhab.binding.openthermgateway/.classpath b/bundles/org.openhab.binding.openthermgateway/.classpath new file mode 100644 index 0000000000000..a5d95095ccaaf --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.openthermgateway/.project b/bundles/org.openhab.binding.openthermgateway/.project new file mode 100644 index 0000000000000..23974da119696 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/.project @@ -0,0 +1,23 @@ + + + org.openhab.binding.openthermgateway + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.openthermgateway/NOTICE b/bundles/org.openhab.binding.openthermgateway/NOTICE new file mode 100644 index 0000000000000..4c20ef446c1e4 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab2-addons diff --git a/bundles/org.openhab.binding.openthermgateway/README.md b/bundles/org.openhab.binding.openthermgateway/README.md new file mode 100644 index 0000000000000..e84891cf833be --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/README.md @@ -0,0 +1,144 @@ +# OpenTherm Gateway binding + +This binding is used to integrate the OpenTherm Gateway into openHAB. +The OpenTherm Gateway is a module designed by Schelte Bron that is connected in between a boiler and a thermostat and communicates using the OpenTherm protocol. + +More information on the OpenTherm Gateway device can be found at http://otgw.tclcode.com/ + +Comments on this binding can be submitted to the openHAB community topic at https://community.openhab.org/t/39160 + +## Supported Things + +The OpenTherm Gateway binding currently only supports one thing, and that's the gateway itself. + +## Discovery + +The binding does not support auto discovery. + +## Binding Configuration + +The binding itself does not require any configuration. + +## Thing Configuration + +The binding is designed to support various ways of connecting to the OpenTherm Gateway device, but currently only supports a TCP socket connection. +The configuration settings for the thing are Hostname/IP address and Port, which are used to connect to the gateway, and an automatic connection retry interval in case the connection to the OpenTherm Gateway device is lost. + +| Parameter | Name | Description | Required | Default | +|---------------------------|---------------------------|-----------------------------------------------------------------|----------|---------| +| `ipaddress` | Hostname or IP address | The hostname or IP address to connect to the OpenTherm Gateway. | yes | | +| `port` | Port | The port used to connect to the OpenTherm Gateway. | yes | | +| `connectionRetryInterval` | Connection Retry Interval | The interval in seconds to retry connecting (0 = disabled). | yes | 60 | + +## Channels + +The OpenTherm Gateway binding supports the following channels: + +| Channel Type ID | Item Type | Description | Read Only | +|----------------------|-----------|----------------------------------------------------------|-----------| +| roomtemp | Number | Current sensed room temperature | yes | +| roomsetpoint | Number | Current room temperature setpoint | yes | +| temperaturetemporary | Number | Temporary override room temperature setpoint | no | +| temperatureconstant | Number | Constant override room temperature setpoint | no | +| controlsetpoint | Number | Central heating water setpoint | yes | +| dhwtemp | Number | Domestic hot water temperature | yes | +| tdhwset | Number | Domestic hot water temperature setpoint | yes | +| overridedhwsetpoint | Number | Domestic hot water temperature setpoint override | no | +| flowtemp | Number | Boiler water temperature | yes | +| returntemp | Number | Return water temperature | yes | +| outsidetemp | Number | Outside temperature | no | +| waterpressure | Number | Central heating water pressure | yes | +| ch_enable | Switch | Central heating enabled | yes | +| ch_mode | Switch | Central heating active | yes | +| dhw_enable | Switch | Domestic hot water enabled | yes | +| dhw_mode | Switch | Domestic hot water active | yes | +| flame | Switch | Burner active | yes | +| modulevel | Number | Relative modulation level | yes | +| maxrelmdulevel | Number | Maximum relative modulation level | yes | +| fault | Switch | Fault indication | yes | +| servicerequest | Switch | Service required | yes | +| lockout-reset | Switch | Lockout-reset enabled | yes | +| lowwaterpress | Switch | Low water pressure fault | yes | +| gasflamefault | Switch | Gas or flame fault | yes | +| airpressfault | Switch | Air pressure fault | yes | +| waterovtemp | Switch | Water over-temperature fault | yes | +| oemfaultcode | Switch | OEM fault code | yes | +| sendcommand | Text | Channel to send commands to the OpenTherm Gateway device | no | + +## Full Example + +### demo.things + +``` +Thing openthermgateway:otgw:1 [ ipaddress="192.168.1.100", port=8000, connectionRetryInterval=60 ] +``` + +### demo.items + +``` +Number RoomTemperature "Room temperature [%.1f °C]" { channel="openthermgateway:otgw:1:roomtemp" } +Number RoomSetpoint "Room setpoint [%.1f °C]" { channel="openthermgateway:otgw:1:roomsetpoint" } +Number TemporaryRoomSetpointOverride "Temporary room setpoint override [%.1f °C]" { channel="openthermgateway:otgw:1:temperaturetemporary" } +Number ConstantRoomSetpointOverride "Constant room setpoint override [%.1f °C]" { channel="openthermgateway:otgw:1:temperatureconstant" } +Number ControlSetpoint "Control setpoint [%.1f °C]" { channel="openthermgateway:otgw:1:controlsetpoint" } +Number DomesticHotWaterTemperature "Domestic hot water temperature [%.1f °C]" { channel="openthermgateway:otgw:1:dhwtemp" } +Number DomesticHotWaterSetpoint "Domestic hot water setpoint [%.1f °C]" { channel="openthermgateway:otgw:1:tdhwset" } +Number DomesticHotWaterSetpointOverride "Domestic hot water setpoint override [%.1f °C]" { channel="openthermgateway:otgw:1:overridedhwsetpoint" } +Number BoilerWaterTemperature "Boiler water temperature [%.1f °C]" { channel="openthermgateway:otgw:1:flowtemp" } +Number ReturnWaterTemperature "Return water temperature [%.1f °C]" { channel="openthermgateway:otgw:1:returntemp" } +Number OutsideTemperature "Outside temperature [%.1f °C]" { channel="openthermgateway:otgw:1:outsidetemp" } +Number CentralHeatingWaterPressure "Central heating water pressure [%.1f bar]" { channel="openthermgateway:otgw:1:waterpressure" } +Switch CentralHeatingEnabled "Central heating enabled" { channel="openthermgateway:otgw:1:ch_enable" } +Switch CentralHeatingActive "Central heating active" { channel="openthermgateway:otgw:1:ch_mode" } +Switch DomesticHotWaterEnabled "Domestic hot water enabled" { channel="openthermgateway:otgw:1:dhw_enable" } +Switch DomesticHotWaterActive "Domestic hot water active" { channel="openthermgateway:otgw:1:dhw_mode" } +Switch BurnerActive "Burner active" { channel="openthermgateway:otgw:1:flame" } +Number RelativeModulationLevel "Relative modulation level [%.1f %%]" { channel="openthermgateway:otgw:1:modulevel" } +Number MaximumRelativeModulationLevel "Maximum relative modulation level [%.1f %%]" { channel="openthermgateway:otgw:1:maxrelmdulevel" } +Switch Fault "Fault indication" { channel="openthermgateway:otgw:1:fault" } +Switch ServiceRequest "Service required" { channel="openthermgateway:otgw:1:servicerequest" } +Switch LockoutReset "Lockout-reset" { channel="openthermgateway:otgw:1:lockout-reset" } +Switch LowWaterPress "Low water pressure fault" { channel="openthermgateway:otgw:1:lowwaterpress" } +Switch GasFlameFault "Gas or flame fault" { channel="openthermgateway:otgw:1:gasflamefault" } +Switch AirPressFault "Air pressure fault" { channel="openthermgateway:otgw:1:airpressfault" } +Switch WaterOvTemp "Water over-temperature fault" { channel="openthermgateway:otgw:1:waterovtemp" } +Number OemFaultCode "OEM fault code" { channel="openthermgateway:otgw:1:oemfaultcode" } +Text SendCommand "Send command channel" { channel="openthermgateway:otgw:1:sendcommand" } +``` + +### demo.sitemap + +``` +sitemap demo label="Main Menu" { + Frame label="OpenTherm Gateway" { + Text item="RoomTemperature" icon="temperature" label="Room temperature [%.1f °C]" + Text item="RoomSetpoint" icon="temperature" label="Room setpoint [%.1f °C]" + Setpoint item="TemporaryRoomSetpointOverride" icon="temperature" label="Temporary room setpoint override [%.1f °C]" minValue="0" maxValue="30" step="0.1" + Setpoint item="ConstantRoomSetpointOverride" icon="temperature" label="Constant room setpoint override [%.1f °C]" minValue="0" maxValue="30" step="0.1" + Text item="ControlSetpoint" icon="temperature" label="Control setpoint [%.1f °C]" + Text item="DomesticHotWaterTemperature" icon="temperature" label="Domestic hot water temperature [%.1f °C]" + Text item="DomesticHotWaterSetpoint" icon="temperature" label="Domestic hot water setpoint [%.1f °C]" + Setpoint item="DomesticHotWaterSetpointOverride" icon="temperature" label="Domestic hot water setpoint override [%.1f °C]" minValue="0" maxValue="100" step="0.1" + Text item="BoilerWaterTemperature" icon="temperature" label="Boiler water temperature [%.1f °C]" + Text item="ReturnWaterTemperature" icon="temperature" label="Return water temperature [%.1f °C]" + Setpoint item="OutsideTemperature" icon="temperature" label="Outside temperature [%.1f °C]" minValue="-40" maxValue="100" step="0.1" + Text item="CentralHeatingWaterPressure" icon="" label="Central heating water pressure [%.1f bar]" + Switch item="CentralHeatingEnabled" icon="switch" label="Central heating enabled" + Switch item="CentralHeatingActive" icon="switch" label="Central heating active" + Switch item="DomesticHotWaterEnabled" icon="switch" label="Domestic hot water enabled" + Switch item="DomesticHotWaterActive" icon="switch" label="Domestic hot water active" + Switch item="BurnerActive" icon="switch" label="Burner active" + Text item="RelativeModulationLevel" icon="" label="Relative modulation level [%.1f %%]" + Text item="MaximumRelativeModulationLevel" icon="" label="Maximum relative modulation level [%.1f %%]" + Switch item="Fault" icon="" label="Fault indication" + Switch item="ServiceRequest" icon="" label="Service required" + Switch item="LockoutReset" icon="" label="Lockout-reset" + Switch item="LowWaterPress" icon="" label="Low water pressure fault" + Switch item="GasFlameFault" icon="" label="Gas or flame fault" + Switch item="AirPressFault" icon="" label="Air pressure fault" + Switch item="waterOvTemp" icon="" label="Water over-temperature fault" + Text item="OemFaultCode" icon="" label="OEM fault code" + } +} + +``` diff --git a/bundles/org.openhab.binding.openthermgateway/pom.xml b/bundles/org.openhab.binding.openthermgateway/pom.xml new file mode 100644 index 0000000000000..6d91464ad3633 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + + + org.openhab.binding.openthermgateway + + openHAB Add-ons :: Bundles :: OpenTherm Gateway Binding + + diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/feature/feature.xml b/bundles/org.openhab.binding.openthermgateway/src/main/feature/feature.xml new file mode 100644 index 0000000000000..7bb3096bc8329 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.openthermgateway/${project.version} + + diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/OpenThermGatewayBindingConstants.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/OpenThermGatewayBindingConstants.java new file mode 100644 index 0000000000000..0b19a9bbcaace --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/OpenThermGatewayBindingConstants.java @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link OpenThermGatewayBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public class OpenThermGatewayBindingConstants { + + private static final String BINDING_ID = "openthermgateway"; + + // List of all Thing Type UID's + public static final ThingTypeUID MAIN_THING_TYPE = new ThingTypeUID(BINDING_ID, "otgw"); + + // List of all Channel id's + public static final String CHANNEL_SEND_COMMAND = "sendcommand"; + + public static final String CHANNEL_OVERRIDE_SETPOINT_TEMPORARY = "temperaturetemporary"; + public static final String CHANNEL_OVERRIDE_SETPOINT_CONSTANT = "temperatureconstant"; + public static final String CHANNEL_OVERRIDE_DHW_SETPOINT = "overridedhwsetpoint"; + public static final String CHANNEL_ROOM_TEMPERATURE = "roomtemp"; + public static final String CHANNEL_ROOM_SETPOINT = "roomsetpoint"; + public static final String CHANNEL_FLOW_TEMPERATURE = "flowtemp"; + public static final String CHANNEL_RETURN_TEMPERATURE = "returntemp"; + public static final String CHANNEL_OUTSIDE_TEMPERATURE = "outsidetemp"; + public static final String CHANNEL_CENTRAL_HEATING_WATER_SETPOINT = "controlsetpoint"; + public static final String CHANNEL_CENTRAL_HEATING_WATER_PRESSURE = "waterpressure"; + public static final String CHANNEL_CENTRAL_HEATING_ENABLED = "ch_enable"; + public static final String CHANNEL_CENTRAL_HEATING_MODE = "ch_mode"; + public static final String CHANNEL_DOMESTIC_HOT_WATER_TEMPERATURE = "dhwtemp"; + public static final String CHANNEL_DOMESTIC_HOT_WATER_ENABLED = "dhw_enable"; + public static final String CHANNEL_DOMESTIC_HOT_WATER_MODE = "dhw_mode"; + public static final String CHANNEL_DOMESTIC_HOT_WATER_SETPOINT = "tdhwset"; + public static final String CHANNEL_FLAME = "flame"; + public static final String CHANNEL_RELATIVE_MODULATION_LEVEL = "modulevel"; + public static final String CHANNEL_MAXIMUM_MODULATION_LEVEL = "maxrelmdulevel"; + public static final String CHANNEL_FAULT = "fault"; + public static final String CHANNEL_SERVICEREQUEST = "servicerequest"; + public static final String CHANNEL_REMOTE_RESET = "lockout-reset"; + public static final String CHANNEL_LOW_WATER_PRESSURE = "lowwaterpress"; + public static final String CHANNEL_GAS_FLAME_FAULT = "gasflamefault"; + public static final String CHANNEL_AIR_PRESSURE_FAULT = "airpressfault"; + public static final String CHANNEL_WATER_OVER_TEMP = "waterovtemp"; + public static final String CHANNEL_OEM_FAULTCODE = "oemfaultcode"; + + public static final Set SUPPORTED_CHANNEL_IDS = Collections + .unmodifiableSet(Stream.of(CHANNEL_ROOM_TEMPERATURE, CHANNEL_ROOM_SETPOINT, CHANNEL_FLOW_TEMPERATURE, + CHANNEL_RETURN_TEMPERATURE, CHANNEL_OUTSIDE_TEMPERATURE, CHANNEL_CENTRAL_HEATING_WATER_PRESSURE, + CHANNEL_CENTRAL_HEATING_ENABLED, CHANNEL_CENTRAL_HEATING_MODE, + CHANNEL_CENTRAL_HEATING_WATER_SETPOINT, CHANNEL_DOMESTIC_HOT_WATER_TEMPERATURE, + CHANNEL_DOMESTIC_HOT_WATER_ENABLED, CHANNEL_DOMESTIC_HOT_WATER_MODE, + CHANNEL_DOMESTIC_HOT_WATER_SETPOINT, CHANNEL_FLAME, CHANNEL_RELATIVE_MODULATION_LEVEL, + CHANNEL_MAXIMUM_MODULATION_LEVEL, CHANNEL_FAULT, CHANNEL_SERVICEREQUEST, CHANNEL_REMOTE_RESET, + CHANNEL_LOW_WATER_PRESSURE, CHANNEL_GAS_FLAME_FAULT, CHANNEL_AIR_PRESSURE_FAULT, + CHANNEL_WATER_OVER_TEMP, CHANNEL_OEM_FAULTCODE).collect(Collectors.toSet())); +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/handler/OpenThermGatewayHandler.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/handler/OpenThermGatewayHandler.java new file mode 100644 index 0000000000000..1a1e88ccdc831 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/handler/OpenThermGatewayHandler.java @@ -0,0 +1,273 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.handler; + +import java.util.concurrent.TimeUnit; + +import javax.measure.Unit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.QuantityType; +import org.eclipse.smarthome.core.library.unit.SIUnits; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.State; +import org.openhab.binding.openthermgateway.OpenThermGatewayBindingConstants; +import org.openhab.binding.openthermgateway.internal.DataItem; +import org.openhab.binding.openthermgateway.internal.DataItemGroup; +import org.openhab.binding.openthermgateway.internal.GatewayCommand; +import org.openhab.binding.openthermgateway.internal.GatewayCommandCode; +import org.openhab.binding.openthermgateway.internal.Message; +import org.openhab.binding.openthermgateway.internal.OpenThermGatewayCallback; +import org.openhab.binding.openthermgateway.internal.OpenThermGatewayConfiguration; +import org.openhab.binding.openthermgateway.internal.OpenThermGatewayConnector; +import org.openhab.binding.openthermgateway.internal.OpenThermGatewaySocketConnector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link OpenThermGatewayHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public class OpenThermGatewayHandler extends BaseThingHandler implements OpenThermGatewayCallback { + + private final Logger logger = LoggerFactory.getLogger(OpenThermGatewayHandler.class); + + private @Nullable OpenThermGatewayConfiguration config; + + private @Nullable OpenThermGatewayConnector connector; + + private boolean connecting = false; + + private boolean explicitDisconnect = false; + + public OpenThermGatewayHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + logger.debug("Initializing OpenTherm Gateway handler for uid '{}'", getThing().getUID()); + + updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, "Initializing"); + + config = getConfigAs(OpenThermGatewayConfiguration.class); + + connect(); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + logger.debug("Received channel: {}, command: {}", channelUID, command); + + if (!(command instanceof RefreshType)) { + String channel = channelUID.getId(); + String code = getGatewayCodeFromChannel(channel); + + GatewayCommand gatewayCommand = null; + + if (command instanceof QuantityType) { + QuantityType quantityType = ((QuantityType) command).toUnit(SIUnits.CELSIUS); + + if (quantityType != null) { + double value = quantityType.doubleValue(); + gatewayCommand = GatewayCommand.parse(code, Double.toString(value)); + } + } + + if (gatewayCommand == null) { + gatewayCommand = GatewayCommand.parse(code, command.toFullString()); + } + + if (checkConnection()) { + @Nullable + OpenThermGatewayConnector conn = connector; + + if (conn != null) { + conn.sendCommand(gatewayCommand); + } + } + } + } + + @Override + public void connecting() { + connecting = true; + updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, "Connecting"); + } + + @Override + public void connected() { + connecting = false; + updateStatus(ThingStatus.ONLINE); + } + + @Override + public void disconnected() { + @Nullable + OpenThermGatewayConnector conn = connector; + + @Nullable + OpenThermGatewayConfiguration conf = config; + + connecting = false; + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "Disconnected"); + + // retry connection if disconnect is not explicitly requested + if (conf != null && !explicitDisconnect && conf.connectionRetryInterval > 0) { + scheduler.schedule(() -> { + if (conn != null && !connecting && !conn.isConnected()) { + connect(); + } + }, conf.connectionRetryInterval, TimeUnit.SECONDS); + } + } + + @Override + public void receiveMessage(Message message) { + if (DataItemGroup.dataItemGroups.containsKey(message.getID())) { + DataItem[] dataItems = DataItemGroup.dataItemGroups.get(message.getID()); + + for (DataItem dataItem : dataItems) { + String channelId = dataItem.getSubject(); + + if (!OpenThermGatewayBindingConstants.SUPPORTED_CHANNEL_IDS.contains(channelId)) { + continue; + } + + State state = null; + + switch (dataItem.getDataType()) { + case FLAGS: + state = OnOffType.from(message.getBit(dataItem.getByteType(), dataItem.getBitPos())); + break; + case UINT8: + case UINT16: + state = new DecimalType(message.getUInt(dataItem.getByteType())); + break; + case INT8: + case INT16: + state = new DecimalType(message.getInt(dataItem.getByteType())); + break; + case FLOAT: + float value = message.getFloat(); + @Nullable + Unit unit = dataItem.getUnit(); + state = (unit == null) ? new DecimalType(value) : new QuantityType<>(value, unit); + break; + case DOWTOD: + break; + } + + if (state != null) { + logger.debug("Received update for channel '{}': {}", channelId, state); + updateState(channelId, state); + } + } + } + } + + @Override + public void handleRemoval() { + logger.debug("Removing OpenTherm Gateway handler"); + disconnect(); + super.handleRemoval(); + } + + @Override + public void dispose() { + disconnect(); + super.dispose(); + } + + private boolean checkConnection() { + @Nullable + OpenThermGatewayConnector conn = connector; + + if (conn != null && conn.isConnected()) { + return true; + } + + return connect(); + } + + private boolean connect() { + @Nullable + OpenThermGatewayConfiguration conf = config; + + disconnect(); + + if (conf != null) { + logger.debug("Starting OpenTherm Gateway connector"); + + explicitDisconnect = false; + + connector = new OpenThermGatewaySocketConnector(this, conf.ipaddress, conf.port); + + Thread thread = new Thread(connector, "OpenTherm Gateway Binding - socket listener thread"); + thread.setDaemon(true); + thread.start(); + + logger.debug("OpenTherm Gateway connector started"); + + return true; + } + + return false; + } + + private void disconnect() { + @Nullable + OpenThermGatewayConnector conn = connector; + + if (conn != null) { + if (conn.isConnected()) { + logger.debug("Stopping OpenTherm Gateway connector"); + + explicitDisconnect = true; + conn.stop(); + } + + connector = null; + } + } + + private @Nullable String getGatewayCodeFromChannel(String channel) throws IllegalArgumentException { + switch (channel) { + case OpenThermGatewayBindingConstants.CHANNEL_OVERRIDE_SETPOINT_TEMPORARY: + return GatewayCommandCode.TemperatureTemporary; + case OpenThermGatewayBindingConstants.CHANNEL_OVERRIDE_SETPOINT_CONSTANT: + return GatewayCommandCode.TemperatureConstant; + case OpenThermGatewayBindingConstants.CHANNEL_OUTSIDE_TEMPERATURE: + return GatewayCommandCode.TemperatureOutside; + case OpenThermGatewayBindingConstants.CHANNEL_OVERRIDE_DHW_SETPOINT: + return GatewayCommandCode.SetpointWater; + case OpenThermGatewayBindingConstants.CHANNEL_SEND_COMMAND: + return null; + default: + throw new IllegalArgumentException(String.format("Unknown channel %s", channel)); + } + } +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/ByteType.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/ByteType.java new file mode 100644 index 0000000000000..301500051da75 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/ByteType.java @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +/** + * The {@link ByteType} enum specifies whether the upper, lower or both bytes are used + * + * @author Arjen Korevaar - Initial contribution + */ +public enum ByteType { + HIGHBYTE, + LOWBYTE, + BOTH +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataItem.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataItem.java new file mode 100644 index 0000000000000..4eb8ca33111d7 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataItem.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import javax.measure.Unit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link DataItem} holds the internal OpenTherm message and meta data. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public class DataItem { + private int id; + private Msg msg; + private ByteType byteType; + private DataType dataType; + private int bitpos; + private String subject; + private @Nullable Unit unit; + + public int getID() { + return id; + } + + public Msg getMsg() { + return msg; + } + + public ByteType getByteType() { + return this.byteType; + } + + public DataType getDataType() { + return dataType; + } + + public int getBitPos() { + return bitpos; + } + + public String getSubject() { + return subject; + } + + public @Nullable Unit getUnit() { + return unit; + } + + public DataItem(int id, Msg msg, ByteType byteType, DataType dataType, int bit, String subject) { + this.id = id; + this.msg = msg; + this.byteType = byteType; + this.dataType = dataType; + this.bitpos = bit; + this.subject = subject; + } + + public DataItem(int id, Msg msg, ByteType byteType, DataType dataType, int bit, String subject, Unit unit) { + this(id, msg, byteType, dataType, bit, subject); + this.unit = unit; + } +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataItemGroup.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataItemGroup.java new file mode 100644 index 0000000000000..6026b8c82e5a2 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataItemGroup.java @@ -0,0 +1,178 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.unit.SIUnits; + +/** + * The {@link DataItemGroup} represents a list of all possible DataItem messages within the OpenTherm specification. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public class DataItemGroup { + + public static final Map dataItemGroups = createDataItemGroups(); + + private static Map createDataItemGroups() { + HashMap g = new HashMap<>(); + + g.put(0, new DataItem[] { new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "ch_enable"), + new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 1, "dhw_enable"), + new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 2, "cooling_enabled"), + new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 3, "otc_active"), + new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 4, "ch2_enable"), + new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 5, "0x00:5"), + new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 6, "0x00:6"), + new DataItem(0, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 7, "0x00:7"), + new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 0, "fault"), + new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 1, "ch_mode"), + new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 2, "dhw_mode"), + new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 3, "flame"), + new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 4, "cooling"), + new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 5, "ch2E"), + new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 6, "diag"), + new DataItem(0, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 7, "0x00:7") }); + g.put(1, new DataItem[] { + new DataItem(1, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "controlsetpoint", SIUnits.CELSIUS) }); + g.put(2, new DataItem[] { new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 0, "0x02:0"), + new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 1, "0x02:1"), + new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 2, "0x02:2"), + new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 3, "0x02:3"), + new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 4, "0x02:4"), + new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 5, "0x02:5"), + new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 6, "0x02:6"), + new DataItem(2, Msg.WRITE, ByteType.HIGHBYTE, DataType.FLAGS, 7, "0x02:7"), + new DataItem(2, Msg.WRITE, ByteType.LOWBYTE, DataType.UINT8, 0, "mastermemberid") }); + g.put(3, new DataItem[] { new DataItem(3, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "dhwpresent"), + new DataItem(3, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 1, "controltype"), + new DataItem(3, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 2, "coolingsupport"), + new DataItem(3, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 3, "dhwconfig"), + new DataItem(3, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 4, "masterlowoff"), + new DataItem(3, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 5, "ch2present"), + new DataItem(3, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 6, "0x03:6"), + new DataItem(3, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 7, "0x03:7"), + new DataItem(3, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "slavememberid") }); + g.put(4, new DataItem[] { new DataItem(4, Msg.WRITE, ByteType.HIGHBYTE, DataType.UINT8, 0, "commandcode"), + new DataItem(4, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "commandresponse") }); + g.put(5, new DataItem[] { new DataItem(5, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "servicerequest"), + new DataItem(5, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 1, "lockout-reset"), + new DataItem(5, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 2, "lowwaterpress"), + new DataItem(5, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 3, "gasflamefault"), + new DataItem(5, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 4, "airpressfault"), + new DataItem(5, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 5, "waterovtemp"), + new DataItem(5, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 6, "0x05:6"), + new DataItem(5, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 7, "0x05:7"), + new DataItem(5, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "oemfaultcode") }); + g.put(6, new DataItem[] { new DataItem(6, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 0, "0x06:l0"), + new DataItem(6, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 1, "0x06:l1"), + new DataItem(6, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 2, "0x06:l2"), + new DataItem(6, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 3, "0x06:l3"), + new DataItem(6, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 4, "0x06:l4"), + new DataItem(6, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 5, "0x06:l5"), + new DataItem(6, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 6, "0x06:l6"), + new DataItem(6, Msg.READ, ByteType.LOWBYTE, DataType.FLAGS, 7, "0x06:l7"), + new DataItem(6, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "0x06:h0"), + new DataItem(6, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 1, "0x06:h1"), + new DataItem(6, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 2, "0x06:h2"), + new DataItem(6, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 3, "0x06:h3"), + new DataItem(6, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 4, "0x06:h4"), + new DataItem(6, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 5, "0x06:h5"), + new DataItem(6, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 6, "0x06:h6"), + new DataItem(6, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 7, "0x06:h7") }); + g.put(7, new DataItem[] { new DataItem(7, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "0x07") }); + g.put(8, new DataItem[] { new DataItem(8, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "controlsetpoint2") }); + g.put(9, new DataItem[] { new DataItem(9, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "overridesetpoint") }); + g.put(10, new DataItem[] { new DataItem(10, Msg.WRITE, ByteType.HIGHBYTE, DataType.UINT8, 0, "0x0a:h"), + new DataItem(10, Msg.WRITE, ByteType.LOWBYTE, DataType.UINT8, 0, "0x0a:l") }); + g.put(11, new DataItem[] { new DataItem(11, Msg.READWRITE, ByteType.HIGHBYTE, DataType.UINT8, 0, "tspindex"), + new DataItem(11, Msg.READWRITE, ByteType.LOWBYTE, DataType.UINT8, 0, "tspvalue") }); + g.put(12, new DataItem[] { new DataItem(12, Msg.READ, ByteType.HIGHBYTE, DataType.UINT8, 0, "0x0c:h"), + new DataItem(12, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "0x0c:l") }); + g.put(13, new DataItem[] { new DataItem(13, Msg.READ, ByteType.HIGHBYTE, DataType.UINT8, 0, "0x0d:h"), + new DataItem(13, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "0x0d:l") }); + g.put(14, new DataItem[] { new DataItem(14, Msg.READ, ByteType.LOWBYTE, DataType.FLOAT, 0, "maxrelmdulevel") }); + g.put(15, new DataItem[] { new DataItem(15, Msg.READ, ByteType.HIGHBYTE, DataType.UINT8, 0, "maxcapkw"), + new DataItem(15, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "maxcapprc") }); + g.put(16, new DataItem[] { + new DataItem(16, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "roomsetpoint", SIUnits.CELSIUS) }); + g.put(17, new DataItem[] { new DataItem(17, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "modulevel") }); + g.put(18, new DataItem[] { new DataItem(18, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "waterpressure") }); + g.put(19, new DataItem[] { new DataItem(19, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "dhwflow") }); + g.put(20, new DataItem[] { new DataItem(20, Msg.READWRITE, ByteType.BOTH, DataType.DOWTOD, 0, "dowtod") }); + g.put(21, new DataItem[] { new DataItem(21, Msg.READWRITE, ByteType.HIGHBYTE, DataType.UINT8, 0, "month"), + new DataItem(21, Msg.READWRITE, ByteType.LOWBYTE, DataType.UINT8, 0, "dom") }); + g.put(22, new DataItem[] { new DataItem(22, Msg.READWRITE, ByteType.LOWBYTE, DataType.UINT8, 0, "year") }); + g.put(23, new DataItem[] { new DataItem(23, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "setpointch2") }); + g.put(24, new DataItem[] { + new DataItem(24, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "roomtemp", SIUnits.CELSIUS) }); + g.put(25, new DataItem[] { + new DataItem(25, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "flowtemp", SIUnits.CELSIUS) }); + g.put(26, new DataItem[] { + new DataItem(26, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "dhwtemp", SIUnits.CELSIUS) }); + g.put(27, new DataItem[] { + new DataItem(27, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "outsidetemp", SIUnits.CELSIUS) }); + g.put(28, new DataItem[] { + new DataItem(28, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "returntemp", SIUnits.CELSIUS) }); + g.put(29, new DataItem[] { new DataItem(29, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "solstortemp") }); + g.put(30, new DataItem[] { new DataItem(30, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "solcolltemp") }); + g.put(31, new DataItem[] { new DataItem(31, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "flowtemp2") }); + g.put(32, new DataItem[] { new DataItem(32, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "dhw2temp") }); + g.put(33, new DataItem[] { new DataItem(33, Msg.READ, ByteType.BOTH, DataType.INT16, 0, "exhausttemp") }); + g.put(48, new DataItem[] { new DataItem(48, Msg.READ, ByteType.HIGHBYTE, DataType.INT8, 0, "tdhwsetu"), + new DataItem(48, Msg.READ, ByteType.LOWBYTE, DataType.INT8, 0, "tdhwsetl") }); + g.put(49, new DataItem[] { new DataItem(49, Msg.READ, ByteType.HIGHBYTE, DataType.INT8, 0, "maxchu"), + new DataItem(49, Msg.READ, ByteType.LOWBYTE, DataType.INT8, 0, "maxchl") }); + g.put(50, new DataItem[] { new DataItem(50, Msg.READ, ByteType.HIGHBYTE, DataType.INT8, 0, "otcu"), + new DataItem(50, Msg.READ, ByteType.LOWBYTE, DataType.INT8, 0, "otcl") }); + g.put(56, new DataItem[] { + new DataItem(56, Msg.READWRITE, ByteType.BOTH, DataType.FLOAT, 0, "tdhwset", SIUnits.CELSIUS) }); + g.put(57, new DataItem[] { new DataItem(57, Msg.READWRITE, ByteType.BOTH, DataType.FLOAT, 0, "tchmax") }); + g.put(58, new DataItem[] { new DataItem(58, Msg.READWRITE, ByteType.BOTH, DataType.FLOAT, 0, "otchcratio") }); + g.put(100, + new DataItem[] { new DataItem(100, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 0, "rof0"), + new DataItem(100, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 1, "rof1"), + new DataItem(100, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 2, "rof2"), + new DataItem(100, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 3, "rof3"), + new DataItem(100, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 4, "rof4"), + new DataItem(100, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 5, "rof5"), + new DataItem(100, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 6, "rof6"), + new DataItem(100, Msg.READ, ByteType.HIGHBYTE, DataType.FLAGS, 7, "rof7") }); + g.put(115, new DataItem[] { new DataItem(115, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "oemdiagcode") }); + g.put(116, new DataItem[] { new DataItem(116, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "burnerstarts") }); + g.put(117, new DataItem[] { new DataItem(117, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "chpumpstarts") }); + g.put(118, new DataItem[] { new DataItem(118, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "dhwpvstarts") }); + g.put(119, + new DataItem[] { new DataItem(119, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "dhwburnerstarts") }); + g.put(120, new DataItem[] { new DataItem(120, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "burnerhours") }); + g.put(121, new DataItem[] { new DataItem(121, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "chpumphours") }); + g.put(122, new DataItem[] { new DataItem(122, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "dhwpvhours") }); + g.put(123, new DataItem[] { new DataItem(123, Msg.READ, ByteType.BOTH, DataType.UINT16, 0, "dhwburnerhours") }); + g.put(124, + new DataItem[] { new DataItem(124, Msg.WRITE, ByteType.BOTH, DataType.FLOAT, 0, "masterotversion") }); + g.put(125, new DataItem[] { new DataItem(125, Msg.READ, ByteType.BOTH, DataType.FLOAT, 0, "slaveotversion") }); + g.put(126, + new DataItem[] { + new DataItem(126, Msg.WRITE, ByteType.HIGHBYTE, DataType.UINT8, 0, "masterproducttype"), + new DataItem(126, Msg.WRITE, ByteType.LOWBYTE, DataType.UINT8, 0, "masterproductversion") }); + g.put(127, + new DataItem[] { new DataItem(127, Msg.READ, ByteType.HIGHBYTE, DataType.UINT8, 0, "slaveproducttype"), + new DataItem(127, Msg.READ, ByteType.LOWBYTE, DataType.UINT8, 0, "slaveproductversion") }); + + return g; + } +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataType.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataType.java new file mode 100644 index 0000000000000..13c7bb1aa505b --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/DataType.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +/** + * The {@link DataType} enum indicates the type of data from a DataItem. + * + * @author Arjen Korevaar - Initial contribution + */ +public enum DataType { + FLAGS, + UINT8, + INT8, + FLOAT, + UINT16, + INT16, + DOWTOD +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/GatewayCommand.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/GatewayCommand.java new file mode 100644 index 0000000000000..6a32acb0bf49d --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/GatewayCommand.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link GatewayCommand} is used to validate and match commands send through the binding + * to the OpenTherm gateway device. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public class GatewayCommand { + private static final Map supportedCommands = getSupportedCommands(); + + private String code; + private String validationSet; + private String message; + + public String getCode() { + return code; + } + + public String getMessage() { + return this.message; + } + + public String getValidationSet() { + return validationSet; + } + + public String toFullString() { + return this.code + "=" + this.message; + } + + private GatewayCommand(String code, String message, String validationSet) throws IllegalArgumentException { + this.code = code; + this.message = message; + this.validationSet = validationSet; + + if (!validate()) { + throw new IllegalArgumentException( + String.format("Invalid value '%s' for code '%s'", this.message, this.code)); + } + } + + private boolean validate() { + if (this.validationSet.isEmpty()) { + return true; + } + + String[] validations = this.validationSet.split(","); + + for (String validation : validations) { + if (this.message.equals(validation)) { + return true; + } + } + + return false; + } + + public static GatewayCommand parse(@Nullable String code, String message) throws IllegalArgumentException { + if ((code == null || code.isEmpty()) && message.length() > 2 && message.charAt(2) == '=') { + return parse(message.substring(0, 2), message.substring(3)); + } + + if (code != null && code.length() == 2) { + String codeUpperCase = code.toUpperCase(); + + if (supportedCommands.containsKey(codeUpperCase)) { + String validateSet = supportedCommands.get(codeUpperCase); + + if (validateSet == null) { + validateSet = ""; + } + + return new GatewayCommand(codeUpperCase, message, validateSet); + } else { + throw new IllegalArgumentException(String.format("Unsupported gateway code '%s'", code.toUpperCase())); + } + } + + throw new IllegalArgumentException( + String.format("Unable to parse gateway command with code '%s' and message '%s'", code, message)); + } + + private static Map getSupportedCommands() { + Map c = new HashMap<>(); + + c.put(GatewayCommandCode.TemperatureTemporary, null); + c.put(GatewayCommandCode.TemperatureConstant, null); + c.put(GatewayCommandCode.TemperatureOutside, null); + c.put(GatewayCommandCode.SetClock, null); + c.put(GatewayCommandCode.HotWater, null); + c.put(GatewayCommandCode.PrintReport, "A,B,C,G,I,L,M,O,P,R,S,T,V,W"); + c.put(GatewayCommandCode.PrintSummary, "0,1"); + c.put(GatewayCommandCode.GateWay, "0,1,R"); + c.put(GatewayCommandCode.LedA, "R,X,T,B,O,F,H,W,C,E,M,P"); + c.put(GatewayCommandCode.LedB, "R,X,T,B,O,F,H,W,C,E,M,P"); + c.put(GatewayCommandCode.LedC, "R,X,T,B,O,F,H,W,C,E,M,P"); + c.put(GatewayCommandCode.LedD, "R,X,T,B,O,F,H,W,C,E,M,P"); + c.put(GatewayCommandCode.LedE, "R,X,T,B,O,F,H,W,C,E,M,P"); + c.put(GatewayCommandCode.LedF, "R,X,T,B,O,F,H,W,C,E,M,P"); + c.put(GatewayCommandCode.GpioA, "0,1,2,3,4,5,6,7"); + c.put(GatewayCommandCode.GpioB, "0,1,2,3,4,5,6,7"); + c.put(GatewayCommandCode.SetBack, null); + c.put(GatewayCommandCode.AddAlternative, null); + c.put(GatewayCommandCode.DeleteAlternative, null); + c.put(GatewayCommandCode.UnknownID, null); + c.put(GatewayCommandCode.KnownID, null); + c.put(GatewayCommandCode.PriorityMessage, null); + c.put(GatewayCommandCode.SetResponse, null); + c.put(GatewayCommandCode.ClearResponse, null); + c.put(GatewayCommandCode.SetpointHeating, null); + c.put(GatewayCommandCode.SetpointWater, null); + c.put(GatewayCommandCode.MaximumModulation, null); + c.put(GatewayCommandCode.ControlSetpoint, null); + c.put(GatewayCommandCode.CentralHeating, "0,1"); + c.put(GatewayCommandCode.VentilationSetpoint, null); + c.put(GatewayCommandCode.Reset, null); + c.put(GatewayCommandCode.IgnoreTransition, "0,1"); + c.put(GatewayCommandCode.OverrideHighbyte, "0,1"); + c.put(GatewayCommandCode.ForceThermostat, "0,1"); + c.put(GatewayCommandCode.VoltageReference, "0,1,2,3,4,5,6,7,8,9"); + c.put(GatewayCommandCode.DebugPointer, null); + + return c; + } +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/GatewayCommandCode.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/GatewayCommandCode.java new file mode 100644 index 0000000000000..4e35d99874251 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/GatewayCommandCode.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link GatewayCommandCode} provides a set of supported OpenTherm Gateway commands. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public class GatewayCommandCode { + public static final String TemperatureTemporary = "TT"; + public static final String TemperatureConstant = "TC"; + public static final String TemperatureOutside = "OT"; + public static final String SetClock = "ST"; + public static final String HotWater = "HW"; + public static final String PrintReport = "PR"; + public static final String PrintSummary = "PS"; + public static final String GateWay = "GW"; + public static final String LedA = "LA"; + public static final String LedB = "LB"; + public static final String LedC = "LC"; + public static final String LedD = "LD"; + public static final String LedE = "LE"; + public static final String LedF = "LF"; + public static final String GpioA = "GA"; + public static final String GpioB = "GB"; + public static final String SetBack = "SB"; + public static final String AddAlternative = "AA"; + public static final String DeleteAlternative = "DA"; + public static final String UnknownID = "UI"; + public static final String KnownID = "KI"; + public static final String PriorityMessage = "PM"; + public static final String SetResponse = "SR"; + public static final String ClearResponse = "CR"; + public static final String SetpointHeating = "SH"; + public static final String SetpointWater = "SW"; + public static final String MaximumModulation = "MM"; + public static final String ControlSetpoint = "CS"; + public static final String CentralHeating = "CH"; + public static final String VentilationSetpoint = "VS"; + public static final String Reset = "RS"; + public static final String IgnoreTransition = "IT"; + public static final String OverrideHighbyte = "OH"; + public static final String ForceThermostat = "FT"; + public static final String VoltageReference = "VR"; + public static final String DebugPointer = "DP"; +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/Message.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/Message.java new file mode 100644 index 0000000000000..fc9ce0c0a4fae --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/Message.java @@ -0,0 +1,243 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import java.util.regex.Pattern; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link Message} represent a single message received from the OpenTherm Gateway. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public class Message { + + private static final Pattern messagePattern = Pattern.compile("[TBRA]{1}[A-F0-9]{8}"); + + /* + * The code field is not part of OpenTherm specification, but added by OpenTherm Gateway. + * It can be any of the following: + * + * T: Message received from the thermostat + * B: Message received from the boiler + * R: Request sent to the boiler + * A: Response returned to the thermostat + * E: Parity or stop bit error + */ + private String code; + private MessageType messageType; + private int id; + private String data; + + public String getCode() { + return this.code; + } + + public MessageType getMessageType() { + return messageType; + } + + public int getID() { + return id; + } + + public @Nullable String getData(ByteType byteType) { + if (this.data.length() == 4) { + switch (byteType) { + case HIGHBYTE: + return this.data.substring(0, 2); + case LOWBYTE: + return this.data.substring(2, 4); + case BOTH: + return this.data; + } + } + + return null; + } + + public boolean getBit(ByteType byteType, int pos) { + @Nullable + String data = getData(byteType); + + if (data != null) { + // First parse the hex value to an integer + int parsed = Integer.parseInt(data, 16); + + // Then right shift it pos positions so that the required bit is at the front + // and then apply a bitmask of 00000001 (1) + return ((parsed >> pos) & 1) == 1; + } + + return false; + } + + public int getUInt(ByteType byteType) { + @Nullable + String data = getData(byteType); + + if (data != null) { + return Integer.parseInt(data, 16); + } + + return 0; + } + + public int getInt(ByteType byteType) { + @Nullable + String data = getData(byteType); + + if (data != null) { + return parseSignedInteger(data); + } + + return 0; + } + + public float getFloat() { + // f8.8, two's complement + @Nullable + String data = getData(ByteType.BOTH); + + if (data != null) { + long value = Long.parseLong(data, 16); + + // left padded with zeros + String binary = String.format("%16s", Long.toBinaryString(value)).replace(' ', '0'); + + if (binary.charAt(0) == '1') { + // negative value + + String inverted = invertBinary(binary); + + value = Long.parseLong(inverted, 2); + value = value + 1; + value = value * -1; + } + + // divide by 2^8 = 256 + return (float) value / 256; + } + + return 0; + } + + public boolean overrides(@Nullable Message other) { + // If the message is a Request sent to the boiler or an Answer returned to the + // thermostat, and it's ID is equal to the previous message, then this is an + // override sent by the OpenTherm Gateway + return other != null && this.getID() == other.getID() + && ("R".equals(this.getCode()) || "A".equals(this.getCode())); + } + + @Override + public String toString() { + return String.format("%s - %s - %s", this.code, this.id, this.data); + } + + public Message(String code, MessageType messageType, int id, String data) { + this.code = code; + this.messageType = messageType; + this.id = id; + this.data = data; + } + + public static @Nullable Message parse(String message) { + if (messagePattern.matcher(message).matches()) { + // For now, only parse TBRA codes + String code = message.substring(0, 1); + MessageType messageType = getMessageType(message.substring(1, 3)); + int id = Integer.valueOf(message.substring(3, 5), 16); + String data = message.substring(5); + + return new Message(code, messageType, id, data); + } + + return null; + } + + private static MessageType getMessageType(String value) { + // First parse the hex value to an integer + int integer = Integer.parseInt(value, 16); + + // Then right shift it 4 bits so that the message type bits are at the front + int shifted = integer >> 4; + + // Then mask it with 00000111 (7), so that we only get the first 3 bits, + // effectively cutting off the parity bit. + int cutoff = shifted & 7; + + switch (cutoff) { + case 0: // 000 + return MessageType.READDATA; + case 1: // 001 + return MessageType.WRITEDATA; + case 2: // 010 + return MessageType.INVALIDDATA; + case 3: // 011 + return MessageType.RESERVED; + case 4: // 100 + return MessageType.READACK; + case 5: // 101 + return MessageType.WRITEACK; + case 6: // 110 + return MessageType.DATAINVALID; + case 7: // 111 + default: + return MessageType.UNKNOWNDATAID; + } + } + + private int parseSignedInteger(String data) { + // First parse the hex value to an unsigned integer value + int result = Integer.parseInt(data, 16); + + if (data.length() == 4) { + // This is a two byte value, apply a bitmask of 01111111 11111111 (32767) to cut + // off the sign bit + result = result & 32767; + + // Then apply a bitmask of 10000000 00000000 (32768) to check the sign bit + if ((result & 32768) == 32768) { + // If the sign is 1000000 00000000 (32768) then it's a negative + result = -32768 + result; + } + } else { + // This is a one byte value, apply a bitmask of 01111111 (127), to cut off the + // sign bit + result = result & 127; + + // Then apply a bitmask of 10000000 (128) to check the sign bit + if ((result & 128) == 128) { + // If the sign is 1000000 (128) then it's a negative + result = -128 + result; + } + } + + return result; + } + + private String invertBinary(String value) { + // There is probably a better solution, but for now this works + String result = value; + + result = result.replace('1', 'X'); + result = result.replace('0', '1'); + result = result.replace('X', '0'); + + return result; + } +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/MessageType.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/MessageType.java new file mode 100644 index 0000000000000..8a6abc97d5984 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/MessageType.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +/** + * The {@link MessageType} indicates the type of message received by the OpenTherm Gateway, based + * on the OpenTherm specification. + * + * @author Arjen Korevaar - Initial contribution + */ +public enum MessageType { + READDATA, // 000 + READACK, // 100 + WRITEDATA, // 001 + WRITEACK, // 101 + INVALIDDATA, // 010 + DATAINVALID, // 110 + RESERVED, // 011 + UNKNOWNDATAID // 111 +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/Msg.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/Msg.java new file mode 100644 index 0000000000000..a910f5824970b --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/Msg.java @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +/** + * The {@link Msg} flag is used to indicate whether the message is sent for Reading, Writing + * or both, based on the OpenTherm specification. + * + * @author Arjen Korevaar - Initial contribution + */ +public enum Msg { + READ, + WRITE, + READWRITE +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayCallback.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayCallback.java new file mode 100644 index 0000000000000..3a1b486c93145 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayCallback.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link OpenThermGatewayCallback} is used as a callback interface by a connector to signal status + * and relay incoming messages to be processed by the binding. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public interface OpenThermGatewayCallback { + void connecting(); + + void connected(); + + void disconnected(); + + void receiveMessage(Message message); +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayConfiguration.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayConfiguration.java new file mode 100644 index 0000000000000..80a46fd24a630 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayConfiguration.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link OpenThermGatewayConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public class OpenThermGatewayConfiguration { + + public String ipaddress = ""; + + public int port = 0; + + public int connectionRetryInterval = 60; +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayConnector.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayConnector.java new file mode 100644 index 0000000000000..dc99615df56f8 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayConnector.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link OpenThermGatewayConnector} interface is used to allow multiple types of connectors + * to be implemented and used to connect to the OpenTherm Gateway. + * + * @author Arjen Korevaar - Initial contribution + */ +@NonNullByDefault +public interface OpenThermGatewayConnector extends Runnable { + void sendCommand(GatewayCommand command); + + boolean isConnected(); + + void stop(); +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayHandlerFactory.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayHandlerFactory.java new file mode 100644 index 0000000000000..2195b973fb2f2 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewayHandlerFactory.java @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.openthermgateway.OpenThermGatewayBindingConstants; +import org.openhab.binding.openthermgateway.handler.OpenThermGatewayHandler; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link OpenThermGatewayHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Arjen Korevaar - Initial contribution + */ +@Component(service = ThingHandlerFactory.class, configurationPid = "binding.openthermgateway") +@NonNullByDefault +public class OpenThermGatewayHandlerFactory extends BaseThingHandlerFactory { + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return thingTypeUID.equals(OpenThermGatewayBindingConstants.MAIN_THING_TYPE); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(OpenThermGatewayBindingConstants.MAIN_THING_TYPE)) { + return new OpenThermGatewayHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewaySocketConnector.java b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewaySocketConnector.java new file mode 100644 index 0000000000000..dd8d80b574e02 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/java/org/openhab/binding/openthermgateway/internal/OpenThermGatewaySocketConnector.java @@ -0,0 +1,219 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.openthermgateway.internal; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.AbstractMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.types.State; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link OpenThermGatewaySocketConnector} is responsible for handling the socket connection + * + * @author Arjen Korevaar - Initial contribution + * @author Arjan Mels - Improved robustness by re-sending commands, handling all message types (not only Boiler) + */ +@NonNullByDefault +public class OpenThermGatewaySocketConnector implements OpenThermGatewayConnector { + private static final int COMMAND_RESPONSE_TIME_MILLISECONDS = 100; + private static final int COMMAND_TIMEOUT_MILLISECONDS = 5000; + + private final Logger logger = LoggerFactory.getLogger(OpenThermGatewaySocketConnector.class); + + private final OpenThermGatewayCallback callback; + private final String ipaddress; + private final int port; + + private @Nullable PrintWriter writer; + + private volatile boolean stopping; + private boolean connected; + + private Map> pendingCommands = new ConcurrentHashMap<>(); + + public OpenThermGatewaySocketConnector(OpenThermGatewayCallback callback, String ipaddress, int port) { + this.callback = callback; + this.ipaddress = ipaddress; + this.port = port; + } + + @Override + public void run() { + stopping = false; + connected = false; + + logger.debug("Connecting OpenThermGatewaySocketConnector to {}:{}", this.ipaddress, this.port); + + callback.connecting(); + + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress(this.ipaddress, this.port), COMMAND_TIMEOUT_MILLISECONDS); + socket.setSoTimeout(COMMAND_TIMEOUT_MILLISECONDS); + + connected = true; + + callback.connected(); + + logger.debug("OpenThermGatewaySocketConnector connected"); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + PrintWriter wrt = new PrintWriter(socket.getOutputStream(), true)) { + // Make writer accessible on class level + writer = wrt; + + sendCommand(GatewayCommand.parse(GatewayCommandCode.PrintReport, "A")); + // Set the OTGW to report every message it receives and transmits + sendCommand(GatewayCommand.parse(GatewayCommandCode.PrintSummary, "0")); + + while (!stopping && !Thread.currentThread().isInterrupted()) { + @Nullable + String message = reader.readLine(); + + if (message != null) { + handleMessage(message); + } else { + logger.debug("Connection closed by OpenTherm Gateway"); + break; + } + } + + logger.debug("Stopping OpenThermGatewaySocketConnector"); + } finally { + connected = false; + + logger.debug("OpenThermGatewaySocketConnector disconnected"); + callback.disconnected(); + } + } catch (IOException ex) { + logger.warn("Unable to connect to the OpenTherm Gateway.", ex); + } + } + + @Override + public void stop() { + logger.debug("Stopping OpenThermGatewaySocketConnector"); + stopping = true; + } + + @Override + public boolean isConnected() { + return connected; + } + + @Override + public void sendCommand(GatewayCommand command) { + @Nullable + PrintWriter wrtr = writer; + + String msg = command.toFullString(); + + pendingCommands.put(command.getCode(), + new AbstractMap.SimpleImmutableEntry<>(System.currentTimeMillis(), command)); + + if (connected) { + logger.debug("Sending message: {}", msg); + if (wrtr != null) { + wrtr.print(msg + "\r\n"); + wrtr.flush(); + } + } else { + logger.debug("Unable to send message: {}. OpenThermGatewaySocketConnector is not connected.", msg); + } + } + + private void handleMessage(String message) { + if (message.length() > 2 && message.charAt(2) == ':') { + String code = message.substring(0, 2); + String value = message.substring(3); + + logger.debug("Received command confirmation: {}: {}", code, value); + pendingCommands.remove(code); + return; + } + + long currentTime = System.currentTimeMillis(); + + for (Entry timeAndCommand : pendingCommands.values()) { + long responseTime = timeAndCommand.getKey() + COMMAND_RESPONSE_TIME_MILLISECONDS; + long timeoutTime = timeAndCommand.getKey() + COMMAND_TIMEOUT_MILLISECONDS; + + if (currentTime > responseTime && currentTime <= timeoutTime) { + logger.debug("Resending command: {}", timeAndCommand.getValue()); + sendCommand(timeAndCommand.getValue()); + } else if (currentTime > timeoutTime) { + pendingCommands.remove(timeAndCommand.getValue().getCode()); + } + } + + Message msg = Message.parse(message); + + if (msg == null) { + logger.trace("Received message: {}, (unknown)", message); + return; + } else { + logger.trace("Received message: {}, {} {} {}", message, msg.getID(), msg.getCode(), msg.getMessageType()); + } + + if (DataItemGroup.dataItemGroups.containsKey(msg.getID())) { + DataItem[] dataItems = DataItemGroup.dataItemGroups.get(msg.getID()); + + for (DataItem dataItem : dataItems) { + State state = null; + + switch (dataItem.getDataType()) { + case FLAGS: + state = OnOffType.from(msg.getBit(dataItem.getByteType(), dataItem.getBitPos())); + break; + case UINT8: + case UINT16: + state = new DecimalType(msg.getUInt(dataItem.getByteType())); + break; + case INT8: + case INT16: + state = new DecimalType(msg.getInt(dataItem.getByteType())); + break; + case FLOAT: + state = new DecimalType(msg.getFloat()); + break; + case DOWTOD: + break; + } + + logger.trace(" Data: {} {} {} {}", dataItem.getID(), dataItem.getSubject(), dataItem.getDataType(), + state == null ? "" : state); + } + } + + if (msg.getMessageType() == MessageType.READACK || msg.getMessageType() == MessageType.WRITEDATA) { + receiveMessage(msg); + } + } + + private void receiveMessage(Message message) { + callback.receiveMessage(message); + } +} diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..b7b62803283d5 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/binding/binding.xml @@ -0,0 +1,14 @@ + + + + OpenTherm Gateway Binding + + This is the binding for the OpenTherm Gateway, designed by Schelte Bron. + For more information about the + OpenTherm Gateway please see http://otgw.tclcode.com/ + + Arjen Korevaar + + diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/config/config.xml new file mode 100644 index 0000000000000..db806e80781c0 --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/config/config.xml @@ -0,0 +1,33 @@ + + + + + + + Connection settings. + + + + + The hostname or IP address to connect to the OpenTherm Gateway. + network-address + + + + + The port used to connect to the OpenTherm Gateway. + + + + + The interval in seconds to retry connecting (0 = disabled). + 60 + + + + + diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/thing/channels.xml new file mode 100644 index 0000000000000..74c18b2ecd62f --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/thing/channels.xml @@ -0,0 +1,214 @@ + + + + + Number:Temperature + + Current sensed room temperature + Temperature + + + + + Number:Temperature + + Current room temperature setpoint + Temperature + + + + + Number:Temperature + + Temporary override room temperature setpoint + Temperature + + + + + Number:Temperature + + Constant override room temperature setpoint + Temperature + + + + + Number:Temperature + + Central heating water setpoint + Temperature + + + + + Number:Temperature + + Domestic hot water temperature + Temperature + + + + + Number:Temperature + + Domestic hot water temperature setpoint + Temperature + + + + + Number:Temperature + + Domestic hot water temperature setpoint override + Temperature + + + + + Number:Temperature + + Boiler water temperature + Temperature + + + + + Number:Temperature + + Return water temperature + Temperature + + + + + Number:Temperature + + Outside temperature + Temperature + + + + + Number:Dimensionless + + Central heating water pressure + + + + + Switch + + Central heating enabled + + + + + Switch + + Central heating active + + + + + Switch + + Domestic hot water enabled + + + + + Switch + + Domestic hot water active + + + + + Switch + + Burner active + + + + + Number:Dimensionless + + Relative modulation level + + + + + Number:Dimensionless + + Maximum relative modulation level + + + + + Switch + + Fault indication + + + + + Switch + + Service required + + + + + Switch + + Lockout-reset enabled + + + + + Switch + + Low water pressure fault + + + + + Switch + + Gas or flame fault + + + + + Switch + + Air pressure fault + + + + + Switch + + Water over-temperature fault + + + + + Number:Dimensionless + + OEM fault code + + + + + String + + Channel to send commands to the OpenTherm Gateway device + + + + diff --git a/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/thing/otgw.xml b/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/thing/otgw.xml new file mode 100644 index 0000000000000..c0f53c04fabaa --- /dev/null +++ b/bundles/org.openhab.binding.openthermgateway/src/main/resources/ESH-INF/thing/otgw.xml @@ -0,0 +1,45 @@ + + + + + OpenTherm Gateway binding + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0.2 + + + + + diff --git a/bundles/org.openhab.binding.openuv/pom.xml b/bundles/org.openhab.binding.openuv/pom.xml index ee6b2525b4c15..91697115ac9fc 100644 --- a/bundles/org.openhab.binding.openuv/pom.xml +++ b/bundles/org.openhab.binding.openuv/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.openuv diff --git a/bundles/org.openhab.binding.openuv/src/main/feature/feature.xml b/bundles/org.openhab.binding.openuv/src/main/feature/feature.xml index 5edc141761f29..a6b918f8b7a20 100644 --- a/bundles/org.openhab.binding.openuv/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.openuv/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.openuv/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.openuv/${project.version} + diff --git a/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/OpenUVHandlerFactory.java b/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/OpenUVHandlerFactory.java index 9d867ef10105d..6c7d9f00311f1 100644 --- a/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/OpenUVHandlerFactory.java +++ b/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/OpenUVHandlerFactory.java @@ -75,5 +75,4 @@ private void registerOpenUVDiscoveryService(OpenUVBridgeHandler bridgeHandler) { bridgeHandler.getDiscoveryServiceRegs().put(bridgeHandler.getThing().getUID(), bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>())); } - } diff --git a/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/discovery/OpenUVDiscoveryService.java b/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/discovery/OpenUVDiscoveryService.java index 415fa17fcf263..a98540af3e158 100644 --- a/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/discovery/OpenUVDiscoveryService.java +++ b/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/discovery/OpenUVDiscoveryService.java @@ -117,5 +117,4 @@ protected void stopBackgroundDiscovery() { } } } - } diff --git a/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/json/OpenUVResult.java b/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/json/OpenUVResult.java index b9bdbc1b5faf6..f691998a5e578 100644 --- a/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/json/OpenUVResult.java +++ b/bundles/org.openhab.binding.openuv/src/main/java/org/openhab/binding/openuv/internal/json/OpenUVResult.java @@ -69,5 +69,4 @@ public State getOzoneTime() { public SafeExposureTime getSafeExposureTime() { return safeExposureTime; } - } diff --git a/bundles/org.openhab.binding.openuv/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.openuv/src/main/resources/ESH-INF/binding/binding.xml index 25cfa8110aa42..02f9689a437f3 100644 --- a/bundles/org.openhab.binding.openuv/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.openuv/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + OpenUV Binding Global Real-Time UV Index Forecast API diff --git a/bundles/org.openhab.binding.openuv/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.openuv/src/main/resources/ESH-INF/thing/thing-types.xml index 92ab9e878cf28..51ed38d855544 100644 --- a/bundles/org.openhab.binding.openuv/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.openuv/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -7,7 +8,8 @@ - Bridge to the OpenUV Project API. In order to receive the data, you must register an account on https://www.openuv.io/auth/google and get your API token. + Bridge to the OpenUV Project API. In order to receive the data, you must register an account on + https://www.openuv.io/auth/google and get your API token. @@ -23,27 +25,27 @@ - + - + - Provides various UV data from the OpenUV Project for a given location. + Provides various UV data from the OpenUV Project for a given location. - - - - - - - - - - + + + + + + + + + + - + location @@ -59,40 +61,40 @@ - + Number UV Index - + Number Max UV Index for the day (at solar noon) - + Number:ArealDensity Ozone level from OMI data - + DateTime Latest OMI ozone update time - + DateTime Max UV Index time (solar noon) - + @@ -135,9 +137,9 @@ Number:Angle The elevation of the sun - + - + trigger @@ -146,4 +148,3 @@ - diff --git a/bundles/org.openhab.binding.openweathermap/pom.xml b/bundles/org.openhab.binding.openweathermap/pom.xml index a4edb22123107..19414a2e952b7 100644 --- a/bundles/org.openhab.binding.openweathermap/pom.xml +++ b/bundles/org.openhab.binding.openweathermap/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.openweathermap diff --git a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/connection/OpenWeatherMapConnection.java b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/connection/OpenWeatherMapConnection.java index fc787523e5e77..8986dfaea58d4 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/connection/OpenWeatherMapConnection.java +++ b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/connection/OpenWeatherMapConnection.java @@ -27,7 +27,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; @@ -216,7 +215,7 @@ public OpenWeatherMapConnection(OpenWeatherMapAPIHandler handler, HttpClient htt * @return the weather icon as {@link RawType} */ public static @Nullable RawType getWeatherIcon(String iconId) { - if (StringUtils.isEmpty(iconId)) { + if (iconId.isEmpty()) { throw new IllegalArgumentException("Cannot download weather icon as icon id is null."); } @@ -247,7 +246,11 @@ private Map getRequestParams(OpenWeatherMapAPIConfiguration conf Map params = new HashMap<>(); // API key (see http://openweathermap.org/appid) - params.put(PARAM_APPID, StringUtils.trimToEmpty(config.getApikey())); + String apikey = config.getApikey(); + if (apikey == null || (apikey = apikey.trim()).isEmpty()) { + throw new OpenWeatherMapConfigurationException("@text/offline.conf-error-missing-apikey"); + } + params.put(PARAM_APPID, apikey); // Units format (see https://openweathermap.org/current#data) params.put(PARAM_UNITS, "metric"); @@ -257,8 +260,8 @@ private Map getRequestParams(OpenWeatherMapAPIConfiguration conf params.put(PARAM_LON, location.getLongitude().toString()); // Multilingual support (see https://openweathermap.org/current#multi) - String language = StringUtils.trimToEmpty(config.getLanguage()); - if (!language.isEmpty()) { + String language = config.getLanguage(); + if (language != null && !(language = language.trim()).isEmpty()) { params.put(PARAM_LANG, language.toLowerCase()); } return params; @@ -266,7 +269,7 @@ private Map getRequestParams(OpenWeatherMapAPIConfiguration conf private String buildURL(String url, Map requestParams) { return requestParams.keySet().stream().map(key -> key + "=" + encodeParam(requestParams.get(key))) - .collect(joining("&", url + "?", StringUtils.EMPTY)); + .collect(joining("&", url + "?", "")); } private String encodeParam(String value) { @@ -274,7 +277,7 @@ private String encodeParam(String value) { return URLEncoder.encode(value, StandardCharsets.UTF_8.name()); } catch (UnsupportedEncodingException e) { logger.debug("UnsupportedEncodingException occurred during execution: {}", e.getLocalizedMessage(), e); - return StringUtils.EMPTY; + return ""; } } @@ -291,7 +294,7 @@ private String getResponse(String url) { .send(); int httpStatus = contentResponse.getStatus(); String content = contentResponse.getContentAsString(); - String errorMessage = StringUtils.EMPTY; + String errorMessage = ""; logger.trace("OpenWeatherMap response: status = {}, content = '{}'", httpStatus, content); switch (httpStatus) { case OK_200: diff --git a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/AbstractOpenWeatherMapHandler.java b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/AbstractOpenWeatherMapHandler.java index e3c641da9b5e7..c9e9925916f31 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/AbstractOpenWeatherMapHandler.java +++ b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/AbstractOpenWeatherMapHandler.java @@ -26,7 +26,6 @@ import javax.measure.Unit; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DateTimeType; @@ -35,6 +34,7 @@ import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.types.RawType; import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelGroupUID; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -44,6 +44,7 @@ import org.eclipse.smarthome.core.thing.ThingStatusInfo; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.BridgeHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerCallback; import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; import org.eclipse.smarthome.core.thing.type.ChannelGroupTypeUID; @@ -82,29 +83,48 @@ public AbstractOpenWeatherMapHandler(Thing thing) { @Override public void initialize() { - OpenWeatherMapLocationConfiguration config = getConfigAs(OpenWeatherMapLocationConfiguration.class); + logger.debug("initializing handler for thing {}", getThing().getUID()); + Bridge bridge = getBridge(); + initializeThing(bridge != null ? bridge.getStatus() : null); + } - boolean configValid = true; - if (StringUtils.trimToNull(config.getLocation()) == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "@text/offline.conf-error-missing-location"); - configValid = false; - } + private void initializeThing(@Nullable ThingStatus bridgeStatus) { + Bridge bridge = getBridge(); + BridgeHandler bridgeHandler = bridge != null ? bridge.getHandler() : null; + if (bridgeHandler != null && bridgeStatus != null) { + if (bridgeStatus == ThingStatus.ONLINE) { + OpenWeatherMapLocationConfiguration config = getConfigAs(OpenWeatherMapLocationConfiguration.class); + + boolean configValid = true; + if (config.getLocation() == null || config.getLocation().trim().isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error-missing-location"); + configValid = false; + } - try { - location = new PointType(config.getLocation()); - } catch (IllegalArgumentException e) { - location = null; - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "@text/offline.conf-error-parsing-location"); - configValid = false; - } + try { + location = new PointType(config.getLocation()); + } catch (IllegalArgumentException e) { + location = null; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "@text/offline.conf-error-parsing-location"); + configValid = false; + } - if (configValid) { - updateStatus(ThingStatus.UNKNOWN); + if (configValid) { + updateStatus(ThingStatus.UNKNOWN); + initializeThing(); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); } } + protected abstract void initializeThing(); + @Override public void handleCommand(ChannelUID channelUID, Command command) { if (command instanceof RefreshType) { @@ -116,13 +136,8 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { - if (ThingStatus.ONLINE.equals(bridgeStatusInfo.getStatus()) - && ThingStatusDetail.BRIDGE_OFFLINE.equals(getThing().getStatusInfo().getStatusDetail())) { - updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE); - } else if (ThingStatus.OFFLINE.equals(bridgeStatusInfo.getStatus()) - && !ThingStatus.OFFLINE.equals(getThing().getStatus())) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); - } + logger.debug("bridgeStatusChanged {} for thing {}", bridgeStatusInfo, getThing().getUID()); + initializeThing(bridgeStatusInfo.getStatus()); } /** diff --git a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapAPIHandler.java b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapAPIHandler.java index bf3924ffb1b75..dab4e99c95b81 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapAPIHandler.java +++ b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapAPIHandler.java @@ -19,7 +19,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; @@ -75,7 +74,7 @@ public void initialize() { config = getConfigAs(OpenWeatherMapAPIConfiguration.class); boolean configValid = true; - if (StringUtils.trimToNull(config.getApikey()) == null) { + if (config.getApikey() == null || config.getApikey().trim().isEmpty()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-missing-apikey"); configValid = false; @@ -87,8 +86,7 @@ public void initialize() { configValid = false; } String language = config.getLanguage(); - if (language != null) { - language = StringUtils.trimToEmpty(language); + if (language != null && !(language = language.trim()).isEmpty()) { if (!OpenWeatherMapAPIConfiguration.SUPPORTED_LANGUAGES.contains(language.toLowerCase())) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-not-supported-language"); diff --git a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapUVIndexHandler.java b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapUVIndexHandler.java index 4e49fd3a9344a..8c484779d1785 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapUVIndexHandler.java +++ b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapUVIndexHandler.java @@ -65,8 +65,7 @@ public OpenWeatherMapUVIndexHandler(Thing thing) { } @Override - public void initialize() { - super.initialize(); + protected void initializeThing() { logger.debug("Initialize OpenWeatherMapUVIndexHandler handler '{}'.", getThing().getUID()); OpenWeatherMapUVIndexConfiguration config = getConfigAs(OpenWeatherMapUVIndexConfiguration.class); diff --git a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapWeatherAndForecastHandler.java b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapWeatherAndForecastHandler.java index 048c56aa09da8..d29cbe771f48f 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapWeatherAndForecastHandler.java +++ b/bundles/org.openhab.binding.openweathermap/src/main/java/org/openhab/binding/openweathermap/internal/handler/OpenWeatherMapWeatherAndForecastHandler.java @@ -82,8 +82,7 @@ public OpenWeatherMapWeatherAndForecastHandler(Thing thing) { } @Override - public void initialize() { - super.initialize(); + protected void initializeThing() { logger.debug("Initialize OpenWeatherMapWeatherAndForecastHandler handler '{}'.", getThing().getUID()); OpenWeatherMapWeatherAndForecastConfiguration config = getConfigAs( OpenWeatherMapWeatherAndForecastConfiguration.class); diff --git a/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/bridge-types.xml b/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/bridge-types.xml index dfbeec5a4b200..9decd02247ebd 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/bridge-types.xml +++ b/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/bridge-types.xml @@ -11,7 +11,7 @@ apikey - + diff --git a/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/channel-types.xml index 874f68b2f69ed..17e604f5e5010 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/channel-types.xml @@ -9,8 +9,8 @@ This is a weather station. - - + + Location of the weather station or the city. @@ -21,22 +21,22 @@ This is the current weather. - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -44,23 +44,23 @@ This is the 5 day / 3 hour weather forecast. - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -68,22 +68,22 @@ This is the 16 day / daily weather forecast. - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -91,8 +91,8 @@ This is the current UV Index. - - + + @@ -100,8 +100,8 @@ This is the forecasted UV Index. - - + + @@ -110,14 +110,14 @@ String Id of the weather station or the city. - + String Name of the weather station or the city. - + @@ -125,7 +125,7 @@ Time of data observation. Time - + @@ -133,7 +133,7 @@ Time of data forecasted. Time - + @@ -141,7 +141,7 @@ Date of data forecasted. Time - + @@ -149,7 +149,7 @@ Current weather condition. Sun_Clouds - + @@ -157,28 +157,28 @@ Forecasted weather condition. Sun_Clouds - + String Id of the weather condition. - + Image Icon representing the weather condition. - + String Id of the icon to create the URL. - + @@ -186,7 +186,7 @@ Forecasted outdoor temperature. Temperature - + @@ -194,7 +194,7 @@ Minimum forecasted outdoor temperature. Temperature - + @@ -202,7 +202,7 @@ Maximum forecasted outdoor temperature. Temperature - + @@ -210,7 +210,7 @@ Current apparent temperature. Temperature - + @@ -218,7 +218,7 @@ Forecasted apparent temperature. Temperature - + @@ -226,7 +226,7 @@ Forecasted barometric pressure. Pressure - + @@ -234,7 +234,7 @@ Forecasted atmospheric relative humidity. Humidity - + @@ -242,7 +242,7 @@ Forecasted wind speed. Wind - + @@ -250,7 +250,7 @@ Forecasted wind direction expressed as an angle. Wind - + @@ -258,7 +258,7 @@ Current gust speed. Wind - + @@ -266,7 +266,7 @@ Forecasted gust speed. Wind - + @@ -274,7 +274,7 @@ Current cloudiness. Clouds - + @@ -282,7 +282,7 @@ Forecasted cloudiness. Clouds - + @@ -290,7 +290,7 @@ Rain volume of the last hour. Rain - + @@ -298,7 +298,7 @@ Forecasted rain volume. Rain - + @@ -306,7 +306,7 @@ Snow volume of the last hour. Snow - + @@ -314,28 +314,28 @@ Forecasted snow volume. Snow - + Number Current UV Index. - + Number Forecasted UV Index. - + Number:Length Current visibility. - + diff --git a/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/thing-types.xml index dfe1de0fbc0b0..fc0c9ba2454f8 100644 --- a/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.openweathermap/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,15 +7,15 @@ - + Provides current weather and forecast data from the OpenWeatherMap API. - - + + This is the weather forecast for the next 3 hours. @@ -76,19 +76,19 @@ location - + - + Provides UV Index data from the OpenWeatherMap API. - + This is the UV Index forecast for tomorrow. @@ -113,7 +113,7 @@ location - + diff --git a/bundles/org.openhab.binding.orvibo/pom.xml b/bundles/org.openhab.binding.orvibo/pom.xml index a831c563093d8..b62794e9ca280 100644 --- a/bundles/org.openhab.binding.orvibo/pom.xml +++ b/bundles/org.openhab.binding.orvibo/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.orvibo @@ -30,5 +32,5 @@ compile - + diff --git a/bundles/org.openhab.binding.orvibo/src/main/feature/feature.xml b/bundles/org.openhab.binding.orvibo/src/main/feature/feature.xml index 03b85e236e88a..23fb753cc2199 100644 --- a/bundles/org.openhab.binding.orvibo/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.orvibo/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.apache.commons/commons-collections4/4.1 - mvn:org.openhab.addons.bundles/org.openhab.binding.orvibo/${project.version} - + + openhab-runtime-base + mvn:org.apache.commons/commons-collections4/4.1 + mvn:org.openhab.addons.bundles/org.openhab.binding.orvibo/${project.version} + diff --git a/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboActivator.java b/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboActivator.java index 6ab9c28ba0962..c401b9129d7b0 100644 --- a/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboActivator.java +++ b/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboActivator.java @@ -37,5 +37,4 @@ public void start(BundleContext context) throws Exception { public void stop(BundleContext context) throws Exception { s20Client.disconnect(); } - } diff --git a/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboBindingConstants.java b/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboBindingConstants.java index e4b2cbdbe0165..43094aebbc1d6 100644 --- a/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboBindingConstants.java +++ b/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboBindingConstants.java @@ -34,5 +34,4 @@ public class OrviboBindingConstants { // List of all Config properties public static final String CONFIG_PROPERTY_DEVICE_ID = "deviceId"; - } diff --git a/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboHandlerFactory.java b/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboHandlerFactory.java index 855d1ce0c5133..76f4aeec0bf75 100644 --- a/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboHandlerFactory.java +++ b/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/OrviboHandlerFactory.java @@ -49,5 +49,4 @@ protected ThingHandler createHandler(Thing thing) { } return null; } - } diff --git a/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/discovery/SocketDiscoveryService.java b/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/discovery/SocketDiscoveryService.java index 469aa123a978a..73ee1c0a28c23 100644 --- a/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/discovery/SocketDiscoveryService.java +++ b/bundles/org.openhab.binding.orvibo/src/main/java/org/openhab/binding/orvibo/internal/discovery/SocketDiscoveryService.java @@ -118,5 +118,4 @@ private void doThingDiscovered(Socket socket) { DiscoveryResult discoveryResult = createDiscoveryResult(socket); thingDiscovered(discoveryResult); } - } diff --git a/bundles/org.openhab.binding.orvibo/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.orvibo/src/main/resources/ESH-INF/binding/binding.xml index 6219b604843a2..1db30bbc0db13 100644 --- a/bundles/org.openhab.binding.orvibo/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.orvibo/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Orvibo Binding This is the binding for Orvibo devices. diff --git a/bundles/org.openhab.binding.orvibo/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.orvibo/src/main/resources/ESH-INF/thing/thing-types.xml index beca57b8435ec..178fe6a97f7b0 100644 --- a/bundles/org.openhab.binding.orvibo/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.orvibo/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> diff --git a/bundles/org.openhab.binding.paradoxalarm/.classpath b/bundles/org.openhab.binding.paradoxalarm/.classpath index 906bfcecb475f..a5d95095ccaaf 100644 --- a/bundles/org.openhab.binding.paradoxalarm/.classpath +++ b/bundles/org.openhab.binding.paradoxalarm/.classpath @@ -1,32 +1,32 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.paradoxalarm/NOTICE b/bundles/org.openhab.binding.paradoxalarm/NOTICE index edfd204e5d248..38d625e349232 100644 --- a/bundles/org.openhab.binding.paradoxalarm/NOTICE +++ b/bundles/org.openhab.binding.paradoxalarm/NOTICE @@ -1,13 +1,13 @@ -This content is produced and maintained by the openHAB project. - -* Project home: https://www.openhab.org - -== Declared Project Licenses - -This program and the accompanying materials are made available under the terms -of the Eclipse Public License 2.0 which is available at -https://www.eclipse.org/legal/epl-2.0/. - -== Source Code - -https://github.com/openhab/openhab-addons +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons diff --git a/bundles/org.openhab.binding.paradoxalarm/README.md b/bundles/org.openhab.binding.paradoxalarm/README.md index 5c19dbdae7ec3..8b4b458b689c1 100644 --- a/bundles/org.openhab.binding.paradoxalarm/README.md +++ b/bundles/org.openhab.binding.paradoxalarm/README.md @@ -1,177 +1,177 @@ -# Paradox Alarm System binding - -This binding is intended to provide basic support for Paradox Alarm system. -Currently the binding does not support active communication, i.e. you cannot change states (arming, disarming). The intention is to use it only for monitoring of your security system. -With the power of openHAB this binding can be used for complex decision rules combining motion/magnetic sensor or whole partitions states with different scenarios. - -Examples: - -* All partitions are armed, therefore there is no one at home. -* Window is opened for more than 10 minutes and temperature outside is bellow XXX degrees, send mail/any other supported notification to particular people. - -## Supported Paradox panels/systems - -Currently binding supports the following panels: EVO192, EVO48(not tested), EVO96(not tested) - -## Supported things - -| Thing | Thing Type | Description | -|------------|------------|----------------------------------------------------------------| -| ip150 | Bridge | The bridge is used to communicate with IP150 ethernet module attached to Paradox security system.| -| panel | Thing | this is representation of Paradox panel. Has the general information about the main panel module, i.e. serial number, firmware/hardware/software versions, panel type, etc...| -| partition | Thing | provides "state"(armed, disarmed, in alarm), "partition label" and "additional states" are aggregated additional states which are booleans (ready to arm, trouble, force instant arm ready, etc...)| -| zone | Thing | Paradox zone. Can be anything - magnetic, motion or any other opened/closed sensor. State channel is contact, low battery and is tampered channels are switch, label is String | - -## Things configuration - -### IP150 bridge parameters - -| Parameter | Description | -|-------------------|----------------------------------------| -| refresh | Value is in seconds. Defines the refresh interval when the binding polls from paradox system.| -| ip150Password | The password to your IP150 (not your panel PIN).| -| pcPassword | The code 3012 setting. Default value is 0000.| -| ipAddress | IP address of your IP150.| -| port | The port used for data communication. Default value is 10000.| -| panelType | Optional parameter. Will be used if discovery does not identify the panel. Otherwise provide EVO48, EVO96, EVO192, etc...| -| reconnectWaitTime | Value is in seconds. The time to wait before a reconnect occurs after socket timeout.| -| maxPartitions | Optional parameter which sets maximum partitions to use during refresh. If not set, maximum allowed amount from panelType will be used.| -| maxZones | Optional parameter which sets maximum zones to use during refresh. If not set, maximum allowed amount from panelType will be used.| - -### IP150 bridge channels - -| Channel | Description | -|---------------------|------------------------------------------------| -|communicationCommand | Possible values [LOGOUT, LOGIN, RESET] | - -| Value | Description | -|--------|------------------------------------------------------------------------------------| -| LOGOUT | Logs out and disconnects from Paradox alarm system | -| LOGIN | Creates socket if necessary, connects to paradox system and uses the logon data from the thing parameters to connect.| -| RESET | Does logout and then login with recreation of communicator objects inside the code.| - -### Entities (zones, partitions) configuration parameters: - -| Value | Description | -|--------|------------------------------------------------------------------------------------| -| id | The numeric ID of the zone/partition | - -### Partition channels: - -| Channel | Type | Description | -|--------------------------|---------|---------------------------------------------------------------------------------------------| -| partitionLabel | String | Label of partition inside Paradox configuration | -| state | String |State of partition (armed, disarmed, in alarm) | -| additionalState | String | This used to be a channel where all different states were consolidated as semi-colon separated string. With implementation of each state as channel additional states should be no longer used. (deprecated channel) | -| readyToArm | Switch | Partition is Ready to arm | -| inExitDelay | Switch | Partition is in Exit delay | -| inEntryDelay | Switch | Partition in Entry Delay | -| inTrouble | Switch | Partition has trouble | -| alarmInMemory | Switch | Partition has alarm in memory | -| zoneBypass | Switch | Partition is in Zone Bypass | -| zoneInTamperTrouble | Switch | Partition is in Tamper Trouble | -| zoneInLowBatteryTrouble | Switch | Partition has zone in Low Battery Trouble | -| zoneInFireLoopTrouble | Switch | Partition has zone in Fire Loop Trouble | -| zoneInSupervisionTrouble | Switch | Partition has zone in Supervision Trouble | -| stayInstantReady | Switch | Partition is in state Stay Instant Ready | -| forceReady | Switch | Partition is in state Force Ready | -| bypassReady | Switch | Partition is in state Bypass Ready | -| inhibitReady | Switch | Partition is in state Inhibit Ready | -| allZonesClosed | Contact | All zones in partition are currently closed | - -### Zone channels: - -| Channel | Type | Description | -|-----------------|---------|--------------------------------------------------------------------------------| -| zoneLabel | String | Label of zone inside Paradox configuration | -| openedState | Contact | Zone opened / closed | -| tamperedState | Switch | Zone is tampered / not tampered | -## Example things configuration - -```java - Bridge paradoxalarm:ip150:ip150 [refresh=5, panelType="EVO192", ip150Password="asdfasdf", pcPassword="1234", ipAddress=XXX.XXX.XXX.XXX", port=10000 ] { - - Thing panel panel - - Thing partition partition1 [id=1] - Thing partition partition2 [id=2] - Thing partition partition3 [id=3] - Thing partition partition4 [id=4] - - Thing zone MotionSensor1 [id=1] - Thing zone MagneticSensorWindow1 [id=2] - Thing zone MotionSensor2 [id=3] - Thing zone MagneticSensorWindow2 [id=4] -} -``` - -## Example items configuration - -```java -//Groups - Group Paradox "Paradox security group" - Group Partitions "Paradox partitions" (Paradox) - Group Floor1MUC "Magnetic sensors - Floor 1" (Paradox) - Group PIRSensors "Motion sensors" (Paradox) - -//COMMUNICATOR BRIDGE - String paradoxSendCommand "Send command to IP150" {channel="paradoxalarm:ip150:ip150:communicationCommand"} - -//PANEL - String panelState "Paradox panel state: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:state" } - String panelType "Paradox panel type: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:panelType" } - String serialNumber "Paradox Serial number: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:serialNumber" } - String hardwareVersion "Paradox HW version: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:hardwareVersion" } - String applicationVersion "Paradox Application version: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:applicationVersion" } - String bootloaderVersion "Paradox Bootloader version: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:bootloaderVersion" } - -//PARTITIONS - String partition1State "Magnetic sensors - Floor 1: [%s]" (Partitions) { channel = "paradoxalarm:partition:ip150:partition1:state" } - String partition1AdditionalStates "Floor1 MUC additional states: [%s]" (Partitions) { channel = "paradoxalarm:partition:ip150:partition1:additionalStates" } - -//ZONES - Contact CorridorFl1_PIR_state "Corridor Fl1 motion: [%s]" (PIRSensors) { channel = "paradoxalarm:zone:ip150:MotionSensor1:opened" } - Contact CorridorFl1_MUC_state "Corridor Fl1 window: [%s]" (Floor1MUC) { channel = "paradoxalarm:zone:ip150:MagneticSensorWindow1:opened" } -``` - -## Example sitemap configuration - -```java - Text label="Security" icon="lock"{ - Frame label="Panel"{ - Text item=panelState valuecolor=[panelState=="Online"="green", panelState=="Offline"="red"] - Text item=panelType - Text item=serialNumber - Text item=hardwareVersion - Text item=applicationVersion - Text item=bootloaderVersion - } - Frame label="IP150 communication" { - Switch item=paradoxSendCommand mappings=["LOGOUT"="Logout", "LOGIN"="Login", "RESET"="Reset"] - } - Frame label="Partitions" { - Text item=partition1State valuecolor=[partition1State=="Disarmed"="green", partition1State=="Armed"="red"] - Text item=partition1AdditionalStates - Text item=partition2State valuecolor=[partition2State=="Disarmed"="green", partition2State=="Armed"="red"] - Text item=partition2AdditionalStates - Text item=partition3State valuecolor=[partition3State=="Disarmed"="green", partition3State=="Armed"="red"] - Text item=partition3AdditionalStates - Text item=partition4State valuecolor=[partition4State=="Disarmed"="green", partition4State=="Armed"="red"] - Text item=partition4AdditionalStates - } - Frame label="Zones" { - Group item=Floor1MUC - Group item=Floor2MUC - Group item=Floor3MUC - Group item=PIRSensors - } - } -``` -## Acknowledgements -This binding would not be possible without the reverse engineering of the byte level protocol and the development by other authors in python, C# and other languages. Many thanks to the following authors and their respective github repositories for their development that helped in creating this binding: - -João Paulo Barraca - https://github.com/ParadoxAlarmInterface/pai - -Jean Henning - repository not available - -Tertuish - https://github.com/Tertiush/ParadoxIP150v2 / https://github.com/Tertiush/ParadoxIP150 +# Paradox Alarm System binding + +This binding is intended to provide basic support for Paradox Alarm system. +Currently the binding does not support active communication, i.e. you cannot change states (arming, disarming). The intention is to use it only for monitoring of your security system. +With the power of openHAB this binding can be used for complex decision rules combining motion/magnetic sensor or whole partitions states with different scenarios. + +Examples: + +* All partitions are armed, therefore there is no one at home. +* Window is opened for more than 10 minutes and temperature outside is bellow XXX degrees, send mail/any other supported notification to particular people. + +## Supported Paradox panels/systems + +Currently binding supports the following panels: EVO192, EVO48(not tested), EVO96(not tested) + +## Supported things + +| Thing | Thing Type | Description | +|------------|------------|----------------------------------------------------------------| +| ip150 | Bridge | The bridge is used to communicate with IP150 ethernet module attached to Paradox security system.| +| panel | Thing | this is representation of Paradox panel. Has the general information about the main panel module, i.e. serial number, firmware/hardware/software versions, panel type, etc...| +| partition | Thing | provides "state"(armed, disarmed, in alarm), "partition label" and "additional states" are aggregated additional states which are booleans (ready to arm, trouble, force instant arm ready, etc...)| +| zone | Thing | Paradox zone. Can be anything - magnetic, motion or any other opened/closed sensor. State channel is contact, low battery and is tampered channels are switch, label is String | + +## Things configuration + +### IP150 bridge parameters + +| Parameter | Description | +|-------------------|----------------------------------------| +| refresh | Value is in seconds. Defines the refresh interval when the binding polls from paradox system.| +| ip150Password | The password to your IP150 (not your panel PIN).| +| pcPassword | The code 3012 setting. Default value is 0000.| +| ipAddress | IP address of your IP150.| +| port | The port used for data communication. Default value is 10000.| +| panelType | Optional parameter. Will be used if discovery does not identify the panel. Otherwise provide EVO48, EVO96, EVO192, etc...| +| reconnectWaitTime | Value is in seconds. The time to wait before a reconnect occurs after socket timeout.| +| maxPartitions | Optional parameter which sets maximum partitions to use during refresh. If not set, maximum allowed amount from panelType will be used.| +| maxZones | Optional parameter which sets maximum zones to use during refresh. If not set, maximum allowed amount from panelType will be used.| + +### IP150 bridge channels + +| Channel | Description | +|---------------------|------------------------------------------------| +|communicationCommand | Possible values [LOGOUT, LOGIN, RESET] | + +| Value | Description | +|--------|------------------------------------------------------------------------------------| +| LOGOUT | Logs out and disconnects from Paradox alarm system | +| LOGIN | Creates socket if necessary, connects to paradox system and uses the logon data from the thing parameters to connect.| +| RESET | Does logout and then login with recreation of communicator objects inside the code.| + +### Entities (zones, partitions) configuration parameters: + +| Value | Description | +|--------|------------------------------------------------------------------------------------| +| id | The numeric ID of the zone/partition | + +### Partition channels: + +| Channel | Type | Description | +|--------------------------|---------|---------------------------------------------------------------------------------------------| +| partitionLabel | String | Label of partition inside Paradox configuration | +| state | String |State of partition (armed, disarmed, in alarm) | +| additionalState | String | This used to be a channel where all different states were consolidated as semi-colon separated string. With implementation of each state as channel additional states should be no longer used. (deprecated channel) | +| readyToArm | Switch | Partition is Ready to arm | +| inExitDelay | Switch | Partition is in Exit delay | +| inEntryDelay | Switch | Partition in Entry Delay | +| inTrouble | Switch | Partition has trouble | +| alarmInMemory | Switch | Partition has alarm in memory | +| zoneBypass | Switch | Partition is in Zone Bypass | +| zoneInTamperTrouble | Switch | Partition is in Tamper Trouble | +| zoneInLowBatteryTrouble | Switch | Partition has zone in Low Battery Trouble | +| zoneInFireLoopTrouble | Switch | Partition has zone in Fire Loop Trouble | +| zoneInSupervisionTrouble | Switch | Partition has zone in Supervision Trouble | +| stayInstantReady | Switch | Partition is in state Stay Instant Ready | +| forceReady | Switch | Partition is in state Force Ready | +| bypassReady | Switch | Partition is in state Bypass Ready | +| inhibitReady | Switch | Partition is in state Inhibit Ready | +| allZonesClosed | Contact | All zones in partition are currently closed | + +### Zone channels: + +| Channel | Type | Description | +|-----------------|---------|--------------------------------------------------------------------------------| +| zoneLabel | String | Label of zone inside Paradox configuration | +| openedState | Contact | Zone opened / closed | +| tamperedState | Switch | Zone is tampered / not tampered | +## Example things configuration + +```java + Bridge paradoxalarm:ip150:ip150 [refresh=5, panelType="EVO192", ip150Password="asdfasdf", pcPassword="1234", ipAddress=XXX.XXX.XXX.XXX", port=10000 ] { + + Thing panel panel + + Thing partition partition1 [id=1] + Thing partition partition2 [id=2] + Thing partition partition3 [id=3] + Thing partition partition4 [id=4] + + Thing zone MotionSensor1 [id=1] + Thing zone MagneticSensorWindow1 [id=2] + Thing zone MotionSensor2 [id=3] + Thing zone MagneticSensorWindow2 [id=4] +} +``` + +## Example items configuration + +```java +//Groups + Group Paradox "Paradox security group" + Group Partitions "Paradox partitions" (Paradox) + Group Floor1MUC "Magnetic sensors - Floor 1" (Paradox) + Group PIRSensors "Motion sensors" (Paradox) + +//COMMUNICATOR BRIDGE + String paradoxSendCommand "Send command to IP150" {channel="paradoxalarm:ip150:ip150:communicationCommand"} + +//PANEL + String panelState "Paradox panel state: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:state" } + String panelType "Paradox panel type: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:panelType" } + String serialNumber "Paradox Serial number: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:serialNumber" } + String hardwareVersion "Paradox HW version: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:hardwareVersion" } + String applicationVersion "Paradox Application version: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:applicationVersion" } + String bootloaderVersion "Paradox Bootloader version: [%s]" (Paradox) { channel = "paradoxalarm:panel:ip150:panel:bootloaderVersion" } + +//PARTITIONS + String partition1State "Magnetic sensors - Floor 1: [%s]" (Partitions) { channel = "paradoxalarm:partition:ip150:partition1:state" } + String partition1AdditionalStates "Floor1 MUC additional states: [%s]" (Partitions) { channel = "paradoxalarm:partition:ip150:partition1:additionalStates" } + +//ZONES + Contact CorridorFl1_PIR_state "Corridor Fl1 motion: [%s]" (PIRSensors) { channel = "paradoxalarm:zone:ip150:MotionSensor1:opened" } + Contact CorridorFl1_MUC_state "Corridor Fl1 window: [%s]" (Floor1MUC) { channel = "paradoxalarm:zone:ip150:MagneticSensorWindow1:opened" } +``` + +## Example sitemap configuration + +```java + Text label="Security" icon="lock"{ + Frame label="Panel"{ + Text item=panelState valuecolor=[panelState=="Online"="green", panelState=="Offline"="red"] + Text item=panelType + Text item=serialNumber + Text item=hardwareVersion + Text item=applicationVersion + Text item=bootloaderVersion + } + Frame label="IP150 communication" { + Switch item=paradoxSendCommand mappings=["LOGOUT"="Logout", "LOGIN"="Login", "RESET"="Reset"] + } + Frame label="Partitions" { + Text item=partition1State valuecolor=[partition1State=="Disarmed"="green", partition1State=="Armed"="red"] + Text item=partition1AdditionalStates + Text item=partition2State valuecolor=[partition2State=="Disarmed"="green", partition2State=="Armed"="red"] + Text item=partition2AdditionalStates + Text item=partition3State valuecolor=[partition3State=="Disarmed"="green", partition3State=="Armed"="red"] + Text item=partition3AdditionalStates + Text item=partition4State valuecolor=[partition4State=="Disarmed"="green", partition4State=="Armed"="red"] + Text item=partition4AdditionalStates + } + Frame label="Zones" { + Group item=Floor1MUC + Group item=Floor2MUC + Group item=Floor3MUC + Group item=PIRSensors + } + } +``` +## Acknowledgements +This binding would not be possible without the reverse engineering of the byte level protocol and the development by other authors in python, C# and other languages. Many thanks to the following authors and their respective github repositories for their development that helped in creating this binding: + +João Paulo Barraca - https://github.com/ParadoxAlarmInterface/pai + +Jean Henning - repository not available + +Tertuish - https://github.com/Tertiush/ParadoxIP150v2 / https://github.com/Tertiush/ParadoxIP150 diff --git a/bundles/org.openhab.binding.paradoxalarm/pom.xml b/bundles/org.openhab.binding.paradoxalarm/pom.xml index 27db12071a05a..c15ca6b44f7ca 100644 --- a/bundles/org.openhab.binding.paradoxalarm/pom.xml +++ b/bundles/org.openhab.binding.paradoxalarm/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.reactor.bundles org.openhab.addons.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.paradoxalarm diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/feature/feature.xml b/bundles/org.openhab.binding.paradoxalarm/src/main/feature/feature.xml index c6820307c1236..2abed59eb452c 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.paradoxalarm/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.paradoxalarm/${project.version} + diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/CommunicationState.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/CommunicationState.java index 548da82a6c1dc..278c089acbdcd 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/CommunicationState.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/CommunicationState.java @@ -83,7 +83,6 @@ protected boolean isPhaseSuccess(IResponse response) { } return false; } - }, STEP2 { @@ -99,7 +98,6 @@ protected void runPhase(IParadoxInitialLoginCommunicator communicator, Object... .setCommand(HeaderCommand.LOGIN_COMMAND1); sendPacket(communicator, packet); } - }, STEP3 { @@ -115,7 +113,6 @@ protected void runPhase(IParadoxInitialLoginCommunicator communicator, Object... .setCommand(HeaderCommand.LOGIN_COMMAND2); sendPacket(communicator, packet); } - }, STEP4 { @@ -147,7 +144,6 @@ protected void receiveResponse(IParadoxInitialLoginCommunicator communicator, IR LOGOUT.runPhase(communicator); } } - }, STEP5 { @@ -163,7 +159,6 @@ protected void runPhase(IParadoxInitialLoginCommunicator communicator, Object... .setCommand(HeaderCommand.SERIAL_CONNECTION_INITIATED); sendPacket(communicator, packet); } - }, STEP6 { @@ -191,7 +186,6 @@ protected void receiveResponse(IParadoxInitialLoginCommunicator communicator, IR logger.debug("Phase {} completed successfully.", this); nextState().runPhase(communicator, initializationMessage); } - }, STEP7 { @@ -298,7 +292,6 @@ protected void receiveResponse(IParadoxInitialLoginCommunicator communicator, IR } }, 300, TimeUnit.MILLISECONDS); } - }, INITIALIZE_DATA { @@ -315,7 +308,6 @@ protected void runPhase(IParadoxInitialLoginCommunicator communicator, Object... } ONLINE.runPhase(communicator); } - }, ONLINE { @@ -330,7 +322,6 @@ protected void runPhase(IParadoxInitialLoginCommunicator communicator, Object... communicator.setOnline(true); logger.info("Successfully established communication with the panel."); } - }, LOGOUT { @@ -350,7 +341,6 @@ protected void runPhase(IParadoxInitialLoginCommunicator communicator, Object... // sendPacket(communicator, logoutPacket); nextState().runPhase(communicator); } - }, OFFLINE { @@ -364,7 +354,6 @@ protected void runPhase(IParadoxInitialLoginCommunicator communicator, Object... communicator.close(); communicator.setOnline(false); } - }; protected final Logger logger = LoggerFactory.getLogger(CommunicationState.class); diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/EpromRequest.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/EpromRequest.java index cc64de0c0dbb3..3a890a164632d 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/EpromRequest.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/EpromRequest.java @@ -43,5 +43,4 @@ public int getEntityId() { public String toString() { return "EpromRequest [getType()=" + getType() + ", entityType=" + entityType + ", entityId=" + entityId + "]"; } - } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/EvoCommunicator.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/EvoCommunicator.java index e57745e2d41cc..5b66a1480f987 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/EvoCommunicator.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/EvoCommunicator.java @@ -1,398 +1,398 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication; - -import java.io.IOException; -import java.net.UnknownHostException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.openhab.binding.paradoxalarm.internal.communication.messages.EpromRequestPayload; -import org.openhab.binding.paradoxalarm.internal.communication.messages.HeaderMessageType; -import org.openhab.binding.paradoxalarm.internal.communication.messages.IPPacketPayload; -import org.openhab.binding.paradoxalarm.internal.communication.messages.ParadoxIPPacket; -import org.openhab.binding.paradoxalarm.internal.communication.messages.RamRequestPayload; -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; -import org.openhab.binding.paradoxalarm.internal.model.EntityType; -import org.openhab.binding.paradoxalarm.internal.model.PanelType; -import org.openhab.binding.paradoxalarm.internal.model.ZoneStateFlags; -import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link EvoCommunicator} is responsible for handling communication to Evo192 alarm system via IP150 interface. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class EvoCommunicator extends GenericCommunicator implements IParadoxCommunicator { - - private static final byte RAM_BLOCK_SIZE = (byte) 64; - - private final Logger logger = LoggerFactory.getLogger(EvoCommunicator.class); - - private MemoryMap memoryMap; - - private Map> entityLabelsMap = new HashMap<>(); - - private PanelType panelType = PanelType.UNKNOWN; - private Integer maxPartitions; - private Integer maxZones; - - private EvoCommunicator(String ipAddress, int tcpPort, String ip150Password, String pcPassword, - ScheduledExecutorService scheduler, PanelType panelType, Integer maxPartitions, Integer maxZones) - throws UnknownHostException, IOException { - super(ipAddress, tcpPort, ip150Password, pcPassword, scheduler); - this.panelType = panelType; - this.maxPartitions = maxPartitions; - this.maxZones = maxZones; - logger.debug("PanelType={}, max partitions={}, max Zones={}", panelType, maxPartitions, maxZones); - initializeMemoryMap(); - } - - @Override - protected void receiveEpromResponse(IResponse response) throws ParadoxException { - EpromRequest request = (EpromRequest) response.getRequest(); - int entityId = request.getEntityId(); - EntityType entityType = request.getEntityType(); - - byte[] parsedResult = parsePacket(response); - updateEntityLabel(entityType, entityId, parsedResult); - } - - @Override - protected void receiveRamResponse(IResponse response) throws ParadoxException { - RamRequest request = (RamRequest) response.getRequest(); - int ramBlockNumber = request.getRamBlockNumber(); - - byte[] parsedResult = parsePacket(response); - if (parsedResult != null && parsedResult.length == RAM_BLOCK_SIZE) { - memoryMap.updateElement(ramBlockNumber, parsedResult); - logger.trace("Result for ramBlock={} is [{}]", ramBlockNumber, parsedResult); - } else { - logger.debug("Wrong parsed result. Probably wrong data received in response"); - return; - } - - // Trigger listeners update when last memory page update is received - if (ramBlockNumber == panelType.getRamPagesNumber()) { - updateListeners(); - } - } - - private void updateEntityLabel(EntityType entityType, int entityId, byte[] payload) { - String label = createString(payload); - logger.debug("{} label updated to: {}", entityType, label); - - entityLabelsMap.get(entityType).put(entityId, label); - } - - private void retrievePartitionLabel(int partitionNo) { - logger.debug("Submitting request for partition label: {}", partitionNo); - int address = 0x3A6B + (partitionNo) * 107; - byte labelLength = 16; - - try { - IPPacketPayload payload = new EpromRequestPayload(address, labelLength); - ParadoxIPPacket readEpromIPPacket = new ParadoxIPPacket(payload) - .setMessageType(HeaderMessageType.SERIAL_PASSTHRU_REQUEST).setUnknown0((byte) 0x14); - - IRequest epromRequest = new EpromRequest(partitionNo, EntityType.PARTITION, readEpromIPPacket); - submitRequest(epromRequest); - } catch (ParadoxException e) { - logger.debug("Error creating request for with number={}, Exception={} ", partitionNo, e.getMessage()); - } - } - - private void retrieveZoneLabel(int zoneNumber) { - logger.debug("Submitting request for zone label: {}", zoneNumber); - byte labelLength = 16; - - try { - int address; - if (zoneNumber < 96) { - address = 0x430 + (zoneNumber) * 16; - } else { - address = 0x62F7 + (zoneNumber - 96) * 16; - } - - IPPacketPayload payload = new EpromRequestPayload(address, labelLength); - ParadoxIPPacket readEpromIPPacket = createParadoxIpPacket(payload); - - IRequest epromRequest = new EpromRequest(zoneNumber, EntityType.ZONE, readEpromIPPacket); - submitRequest(epromRequest); - } catch (ParadoxException e) { - logger.debug("Error creating request with number={}, Exception={} ", zoneNumber, e.getMessage()); - } - } - - @Override - public List getPartitionFlags() { - List result = new ArrayList<>(); - - byte[] element = memoryMap.getElement(2); - byte[] firstBlock = Arrays.copyOfRange(element, 32, 64); - - element = memoryMap.getElement(3); - byte[] secondBlock = Arrays.copyOfRange(element, 0, 16); - byte[] mergeByteArrays = ParadoxUtil.mergeByteArrays(firstBlock, secondBlock); - for (int i = 0; i < mergeByteArrays.length; i += 6) { - result.add(Arrays.copyOfRange(mergeByteArrays, i, i + 6)); - } - - return result; - } - - @Override - public ZoneStateFlags getZoneStateFlags() { - ZoneStateFlags result = new ZoneStateFlags(); - - byte[] firstPage = memoryMap.getElement(0); - byte[] secondPage = memoryMap.getElement(8); - - int pageOffset = panelType == PanelType.EVO48 ? 34 : 40; - byte[] firstBlock = Arrays.copyOfRange(firstPage, 28, pageOffset); - if (panelType != PanelType.EVO192) { - result.setZonesOpened(firstBlock); - } else { - byte[] secondBlock = Arrays.copyOfRange(secondPage, 0, 12); - byte[] zonesOpened = ParadoxUtil.mergeByteArrays(firstBlock, secondBlock); - result.setZonesOpened(zonesOpened); - } - - pageOffset = panelType == PanelType.EVO48 ? 46 : 52; - firstBlock = Arrays.copyOfRange(firstPage, 40, pageOffset); - if (panelType != PanelType.EVO192) { - result.setZonesTampered(firstBlock); - } else { - byte[] secondBlock = Arrays.copyOfRange(secondPage, 12, 24); - byte[] zonesTampered = ParadoxUtil.mergeByteArrays(firstBlock, secondBlock); - result.setZonesTampered(zonesTampered); - } - - pageOffset = panelType == PanelType.EVO48 ? 58 : 64; - firstBlock = Arrays.copyOfRange(firstPage, 52, pageOffset); - if (panelType != PanelType.EVO192) { - result.setZonesTampered(firstBlock); - } else { - byte[] secondBlock = Arrays.copyOfRange(secondPage, 24, 36); - byte[] zonesLowBattery = ParadoxUtil.mergeByteArrays(firstBlock, secondBlock); - result.setZonesLowBattery(zonesLowBattery); - } - - return result; - } - - public void initializeMemoryMap() { - for (EntityType type : EntityType.values()) { - entityLabelsMap.put(type, new HashMap<>()); - } - - List ramCache = new ArrayList<>(panelType.getRamPagesNumber() + 1); - for (int i = 0; i <= panelType.getRamPagesNumber(); i++) { - ramCache.add(new byte[0]); - } - memoryMap = new MemoryMap(ramCache); - } - - @Override - public void refreshMemoryMap() { - if (!isOnline()) { - return; - } - - SyncQueue queue = SyncQueue.getInstance(); - synchronized (queue) { - for (int i = 1; i <= panelType.getRamPagesNumber(); i++) { - readRAM(i); - } - } - } - - private void readRAM(int blockNo) { - try { - logger.trace("Creating RAM page {} read request", blockNo); - IPPacketPayload payload = new RamRequestPayload(blockNo, RAM_BLOCK_SIZE); - ParadoxIPPacket ipPacket = createParadoxIpPacket(payload); - IRequest ramRequest = new RamRequest(blockNo, ipPacket); - submitRequest(ramRequest); - } catch (ParadoxException e) { - logger.debug( - "Unable to create request payload from provided bytes to read. blockNo={}, bytes to read={}. Exception={}", - blockNo, RAM_BLOCK_SIZE, e.getMessage()); - } - } - - private String createString(byte[] payloadResult) { - return new String(payloadResult, StandardCharsets.US_ASCII); - } - - @Override - public void executeCommand(String command) { - IP150Command ip150Command = IP150Command.valueOf(command); - switch (ip150Command) { - case LOGIN: - startLoginSequence(); - return; - case LOGOUT: - CommunicationState.LOGOUT.runPhase(this); - return; - case RESET: - CommunicationState.LOGOUT.runPhase(this); - scheduler.schedule(this::startLoginSequence, 5, TimeUnit.SECONDS); - return; - default: - logger.debug("Command {} not implemented.", command); - } - } - - public MemoryMap getMemoryMap() { - return memoryMap; - } - - public Map> getEntityLabelsMap() { - return entityLabelsMap; - } - - @Override - public Map getPartitionLabels() { - return entityLabelsMap.get(EntityType.PARTITION); - } - - @Override - public Map getZoneLabels() { - return entityLabelsMap.get(EntityType.ZONE); - } - - @Override - public void initializeData() { - synchronized (SyncQueue.getInstance()) { - initializeEpromData(); - refreshMemoryMap(); - } - } - - private void initializeEpromData() { - for (int i = 0; i < maxPartitions; i++) { - retrievePartitionLabel(i); - } - for (int i = 0; i < maxZones; i++) { - retrieveZoneLabel(i); - } - } - - public static class EvoCommunicatorBuilder implements ICommunicatorBuilder { - - private final Logger logger = LoggerFactory.getLogger(EvoCommunicatorBuilder.class); - - // Mandatory parameters - private PanelType panelType; - private String ipAddress; - private String ip150Password; - private ScheduledExecutorService scheduler; - - // Non mandatory or with predefined values - private Integer maxPartitions; - private Integer maxZones; - private int tcpPort = 10000; - private String pcPassword = "0000"; - - EvoCommunicatorBuilder(PanelType panelType) { - this.panelType = panelType; - } - - @Override - public IParadoxCommunicator build() { - if (panelType != PanelType.EVO48 && panelType != PanelType.EVO96 && panelType != PanelType.EVO192) { - throw new ParadoxRuntimeException("Unknown or unsupported panel type. Type=" + panelType); - } - - if (ipAddress == null || ipAddress.isEmpty()) { - throw new ParadoxRuntimeException("IP address cannot be empty !"); - } - - if (ip150Password == null || ip150Password.isEmpty()) { - throw new ParadoxRuntimeException("Password for IP150 cannot be empty !"); - } - - if (scheduler == null) { - throw new ParadoxRuntimeException("Scheduler is mandatory parameter !"); - } - - if (maxPartitions == null || maxPartitions < 1) { - this.maxPartitions = panelType.getPartitions(); - } - - if (maxZones == null || maxZones < 1) { - this.maxZones = panelType.getZones(); - } - - try { - return new EvoCommunicator(ipAddress, tcpPort, ip150Password, pcPassword, scheduler, panelType, - maxPartitions, maxZones); - } catch (IOException e) { - logger.warn("Unable to create communicator for Panel={}. Message={}", panelType, e.getMessage()); - throw new ParadoxRuntimeException(e); - } - } - - @Override - public ICommunicatorBuilder withMaxZones(Integer maxZones) { - this.maxZones = maxZones; - return this; - } - - @Override - public ICommunicatorBuilder withMaxPartitions(Integer maxPartitions) { - this.maxPartitions = maxPartitions; - return this; - } - - @Override - public ICommunicatorBuilder withIp150Password(String ip150Password) { - this.ip150Password = ip150Password; - return this; - } - - @Override - public ICommunicatorBuilder withPcPassword(String pcPassword) { - this.pcPassword = pcPassword; - return this; - } - - @Override - public ICommunicatorBuilder withIpAddress(String ipAddress) { - this.ipAddress = ipAddress; - return this; - } - - @Override - public ICommunicatorBuilder withTcpPort(Integer tcpPort) { - this.tcpPort = tcpPort; - return this; - } - - @Override - public ICommunicatorBuilder withScheduler(ScheduledExecutorService scheduler) { - this.scheduler = scheduler; - return this; - } - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication; + +import java.io.IOException; +import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.openhab.binding.paradoxalarm.internal.communication.messages.EpromRequestPayload; +import org.openhab.binding.paradoxalarm.internal.communication.messages.HeaderMessageType; +import org.openhab.binding.paradoxalarm.internal.communication.messages.IPPacketPayload; +import org.openhab.binding.paradoxalarm.internal.communication.messages.ParadoxIPPacket; +import org.openhab.binding.paradoxalarm.internal.communication.messages.RamRequestPayload; +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; +import org.openhab.binding.paradoxalarm.internal.model.EntityType; +import org.openhab.binding.paradoxalarm.internal.model.PanelType; +import org.openhab.binding.paradoxalarm.internal.model.ZoneStateFlags; +import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EvoCommunicator} is responsible for handling communication to Evo192 alarm system via IP150 interface. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class EvoCommunicator extends GenericCommunicator implements IParadoxCommunicator { + + private static final byte RAM_BLOCK_SIZE = (byte) 64; + + private final Logger logger = LoggerFactory.getLogger(EvoCommunicator.class); + + private MemoryMap memoryMap; + + private Map> entityLabelsMap = new HashMap<>(); + + private PanelType panelType = PanelType.UNKNOWN; + private Integer maxPartitions; + private Integer maxZones; + + private EvoCommunicator(String ipAddress, int tcpPort, String ip150Password, String pcPassword, + ScheduledExecutorService scheduler, PanelType panelType, Integer maxPartitions, Integer maxZones) + throws UnknownHostException, IOException { + super(ipAddress, tcpPort, ip150Password, pcPassword, scheduler); + this.panelType = panelType; + this.maxPartitions = maxPartitions; + this.maxZones = maxZones; + logger.debug("PanelType={}, max partitions={}, max Zones={}", panelType, maxPartitions, maxZones); + initializeMemoryMap(); + } + + @Override + protected void receiveEpromResponse(IResponse response) throws ParadoxException { + EpromRequest request = (EpromRequest) response.getRequest(); + int entityId = request.getEntityId(); + EntityType entityType = request.getEntityType(); + + byte[] parsedResult = parsePacket(response); + updateEntityLabel(entityType, entityId, parsedResult); + } + + @Override + protected void receiveRamResponse(IResponse response) throws ParadoxException { + RamRequest request = (RamRequest) response.getRequest(); + int ramBlockNumber = request.getRamBlockNumber(); + + byte[] parsedResult = parsePacket(response); + if (parsedResult != null && parsedResult.length == RAM_BLOCK_SIZE) { + memoryMap.updateElement(ramBlockNumber, parsedResult); + logger.trace("Result for ramBlock={} is [{}]", ramBlockNumber, parsedResult); + } else { + logger.debug("Wrong parsed result. Probably wrong data received in response"); + return; + } + + // Trigger listeners update when last memory page update is received + if (ramBlockNumber == panelType.getRamPagesNumber()) { + updateListeners(); + } + } + + private void updateEntityLabel(EntityType entityType, int entityId, byte[] payload) { + String label = createString(payload); + logger.debug("{} label updated to: {}", entityType, label); + + entityLabelsMap.get(entityType).put(entityId, label); + } + + private void retrievePartitionLabel(int partitionNo) { + logger.debug("Submitting request for partition label: {}", partitionNo); + int address = 0x3A6B + (partitionNo) * 107; + byte labelLength = 16; + + try { + IPPacketPayload payload = new EpromRequestPayload(address, labelLength); + ParadoxIPPacket readEpromIPPacket = new ParadoxIPPacket(payload) + .setMessageType(HeaderMessageType.SERIAL_PASSTHRU_REQUEST).setUnknown0((byte) 0x14); + + IRequest epromRequest = new EpromRequest(partitionNo, EntityType.PARTITION, readEpromIPPacket); + submitRequest(epromRequest); + } catch (ParadoxException e) { + logger.debug("Error creating request for with number={}, Exception={} ", partitionNo, e.getMessage()); + } + } + + private void retrieveZoneLabel(int zoneNumber) { + logger.debug("Submitting request for zone label: {}", zoneNumber); + byte labelLength = 16; + + try { + int address; + if (zoneNumber < 96) { + address = 0x430 + (zoneNumber) * 16; + } else { + address = 0x62F7 + (zoneNumber - 96) * 16; + } + + IPPacketPayload payload = new EpromRequestPayload(address, labelLength); + ParadoxIPPacket readEpromIPPacket = createParadoxIpPacket(payload); + + IRequest epromRequest = new EpromRequest(zoneNumber, EntityType.ZONE, readEpromIPPacket); + submitRequest(epromRequest); + } catch (ParadoxException e) { + logger.debug("Error creating request with number={}, Exception={} ", zoneNumber, e.getMessage()); + } + } + + @Override + public List getPartitionFlags() { + List result = new ArrayList<>(); + + byte[] element = memoryMap.getElement(2); + byte[] firstBlock = Arrays.copyOfRange(element, 32, 64); + + element = memoryMap.getElement(3); + byte[] secondBlock = Arrays.copyOfRange(element, 0, 16); + byte[] mergeByteArrays = ParadoxUtil.mergeByteArrays(firstBlock, secondBlock); + for (int i = 0; i < mergeByteArrays.length; i += 6) { + result.add(Arrays.copyOfRange(mergeByteArrays, i, i + 6)); + } + + return result; + } + + @Override + public ZoneStateFlags getZoneStateFlags() { + ZoneStateFlags result = new ZoneStateFlags(); + + byte[] firstPage = memoryMap.getElement(0); + byte[] secondPage = memoryMap.getElement(8); + + int pageOffset = panelType == PanelType.EVO48 ? 34 : 40; + byte[] firstBlock = Arrays.copyOfRange(firstPage, 28, pageOffset); + if (panelType != PanelType.EVO192) { + result.setZonesOpened(firstBlock); + } else { + byte[] secondBlock = Arrays.copyOfRange(secondPage, 0, 12); + byte[] zonesOpened = ParadoxUtil.mergeByteArrays(firstBlock, secondBlock); + result.setZonesOpened(zonesOpened); + } + + pageOffset = panelType == PanelType.EVO48 ? 46 : 52; + firstBlock = Arrays.copyOfRange(firstPage, 40, pageOffset); + if (panelType != PanelType.EVO192) { + result.setZonesTampered(firstBlock); + } else { + byte[] secondBlock = Arrays.copyOfRange(secondPage, 12, 24); + byte[] zonesTampered = ParadoxUtil.mergeByteArrays(firstBlock, secondBlock); + result.setZonesTampered(zonesTampered); + } + + pageOffset = panelType == PanelType.EVO48 ? 58 : 64; + firstBlock = Arrays.copyOfRange(firstPage, 52, pageOffset); + if (panelType != PanelType.EVO192) { + result.setZonesTampered(firstBlock); + } else { + byte[] secondBlock = Arrays.copyOfRange(secondPage, 24, 36); + byte[] zonesLowBattery = ParadoxUtil.mergeByteArrays(firstBlock, secondBlock); + result.setZonesLowBattery(zonesLowBattery); + } + + return result; + } + + public void initializeMemoryMap() { + for (EntityType type : EntityType.values()) { + entityLabelsMap.put(type, new HashMap<>()); + } + + List ramCache = new ArrayList<>(panelType.getRamPagesNumber() + 1); + for (int i = 0; i <= panelType.getRamPagesNumber(); i++) { + ramCache.add(new byte[0]); + } + memoryMap = new MemoryMap(ramCache); + } + + @Override + public void refreshMemoryMap() { + if (!isOnline()) { + return; + } + + SyncQueue queue = SyncQueue.getInstance(); + synchronized (queue) { + for (int i = 1; i <= panelType.getRamPagesNumber(); i++) { + readRAM(i); + } + } + } + + private void readRAM(int blockNo) { + try { + logger.trace("Creating RAM page {} read request", blockNo); + IPPacketPayload payload = new RamRequestPayload(blockNo, RAM_BLOCK_SIZE); + ParadoxIPPacket ipPacket = createParadoxIpPacket(payload); + IRequest ramRequest = new RamRequest(blockNo, ipPacket); + submitRequest(ramRequest); + } catch (ParadoxException e) { + logger.debug( + "Unable to create request payload from provided bytes to read. blockNo={}, bytes to read={}. Exception={}", + blockNo, RAM_BLOCK_SIZE, e.getMessage()); + } + } + + private String createString(byte[] payloadResult) { + return new String(payloadResult, StandardCharsets.US_ASCII); + } + + @Override + public void executeCommand(String command) { + IP150Command ip150Command = IP150Command.valueOf(command); + switch (ip150Command) { + case LOGIN: + startLoginSequence(); + return; + case LOGOUT: + CommunicationState.LOGOUT.runPhase(this); + return; + case RESET: + CommunicationState.LOGOUT.runPhase(this); + scheduler.schedule(this::startLoginSequence, 5, TimeUnit.SECONDS); + return; + default: + logger.debug("Command {} not implemented.", command); + } + } + + public MemoryMap getMemoryMap() { + return memoryMap; + } + + public Map> getEntityLabelsMap() { + return entityLabelsMap; + } + + @Override + public Map getPartitionLabels() { + return entityLabelsMap.get(EntityType.PARTITION); + } + + @Override + public Map getZoneLabels() { + return entityLabelsMap.get(EntityType.ZONE); + } + + @Override + public void initializeData() { + synchronized (SyncQueue.getInstance()) { + initializeEpromData(); + refreshMemoryMap(); + } + } + + private void initializeEpromData() { + for (int i = 0; i < maxPartitions; i++) { + retrievePartitionLabel(i); + } + for (int i = 0; i < maxZones; i++) { + retrieveZoneLabel(i); + } + } + + public static class EvoCommunicatorBuilder implements ICommunicatorBuilder { + + private final Logger logger = LoggerFactory.getLogger(EvoCommunicatorBuilder.class); + + // Mandatory parameters + private PanelType panelType; + private String ipAddress; + private String ip150Password; + private ScheduledExecutorService scheduler; + + // Non mandatory or with predefined values + private Integer maxPartitions; + private Integer maxZones; + private int tcpPort = 10000; + private String pcPassword = "0000"; + + EvoCommunicatorBuilder(PanelType panelType) { + this.panelType = panelType; + } + + @Override + public IParadoxCommunicator build() { + if (panelType != PanelType.EVO48 && panelType != PanelType.EVO96 && panelType != PanelType.EVO192) { + throw new ParadoxRuntimeException("Unknown or unsupported panel type. Type=" + panelType); + } + + if (ipAddress == null || ipAddress.isEmpty()) { + throw new ParadoxRuntimeException("IP address cannot be empty !"); + } + + if (ip150Password == null || ip150Password.isEmpty()) { + throw new ParadoxRuntimeException("Password for IP150 cannot be empty !"); + } + + if (scheduler == null) { + throw new ParadoxRuntimeException("Scheduler is mandatory parameter !"); + } + + if (maxPartitions == null || maxPartitions < 1) { + this.maxPartitions = panelType.getPartitions(); + } + + if (maxZones == null || maxZones < 1) { + this.maxZones = panelType.getZones(); + } + + try { + return new EvoCommunicator(ipAddress, tcpPort, ip150Password, pcPassword, scheduler, panelType, + maxPartitions, maxZones); + } catch (IOException e) { + logger.warn("Unable to create communicator for Panel={}. Message={}", panelType, e.getMessage()); + throw new ParadoxRuntimeException(e); + } + } + + @Override + public ICommunicatorBuilder withMaxZones(Integer maxZones) { + this.maxZones = maxZones; + return this; + } + + @Override + public ICommunicatorBuilder withMaxPartitions(Integer maxPartitions) { + this.maxPartitions = maxPartitions; + return this; + } + + @Override + public ICommunicatorBuilder withIp150Password(String ip150Password) { + this.ip150Password = ip150Password; + return this; + } + + @Override + public ICommunicatorBuilder withPcPassword(String pcPassword) { + this.pcPassword = pcPassword; + return this; + } + + @Override + public ICommunicatorBuilder withIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + return this; + } + + @Override + public ICommunicatorBuilder withTcpPort(Integer tcpPort) { + this.tcpPort = tcpPort; + return this; + } + + @Override + public ICommunicatorBuilder withScheduler(ScheduledExecutorService scheduler) { + this.scheduler = scheduler; + return this; + } + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/GenericCommunicator.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/GenericCommunicator.java index 1e7e491a57b86..05f35bbcbb3dd 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/GenericCommunicator.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/GenericCommunicator.java @@ -1,149 +1,149 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication; - -import java.io.IOException; -import java.net.UnknownHostException; -import java.util.Collection; -import java.util.concurrent.ScheduledExecutorService; - -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; -import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link GenericCommunicator} Used for the common communication logic for all types of panels. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class GenericCommunicator extends AbstractCommunicator implements IParadoxInitialLoginCommunicator { - - private final Logger logger = LoggerFactory.getLogger(GenericCommunicator.class); - - private final String password; - private final byte[] pcPasswordBytes; - private byte[] panelInfoBytes; - - public GenericCommunicator(String ipAddress, int tcpPort, String ip150Password, String pcPassword, - ScheduledExecutorService scheduler) throws UnknownHostException, IOException { - super(ipAddress, tcpPort, scheduler); - this.password = ip150Password; - this.pcPasswordBytes = ParadoxUtil.stringToBCD(pcPassword); - } - - @Override - public synchronized void startLoginSequence() { - logger.debug("Login sequence started"); - - if (isOnline()) { - logger.debug("Already logged on. No action needed. Returning."); - return; - } - - if (socket.isClosed()) { - try { - initializeSocket(); - } catch (IOException e) { - throw new ParadoxRuntimeException(e); - } - } - - CommunicationState.login(this); - } - - @Override - protected void handleReceivedPacket(IResponse response) { - retryCounter = 0; - IRequest request = response.getRequest(); - logger.trace("Handling response for request={}", request); - - RequestType type = request.getType(); - // Send back the response to proper receive methods - switch (type) { - case LOGON_SEQUENCE: - CommunicationState logonSequenceSender = ((LogonRequest) request).getLogonSequenceSender(); - logonSequenceSender.receiveResponse(this, response); - break; - case RAM: - try { - receiveRamResponse(response); - } catch (ParadoxException e) { - RamRequest ramRequest = (RamRequest) request; - logger.debug("Unable to retrieve RAM message for memory page={}", ramRequest.getRamBlockNumber()); - } - break; - case EPROM: - try { - receiveEpromResponse(response); - } catch (ParadoxException e) { - EpromRequest epromRequest = (EpromRequest) request; - logger.debug("Unable to retrieve EPROM message for entity Type={}, Id={}", - epromRequest.getEntityType(), epromRequest.getEntityId()); - } - break; - } - } - - @Override - public byte[] getPanelInfoBytes() { - return panelInfoBytes; - } - - @Override - public void setPanelInfoBytes(byte[] panelInfoBytes) { - this.panelInfoBytes = panelInfoBytes; - } - - @Override - public byte[] getPcPasswordBytes() { - return pcPasswordBytes; - } - - @Override - public String getPassword() { - return password; - } - - @Override - protected void receiveEpromResponse(IResponse response) throws ParadoxException { - // Nothing to do here. Override in sub class. - } - - @Override - protected void receiveRamResponse(IResponse response) throws ParadoxException { - // Nothing to do here. Override in sub class. - } - - public void refreshMemoryMap() { - // Nothing to do here. Override in sub class. - } - - @Override - public ScheduledExecutorService getScheduler() { - return scheduler; - } - - @Override - public void setListeners(Collection listeners) { - this.listeners = listeners; - } - - @Override - public void updateListeners() { - if (listeners != null && !listeners.isEmpty()) { - listeners.forEach(IDataUpdateListener::update); - } - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication; + +import java.io.IOException; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.concurrent.ScheduledExecutorService; + +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; +import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link GenericCommunicator} Used for the common communication logic for all types of panels. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class GenericCommunicator extends AbstractCommunicator implements IParadoxInitialLoginCommunicator { + + private final Logger logger = LoggerFactory.getLogger(GenericCommunicator.class); + + private final String password; + private final byte[] pcPasswordBytes; + private byte[] panelInfoBytes; + + public GenericCommunicator(String ipAddress, int tcpPort, String ip150Password, String pcPassword, + ScheduledExecutorService scheduler) throws UnknownHostException, IOException { + super(ipAddress, tcpPort, scheduler); + this.password = ip150Password; + this.pcPasswordBytes = ParadoxUtil.stringToBCD(pcPassword); + } + + @Override + public synchronized void startLoginSequence() { + logger.debug("Login sequence started"); + + if (isOnline()) { + logger.debug("Already logged on. No action needed. Returning."); + return; + } + + if (socket.isClosed()) { + try { + initializeSocket(); + } catch (IOException e) { + throw new ParadoxRuntimeException(e); + } + } + + CommunicationState.login(this); + } + + @Override + protected void handleReceivedPacket(IResponse response) { + retryCounter = 0; + IRequest request = response.getRequest(); + logger.trace("Handling response for request={}", request); + + RequestType type = request.getType(); + // Send back the response to proper receive methods + switch (type) { + case LOGON_SEQUENCE: + CommunicationState logonSequenceSender = ((LogonRequest) request).getLogonSequenceSender(); + logonSequenceSender.receiveResponse(this, response); + break; + case RAM: + try { + receiveRamResponse(response); + } catch (ParadoxException e) { + RamRequest ramRequest = (RamRequest) request; + logger.debug("Unable to retrieve RAM message for memory page={}", ramRequest.getRamBlockNumber()); + } + break; + case EPROM: + try { + receiveEpromResponse(response); + } catch (ParadoxException e) { + EpromRequest epromRequest = (EpromRequest) request; + logger.debug("Unable to retrieve EPROM message for entity Type={}, Id={}", + epromRequest.getEntityType(), epromRequest.getEntityId()); + } + break; + } + } + + @Override + public byte[] getPanelInfoBytes() { + return panelInfoBytes; + } + + @Override + public void setPanelInfoBytes(byte[] panelInfoBytes) { + this.panelInfoBytes = panelInfoBytes; + } + + @Override + public byte[] getPcPasswordBytes() { + return pcPasswordBytes; + } + + @Override + public String getPassword() { + return password; + } + + @Override + protected void receiveEpromResponse(IResponse response) throws ParadoxException { + // Nothing to do here. Override in sub class. + } + + @Override + protected void receiveRamResponse(IResponse response) throws ParadoxException { + // Nothing to do here. Override in sub class. + } + + public void refreshMemoryMap() { + // Nothing to do here. Override in sub class. + } + + @Override + public ScheduledExecutorService getScheduler() { + return scheduler; + } + + @Override + public void setListeners(Collection listeners) { + this.listeners = listeners; + } + + @Override + public void updateListeners() { + if (listeners != null && !listeners.isEmpty()) { + listeners.forEach(IDataUpdateListener::update); + } + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IConnectionHandler.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IConnectionHandler.java index 67313604ae289..9514a3901a5c2 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IConnectionHandler.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IConnectionHandler.java @@ -31,5 +31,4 @@ public interface IConnectionHandler { * @param stoListener This method sets a listener which is called in case of socket timeout occurrence. */ void setStoListener(ISocketTimeOutListener stoListener); - } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IP150Command.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IP150Command.java index 487d362666a51..a55657d27aa5c 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IP150Command.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IP150Command.java @@ -1,26 +1,26 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication; - -/** - * The {@link IParadoxCommunicator} is representing the functionality of communication implementation. - * If another Paradox alarm system is used this interface must be implemented. - * - * @author Konstantin Polihronov - Initial contribution - */ -public enum IP150Command { - LOGOUT, - LOGIN, - RESET, - UNIMPLEMENTED -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication; + +/** + * The {@link IParadoxCommunicator} is representing the functionality of communication implementation. + * If another Paradox alarm system is used this interface must be implemented. + * + * @author Konstantin Polihronov - Initial contribution + */ +public enum IP150Command { + LOGOUT, + LOGIN, + RESET, + UNIMPLEMENTED +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IParadoxCommunicator.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IParadoxCommunicator.java index 88db7824d179d..56ebbdc452022 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IParadoxCommunicator.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IParadoxCommunicator.java @@ -1,41 +1,41 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication; - -import java.util.List; -import java.util.Map; - -import org.openhab.binding.paradoxalarm.internal.model.ZoneStateFlags; - -/** - * The {@link IParadoxCommunicator} is representing the functionality of communication implementation. - * If another Paradox alarm system is used this interface must be implemented. - * - * @author Konstantin Polihronov - Initial contribution - */ -public interface IParadoxCommunicator extends IParadoxInitialLoginCommunicator { - - void refreshMemoryMap(); - - List getPartitionFlags(); - - ZoneStateFlags getZoneStateFlags(); - - void executeCommand(String commandAsString); - - Map getPartitionLabels(); - - Map getZoneLabels(); - - void initializeData(); -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication; + +import java.util.List; +import java.util.Map; + +import org.openhab.binding.paradoxalarm.internal.model.ZoneStateFlags; + +/** + * The {@link IParadoxCommunicator} is representing the functionality of communication implementation. + * If another Paradox alarm system is used this interface must be implemented. + * + * @author Konstantin Polihronov - Initial contribution + */ +public interface IParadoxCommunicator extends IParadoxInitialLoginCommunicator { + + void refreshMemoryMap(); + + List getPartitionFlags(); + + ZoneStateFlags getZoneStateFlags(); + + void executeCommand(String commandAsString); + + Map getPartitionLabels(); + + Map getZoneLabels(); + + void initializeData(); +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IParadoxInitialLoginCommunicator.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IParadoxInitialLoginCommunicator.java index e1f917b553b01..e971692ce65cf 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IParadoxInitialLoginCommunicator.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/IParadoxInitialLoginCommunicator.java @@ -1,43 +1,42 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication; - -import java.util.Collection; -import java.util.concurrent.ScheduledExecutorService; - -/** - * The {@link IParadoxInitialLoginCommunicator} is representing the functionality of generic communication. Only - * login/logout - * sequence which is used to determine the Panel type. - * - * @author Konstantin Polihronov - Initial contribution - */ -public interface IParadoxInitialLoginCommunicator extends IConnectionHandler { - - void startLoginSequence(); - - byte[] getPanelInfoBytes(); - - void setPanelInfoBytes(byte[] panelInfoBytes); - - byte[] getPcPasswordBytes(); - - String getPassword(); - - ScheduledExecutorService getScheduler(); - - void setListeners(Collection listeners); - - void updateListeners(); - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication; + +import java.util.Collection; +import java.util.concurrent.ScheduledExecutorService; + +/** + * The {@link IParadoxInitialLoginCommunicator} is representing the functionality of generic communication. Only + * login/logout + * sequence which is used to determine the Panel type. + * + * @author Konstantin Polihronov - Initial contribution + */ +public interface IParadoxInitialLoginCommunicator extends IConnectionHandler { + + void startLoginSequence(); + + byte[] getPanelInfoBytes(); + + void setPanelInfoBytes(byte[] panelInfoBytes); + + byte[] getPcPasswordBytes(); + + String getPassword(); + + ScheduledExecutorService getScheduler(); + + void setListeners(Collection listeners); + + void updateListeners(); +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/MemoryMap.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/MemoryMap.java index 7d8f2958723ff..65ce1925b6c98 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/MemoryMap.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/MemoryMap.java @@ -1,46 +1,46 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication; - -import java.util.ArrayList; -import java.util.List; - -/** - * The {@link MemoryMap} this keeps Paradox RAM map as cached object inside the communicator. - * Every record in the list is byte array which contains 64 byte RAM page. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class MemoryMap { - private List ramCache = new ArrayList<>(); - - public MemoryMap(List ramCache) { - this.ramCache = ramCache; - } - - public List getRamCache() { - return ramCache; - } - - public void setRamCache(List ramCache) { - this.ramCache = ramCache; - } - - public synchronized byte[] getElement(int index) { - return ramCache.get(index); - } - - public synchronized void updateElement(int index, byte[] elementValue) { - ramCache.set(index - 1, elementValue); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication; + +import java.util.ArrayList; +import java.util.List; + +/** + * The {@link MemoryMap} this keeps Paradox RAM map as cached object inside the communicator. + * Every record in the list is byte array which contains 64 byte RAM page. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class MemoryMap { + private List ramCache = new ArrayList<>(); + + public MemoryMap(List ramCache) { + this.ramCache = ramCache; + } + + public List getRamCache() { + return ramCache; + } + + public void setRamCache(List ramCache) { + this.ramCache = ramCache; + } + + public synchronized byte[] getElement(int index) { + return ramCache.get(index); + } + + public synchronized void updateElement(int index, byte[] elementValue) { + ramCache.set(index - 1, elementValue); + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/ParadoxBuilderFactory.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/ParadoxBuilderFactory.java index b6b24e68923df..cb88f004af24d 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/ParadoxBuilderFactory.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/ParadoxBuilderFactory.java @@ -1,41 +1,41 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication; - -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; -import org.openhab.binding.paradoxalarm.internal.model.PanelType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link ParadoxBuilderFactory} used to create the proper communicator builder objects for different panel - * types. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxBuilderFactory { - - private final Logger logger = LoggerFactory.getLogger(ParadoxBuilderFactory.class); - - public ICommunicatorBuilder createBuilder(PanelType panelType) { - switch (panelType) { - case EVO48: - case EVO96: - case EVO192: - logger.debug("Creating new builder for Paradox {} system", panelType); - return new EvoCommunicator.EvoCommunicatorBuilder(panelType); - default: - throw new ParadoxRuntimeException("Unsupported panel type: " + panelType); - } - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication; + +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; +import org.openhab.binding.paradoxalarm.internal.model.PanelType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ParadoxBuilderFactory} used to create the proper communicator builder objects for different panel + * types. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxBuilderFactory { + + private final Logger logger = LoggerFactory.getLogger(ParadoxBuilderFactory.class); + + public ICommunicatorBuilder createBuilder(PanelType panelType) { + switch (panelType) { + case EVO48: + case EVO96: + case EVO192: + logger.debug("Creating new builder for Paradox {} system", panelType); + return new EvoCommunicator.EvoCommunicatorBuilder(panelType); + default: + throw new ParadoxRuntimeException("Unsupported panel type: " + panelType); + } + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/RamRequest.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/RamRequest.java index e22a5e2761aef..1eba27a6ebd81 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/RamRequest.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/RamRequest.java @@ -36,6 +36,4 @@ public int getRamBlockNumber() { public String toString() { return "RamRequest [getType()=" + getType() + ", getRamBlockNumber()=" + getRamBlockNumber() + "]"; } - - } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/Response.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/Response.java index e1f275a80c5f5..40b0503eecce5 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/Response.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/Response.java @@ -41,5 +41,4 @@ public byte[] getPayload() { public IRequest getRequest() { return request; } - } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/SyncQueue.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/SyncQueue.java index 7d87253f62955..9f0bf07504962 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/SyncQueue.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/SyncQueue.java @@ -77,7 +77,6 @@ public synchronized IRequest removeSendRequest() { return request; } - public synchronized IRequest peekSendQueue() { return sendQueue.peek(); } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/EpromRequestPayload.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/EpromRequestPayload.java index a11fbe7183b65..648cbfa44e69c 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/EpromRequestPayload.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/EpromRequestPayload.java @@ -1,50 +1,49 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication.messages; - -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; -import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link EpromRequestPayload} Object representing payload of IP packet which retrieves data from Paradox EPROM - * - * @author Konstantin Polihronov - Initial contribution - */ -public class EpromRequestPayload extends MemoryRequestPayload implements IPPacketPayload { - - private final Logger logger = LoggerFactory.getLogger(EpromRequestPayload.class); - - public EpromRequestPayload(int address, byte bytesToRead) throws ParadoxException { - super(address, bytesToRead); - } - - @Override - protected byte calculateControlByte() { - int address = getAddress(); - logTraceHexFormatted("Address: {}", address); - - byte controlByte = 0x00; - byte[] shortToByteArray = ParadoxUtil.intToByteArray(address); - if (shortToByteArray.length > 2) { - byte bit16 = ParadoxUtil.getBit(address, 16); - controlByte |= bit16 << 0; - byte bit17 = ParadoxUtil.getBit(address, 17); - controlByte |= bit17 << 1; - } - logger.trace("ControlByte value: {}", controlByte); - return controlByte; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication.messages; + +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; +import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EpromRequestPayload} Object representing payload of IP packet which retrieves data from Paradox EPROM + * + * @author Konstantin Polihronov - Initial contribution + */ +public class EpromRequestPayload extends MemoryRequestPayload implements IPPacketPayload { + + private final Logger logger = LoggerFactory.getLogger(EpromRequestPayload.class); + + public EpromRequestPayload(int address, byte bytesToRead) throws ParadoxException { + super(address, bytesToRead); + } + + @Override + protected byte calculateControlByte() { + int address = getAddress(); + logTraceHexFormatted("Address: {}", address); + + byte controlByte = 0x00; + byte[] shortToByteArray = ParadoxUtil.intToByteArray(address); + if (shortToByteArray.length > 2) { + byte bit16 = ParadoxUtil.getBit(address, 16); + controlByte |= bit16 << 0; + byte bit17 = ParadoxUtil.getBit(address, 17); + controlByte |= bit17 << 1; + } + logger.trace("ControlByte value: {}", controlByte); + return controlByte; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/HeaderCommand.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/HeaderCommand.java index 7cf0e3745f677..f9880f1635e54 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/HeaderCommand.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/HeaderCommand.java @@ -1,48 +1,48 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication.messages; - -/** - * {@link HeaderCommand} - * From Jean's(Jean_Henning from community) excel sheet: - * 0x00: Serial/pass through command any other: IP module command - * 0xF0: Connect to IP module - * 0xF2: (unknown, part of login sequence) - * 0xF3: (unknown, part of login sequence) - * 0xF4: (unknown) - * 0xF8: (unknown, occurs after serial connection is initiated with the panel) - * 0xFB: Multicommand - * 0xFF: Disconnect from IP module (byte 00 in the response payload MUST be 01 to indicate a successful disconnect) - * - * @author Konstantin Polihronov - Initial contribution - */ -public enum HeaderCommand { - SERIAL((byte) 0x00), - CONNECT_TO_IP_MODULE((byte) 0xF0), - LOGIN_COMMAND1((byte) 0xF2), - LOGIN_COMMAND2((byte) 0xF3), - UNKNOWN1((byte) 0xF4), - SERIAL_CONNECTION_INITIATED((byte) 0xF8), - MULTI_COMMAND((byte) 0xFB), - DISCONNECT((byte) 0xFF); - - private byte value; - - HeaderCommand(byte value) { - this.value = value; - } - - public byte getValue() { - return value; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication.messages; + +/** + * {@link HeaderCommand} + * From Jean's(Jean_Henning from community) excel sheet: + * 0x00: Serial/pass through command any other: IP module command + * 0xF0: Connect to IP module + * 0xF2: (unknown, part of login sequence) + * 0xF3: (unknown, part of login sequence) + * 0xF4: (unknown) + * 0xF8: (unknown, occurs after serial connection is initiated with the panel) + * 0xFB: Multicommand + * 0xFF: Disconnect from IP module (byte 00 in the response payload MUST be 01 to indicate a successful disconnect) + * + * @author Konstantin Polihronov - Initial contribution + */ +public enum HeaderCommand { + SERIAL((byte) 0x00), + CONNECT_TO_IP_MODULE((byte) 0xF0), + LOGIN_COMMAND1((byte) 0xF2), + LOGIN_COMMAND2((byte) 0xF3), + UNKNOWN1((byte) 0xF4), + SERIAL_CONNECTION_INITIATED((byte) 0xF8), + MULTI_COMMAND((byte) 0xFB), + DISCONNECT((byte) 0xFF); + + private byte value; + + HeaderCommand(byte value) { + this.value = value; + } + + public byte getValue() { + return value; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/HeaderMessageType.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/HeaderMessageType.java index 9e970e7d8f010..5db8a9c1ed3dd 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/HeaderMessageType.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/HeaderMessageType.java @@ -1,39 +1,39 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication.messages; - -/** - * From Jean's excel: - * 0x03: IP Request - * 0x01: IP Response - * 0x04: Serial/pass through command request - * 0x02: Serial/pass through command response - * - * @author Konstantin Polihronov - Initial contribution - */ -public enum HeaderMessageType { - IP_REQUEST((byte) 0x03), - IP_RESPONSE((byte) 0x01), - SERIAL_PASSTHRU_REQUEST((byte) 0x04), - SERIAL_PASSTHRU_RESPONSE((byte) 0x02); - - private byte value; - - HeaderMessageType(byte value) { - this.value = value; - } - - public byte getValue() { - return value; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication.messages; + +/** + * From Jean's excel: + * 0x03: IP Request + * 0x01: IP Response + * 0x04: Serial/pass through command request + * 0x02: Serial/pass through command response + * + * @author Konstantin Polihronov - Initial contribution + */ +public enum HeaderMessageType { + IP_REQUEST((byte) 0x03), + IP_RESPONSE((byte) 0x01), + SERIAL_PASSTHRU_REQUEST((byte) 0x04), + SERIAL_PASSTHRU_RESPONSE((byte) 0x02); + + private byte value; + + HeaderMessageType(byte value) { + this.value = value; + } + + public byte getValue() { + return value; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/IPPacketPayload.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/IPPacketPayload.java index 8ea56ff552d5d..4d5ce3c7deeb7 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/IPPacketPayload.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/IPPacketPayload.java @@ -1,24 +1,24 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication.messages; - -/** - * Interface representing what we need to add IPPacketPayload. - * Not sure if we need it as it needs only getBytes() method so far. - * - * @author Konstantin Polihronov - Initial contribution - */ -public interface IPPacketPayload { - - byte[] getBytes(); -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication.messages; + +/** + * Interface representing what we need to add IPPacketPayload. + * Not sure if we need it as it needs only getBytes() method so far. + * + * @author Konstantin Polihronov - Initial contribution + */ +public interface IPPacketPayload { + + byte[] getBytes(); +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/IpMessagesConstants.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/IpMessagesConstants.java index 66c3f02e8e763..425d051515aa0 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/IpMessagesConstants.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/IpMessagesConstants.java @@ -1,28 +1,29 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication.messages; - -/** - * Constants representing packet headers / messages which are easier written as static final byte arrays - * - * @author Konstantin Polihronov - Initial contribution - */ -public class IpMessagesConstants { - - public static final byte[] UNKNOWN_IP150_REQUEST_MESSAGE01 = { 0x0A, 0x50, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x59 }; - - public static final byte[] EPROM_REQUEST_HEADER = { (byte) 0xAA, 0x08, 0x00, 0x04, 0x08, 0x00, 0x00, 0x14, (byte) 0xEE, - (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE }; - - public static final byte[] LOGOUT_MESAGE_BYTES = new byte[] { 0x00, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00 }; -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication.messages; + +/** + * Constants representing packet headers / messages which are easier written as static final byte arrays + * + * @author Konstantin Polihronov - Initial contribution + */ +public class IpMessagesConstants { + + public static final byte[] UNKNOWN_IP150_REQUEST_MESSAGE01 = { 0x0A, 0x50, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x59 }; + + public static final byte[] EPROM_REQUEST_HEADER = { (byte) 0xAA, 0x08, 0x00, 0x04, 0x08, 0x00, 0x00, 0x14, + (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE, (byte) 0xEE }; + + public static final byte[] LOGOUT_MESAGE_BYTES = new byte[] { 0x00, 0x07, 0x05, 0x00, 0x00, 0x00, 0x00 }; +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/MemoryRequestPayload.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/MemoryRequestPayload.java index 62b78e5d9b7be..2b41dabadb284 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/MemoryRequestPayload.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/MemoryRequestPayload.java @@ -1,89 +1,88 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication.messages; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; -import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link EpromRequestPayload} Abstract class which contains common logic used in RAM and EPROM payload generation - * classes. - * - * @author Konstantin Polihronov - Initial contribution - */ -public abstract class MemoryRequestPayload implements IPPacketPayload { - - private final Logger logger = LoggerFactory.getLogger(MemoryRequestPayload.class); - - private static final short MESSAGE_START = (short) ((0x50 << 8) | 0x08); - - private int address; - private byte bytesToRead; - - public MemoryRequestPayload(int address, byte bytesToRead) throws ParadoxException { - if (bytesToRead < 1 || bytesToRead > 64) { - throw new ParadoxException("Invalid bytes to read. Valid values are 1 to 64."); - } - - this.address = address; - this.bytesToRead = bytesToRead; - - logTraceHexFormatted("MessageStart: {}", MESSAGE_START); - } - - protected abstract byte calculateControlByte(); - - @Override - public byte[] getBytes() { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - - outputStream.write(ParadoxUtil.shortToByteArray(MESSAGE_START)); - outputStream.write(calculateControlByte()); - outputStream.write((byte) 0x00); - - outputStream.write(ParadoxUtil.shortToByteArray((short) address)); - - outputStream.write(bytesToRead); - - // The bellow 0x00 is dummy which will be overwritten by the checksum - outputStream.write(0x00); - byte[] byteArray = outputStream.toByteArray(); - - return byteArray; - } catch (IOException e) { - throw new ParadoxRuntimeException("Unable to create byte array stream.", e); - } - } - - protected int getAddress() { - return address; - } - - protected void logTraceHexFormatted(String text, int address) { - logTraceOptional(text, "0x%02X,\t", address); - } - - private void logTraceOptional(String text, String format, int address) { - if (logger.isTraceEnabled()) { - logger.trace("Address: {}", String.format(format, address)); - } - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication.messages; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; +import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EpromRequestPayload} Abstract class which contains common logic used in RAM and EPROM payload generation + * classes. + * + * @author Konstantin Polihronov - Initial contribution + */ +public abstract class MemoryRequestPayload implements IPPacketPayload { + + private final Logger logger = LoggerFactory.getLogger(MemoryRequestPayload.class); + + private static final short MESSAGE_START = (short) ((0x50 << 8) | 0x08); + + private int address; + private byte bytesToRead; + + public MemoryRequestPayload(int address, byte bytesToRead) throws ParadoxException { + if (bytesToRead < 1 || bytesToRead > 64) { + throw new ParadoxException("Invalid bytes to read. Valid values are 1 to 64."); + } + + this.address = address; + this.bytesToRead = bytesToRead; + + logTraceHexFormatted("MessageStart: {}", MESSAGE_START); + } + + protected abstract byte calculateControlByte(); + + @Override + public byte[] getBytes() { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + outputStream.write(ParadoxUtil.shortToByteArray(MESSAGE_START)); + outputStream.write(calculateControlByte()); + outputStream.write((byte) 0x00); + + outputStream.write(ParadoxUtil.shortToByteArray((short) address)); + + outputStream.write(bytesToRead); + + // The bellow 0x00 is dummy which will be overwritten by the checksum + outputStream.write(0x00); + byte[] byteArray = outputStream.toByteArray(); + + return byteArray; + } catch (IOException e) { + throw new ParadoxRuntimeException("Unable to create byte array stream.", e); + } + } + + protected int getAddress() { + return address; + } + + protected void logTraceHexFormatted(String text, int address) { + logTraceOptional(text, "0x%02X,\t", address); + } + + private void logTraceOptional(String text, String format, int address) { + if (logger.isTraceEnabled()) { + logger.trace("Address: {}", String.format(format, address)); + } + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/ParadoxIPPacket.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/ParadoxIPPacket.java index da3a511bdeee9..ceebff426d3a0 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/ParadoxIPPacket.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/ParadoxIPPacket.java @@ -1,198 +1,198 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication.messages; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; - -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; -import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; - -/** - * The {@link ParadoxIPPacket} This class is object representing a full IP request packet. Header and payload together. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxIPPacket implements IPPacketPayload { - - public static final byte[] EMPTY_PAYLOAD = new byte[0]; - - /** - * Start of header - always 0xAA - */ - private byte startOfHeader = (byte) 0xAA; - - /** - * Payload length - 2 bytes (LL HH) - */ - private short payloadLength = 0; - - /** - * "Message Type: 0x01: IP responses 0x02: Serial/pass through cmd response - * 0x03: IP requests 0x04: Serial/pass through cmd requests" - */ - private byte messageType = 0x03; - - /** - * "IP Encryption 0x08: Disabled 0x09: Enabled" - */ - private byte encryption = 0x08; - private byte command = 0; - private byte subCommand = 0; - private byte unknown0 = 0x0A; - - /** - * Padding bytes to fill the header to 16 bytes with 0xEE. - */ - private long theRest = 0xEEEEEEEEEEEEEEEEl; - private byte[] payload; - private boolean isChecksumRequired; - - public ParadoxIPPacket(IPPacketPayload payload) { - this(payload.getBytes(), true); - } - - public ParadoxIPPacket(String payload, boolean isChecksumRequired) { - this(payload.getBytes(StandardCharsets.US_ASCII), isChecksumRequired); - } - - public ParadoxIPPacket(byte[] payload, boolean isChecksumRequired) { - this.isChecksumRequired = isChecksumRequired; - - if (payload == null) { - this.payload = new byte[0]; - this.payloadLength = 0; - } else { - this.payload = payload; - this.payloadLength = (short) payload.length; - } - - // TODO: Figure out how to fill up to 16, 32, 48, etc sizes with 0xEE - // if (payload.length < 16) { - // this.payload = extendPayload(16, payload); - // } else { - // } - } - - @Override - public byte[] getBytes() { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - - outputStream.write(startOfHeader); - outputStream.write(ByteBuffer.allocate(Short.SIZE / Byte.SIZE).order(ByteOrder.LITTLE_ENDIAN) - .putShort(payloadLength).array()); - outputStream.write(messageType); - outputStream.write(encryption); - outputStream.write(command); - outputStream.write(subCommand); - outputStream.write(unknown0); - outputStream.write(ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(theRest).array()); - outputStream.write(payload); - byte[] byteArray = outputStream.toByteArray(); - - if (isChecksumRequired) { - byteArray[byteArray.length - 1] = ParadoxUtil.calculateChecksum(payload); - } - - return byteArray; - } catch (IOException e) { - throw new ParadoxRuntimeException("Unable to create byte array stream.", e); - } - } - - public byte getStartOfHeader() { - return startOfHeader; - } - - public ParadoxIPPacket setStartOfHeader(byte startOfHeader) { - this.startOfHeader = startOfHeader; - return this; - } - - public short getPayloadLength() { - return payloadLength; - } - - public ParadoxIPPacket setPayloadLength(short payloadLength) { - this.payloadLength = payloadLength; - return this; - } - - public byte getMessageType() { - return messageType; - } - - public ParadoxIPPacket setMessageType(byte messageType) { - this.messageType = messageType; - return this; - } - - public ParadoxIPPacket setMessageType(HeaderMessageType messageType) { - this.messageType = messageType.getValue(); - return this; - } - - public byte getEncryption() { - return encryption; - } - - public ParadoxIPPacket setEncryption(byte encryption) { - this.encryption = encryption; - return this; - } - - public byte getCommand() { - return command; - } - - public ParadoxIPPacket setCommand(HeaderCommand command) { - this.command = command.getValue(); - return this; - } - - public ParadoxIPPacket setCommand(byte command) { - this.command = command; - return this; - } - - public byte getSubCommand() { - return subCommand; - } - - public ParadoxIPPacket setSubCommand(byte subCommand) { - this.subCommand = subCommand; - return this; - } - - public byte getUnknown0() { - return unknown0; - } - - public ParadoxIPPacket setUnknown0(byte unknown0) { - this.unknown0 = unknown0; - return this; - } - - public long getTheRest() { - return theRest; - } - - public ParadoxIPPacket setTheRest(long theRest) { - this.theRest = theRest; - return this; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication.messages; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; + +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; +import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; + +/** + * The {@link ParadoxIPPacket} This class is object representing a full IP request packet. Header and payload together. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxIPPacket implements IPPacketPayload { + + public static final byte[] EMPTY_PAYLOAD = new byte[0]; + + /** + * Start of header - always 0xAA + */ + private byte startOfHeader = (byte) 0xAA; + + /** + * Payload length - 2 bytes (LL HH) + */ + private short payloadLength = 0; + + /** + * "Message Type: 0x01: IP responses 0x02: Serial/pass through cmd response + * 0x03: IP requests 0x04: Serial/pass through cmd requests" + */ + private byte messageType = 0x03; + + /** + * "IP Encryption 0x08: Disabled 0x09: Enabled" + */ + private byte encryption = 0x08; + private byte command = 0; + private byte subCommand = 0; + private byte unknown0 = 0x0A; + + /** + * Padding bytes to fill the header to 16 bytes with 0xEE. + */ + private long theRest = 0xEEEEEEEEEEEEEEEEl; + private byte[] payload; + private boolean isChecksumRequired; + + public ParadoxIPPacket(IPPacketPayload payload) { + this(payload.getBytes(), true); + } + + public ParadoxIPPacket(String payload, boolean isChecksumRequired) { + this(payload.getBytes(StandardCharsets.US_ASCII), isChecksumRequired); + } + + public ParadoxIPPacket(byte[] payload, boolean isChecksumRequired) { + this.isChecksumRequired = isChecksumRequired; + + if (payload == null) { + this.payload = new byte[0]; + this.payloadLength = 0; + } else { + this.payload = payload; + this.payloadLength = (short) payload.length; + } + + // TODO: Figure out how to fill up to 16, 32, 48, etc sizes with 0xEE + // if (payload.length < 16) { + // this.payload = extendPayload(16, payload); + // } else { + // } + } + + @Override + public byte[] getBytes() { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + outputStream.write(startOfHeader); + outputStream.write(ByteBuffer.allocate(Short.SIZE / Byte.SIZE).order(ByteOrder.LITTLE_ENDIAN) + .putShort(payloadLength).array()); + outputStream.write(messageType); + outputStream.write(encryption); + outputStream.write(command); + outputStream.write(subCommand); + outputStream.write(unknown0); + outputStream.write(ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(theRest).array()); + outputStream.write(payload); + byte[] byteArray = outputStream.toByteArray(); + + if (isChecksumRequired) { + byteArray[byteArray.length - 1] = ParadoxUtil.calculateChecksum(payload); + } + + return byteArray; + } catch (IOException e) { + throw new ParadoxRuntimeException("Unable to create byte array stream.", e); + } + } + + public byte getStartOfHeader() { + return startOfHeader; + } + + public ParadoxIPPacket setStartOfHeader(byte startOfHeader) { + this.startOfHeader = startOfHeader; + return this; + } + + public short getPayloadLength() { + return payloadLength; + } + + public ParadoxIPPacket setPayloadLength(short payloadLength) { + this.payloadLength = payloadLength; + return this; + } + + public byte getMessageType() { + return messageType; + } + + public ParadoxIPPacket setMessageType(byte messageType) { + this.messageType = messageType; + return this; + } + + public ParadoxIPPacket setMessageType(HeaderMessageType messageType) { + this.messageType = messageType.getValue(); + return this; + } + + public byte getEncryption() { + return encryption; + } + + public ParadoxIPPacket setEncryption(byte encryption) { + this.encryption = encryption; + return this; + } + + public byte getCommand() { + return command; + } + + public ParadoxIPPacket setCommand(HeaderCommand command) { + this.command = command.getValue(); + return this; + } + + public ParadoxIPPacket setCommand(byte command) { + this.command = command; + return this; + } + + public byte getSubCommand() { + return subCommand; + } + + public ParadoxIPPacket setSubCommand(byte subCommand) { + this.subCommand = subCommand; + return this; + } + + public byte getUnknown0() { + return unknown0; + } + + public ParadoxIPPacket setUnknown0(byte unknown0) { + this.unknown0 = unknown0; + return this; + } + + public long getTheRest() { + return theRest; + } + + public ParadoxIPPacket setTheRest(long theRest) { + this.theRest = theRest; + return this; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/RamRequestPayload.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/RamRequestPayload.java index 6ffb14ce381da..beeab01ba1d96 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/RamRequestPayload.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/communication/messages/RamRequestPayload.java @@ -1,36 +1,35 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.communication.messages; - -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; -import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; - -/** - * The {@link RamRequestPayload} Object representing payload of IP packet which retrieves data from Paradox RAM - * - * @author Konstantin Polihronov - Initial contribution - */ -public class RamRequestPayload extends MemoryRequestPayload implements IPPacketPayload { - - private static final byte CONTROL_BYTE = ParadoxUtil.setBit((byte) 0, 7, 1); - - public RamRequestPayload(int address, byte bytesToRead) throws ParadoxException { - super(address, bytesToRead); - } - - @Override - protected byte calculateControlByte() { - return CONTROL_BYTE; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.communication.messages; + +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; +import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; + +/** + * The {@link RamRequestPayload} Object representing payload of IP packet which retrieves data from Paradox RAM + * + * @author Konstantin Polihronov - Initial contribution + */ +public class RamRequestPayload extends MemoryRequestPayload implements IPPacketPayload { + + private static final byte CONTROL_BYTE = ParadoxUtil.setBit((byte) 0, 7, 1); + + public RamRequestPayload(int address, byte bytesToRead) throws ParadoxException { + super(address, bytesToRead); + } + + @Override + protected byte calculateControlByte() { + return CONTROL_BYTE; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/discovery/ParadoxDiscoveryService.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/discovery/ParadoxDiscoveryService.java index 235a6ce2fef1d..e0d6043aed705 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/discovery/ParadoxDiscoveryService.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/discovery/ParadoxDiscoveryService.java @@ -111,5 +111,4 @@ private void discoverZones(List zones) { thingDiscovered(result); }); } - } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/exceptions/ParadoxException.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/exceptions/ParadoxException.java index ba8a21a571b11..cd8f6001e60fa 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/exceptions/ParadoxException.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/exceptions/ParadoxException.java @@ -1,41 +1,39 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.exceptions; - -/** - * The {@link ParadoxException} Wrapper of Exception class. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxException extends Exception { - - private static final long serialVersionUID = -5771699322577106346L; - - public ParadoxException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } - - public ParadoxException(String message, Throwable cause) { - super(message, cause); - } - - public ParadoxException(String message) { - super(message); - } - - public ParadoxException(Throwable cause) { - super(cause); - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.exceptions; + +/** + * The {@link ParadoxException} Wrapper of Exception class. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxException extends Exception { + + private static final long serialVersionUID = -5771699322577106346L; + + public ParadoxException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public ParadoxException(String message, Throwable cause) { + super(message, cause); + } + + public ParadoxException(String message) { + super(message); + } + + public ParadoxException(Throwable cause) { + super(cause); + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/exceptions/ParadoxRuntimeException.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/exceptions/ParadoxRuntimeException.java index d48e64e17bff8..6d57de4001569 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/exceptions/ParadoxRuntimeException.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/exceptions/ParadoxRuntimeException.java @@ -29,7 +29,8 @@ public ParadoxRuntimeException() { super(); } - public ParadoxRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + public ParadoxRuntimeException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } @@ -38,7 +39,7 @@ public ParadoxRuntimeException(String message, Throwable cause) { } public ParadoxRuntimeException(Throwable cause) { - this("This is a Paradox Binding wrapper of RuntimeException. For detailed error message, see the original exception. Short message: " + cause.getMessage(), cause); + this("This is a Paradox Binding wrapper of RuntimeException. For detailed error message, see the original exception. Short message: " + + cause.getMessage(), cause); } - } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/EntityBaseHandler.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/EntityBaseHandler.java index bed4a9434b92b..b1e236accf9f2 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/EntityBaseHandler.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/EntityBaseHandler.java @@ -1,80 +1,81 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.handlers; - -import java.util.concurrent.TimeUnit; - -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link EntityBaseHandler} abstract handler class that contains common logic for entities. - * - * @author Konstantin Polihronov - Initial contribution - */ -public abstract class EntityBaseHandler extends BaseThingHandler { - - private static final long INITIAL_DELAY_SECONDS = 20; - - private final Logger logger = LoggerFactory.getLogger(EntityBaseHandler.class); - - protected EntityConfiguration config; - - public EntityBaseHandler(Thing thing) { - super(thing); - } - - @Override - public void initialize() { - logger.debug("Start initializing. {}", thing.getLabel()); - updateStatus(ThingStatus.UNKNOWN); - - config = getConfigAs(EntityConfiguration.class); - - scheduler.schedule(this::initializeDelayed, INITIAL_DELAY_SECONDS, TimeUnit.SECONDS); - } - - private void initializeDelayed() { - logger.trace("Start initializeDelayed() in {}", getThing().getUID()); - ParadoxPanel panel = ParadoxPanel.getInstance(); - if (!panel.isPanelSupported()) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Panel " + panel.getPanelInformation().getPanelType().name() + " is not supported."); - } - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - if (command instanceof RefreshType) { - if (ThingStatus.ONLINE == getThing().getStatus()) { - updateEntity(); - } else { - logger.debug("Received REFRESH command but {} has the following detailed status {}", getThing().getUID(), getThing().getStatusInfo()); - } - } - } - - protected abstract void updateEntity(); - - protected int calculateEntityIndex() { - return Math.max(0, config.getId() - 1); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.handlers; + +import java.util.concurrent.TimeUnit; + +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link EntityBaseHandler} abstract handler class that contains common logic for entities. + * + * @author Konstantin Polihronov - Initial contribution + */ +public abstract class EntityBaseHandler extends BaseThingHandler { + + private static final long INITIAL_DELAY_SECONDS = 20; + + private final Logger logger = LoggerFactory.getLogger(EntityBaseHandler.class); + + protected EntityConfiguration config; + + public EntityBaseHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + logger.debug("Start initializing. {}", thing.getLabel()); + updateStatus(ThingStatus.UNKNOWN); + + config = getConfigAs(EntityConfiguration.class); + + scheduler.schedule(this::initializeDelayed, INITIAL_DELAY_SECONDS, TimeUnit.SECONDS); + } + + private void initializeDelayed() { + logger.trace("Start initializeDelayed() in {}", getThing().getUID()); + ParadoxPanel panel = ParadoxPanel.getInstance(); + if (!panel.isPanelSupported()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Panel " + panel.getPanelInformation().getPanelType().name() + " is not supported."); + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (command instanceof RefreshType) { + if (ThingStatus.ONLINE == getThing().getStatus()) { + updateEntity(); + } else { + logger.debug("Received REFRESH command but {} has the following detailed status {}", + getThing().getUID(), getThing().getStatusInfo()); + } + } + } + + protected abstract void updateEntity(); + + protected int calculateEntityIndex() { + return Math.max(0, config.getId() - 1); + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/EntityConfiguration.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/EntityConfiguration.java index 9762b325be0a2..27dc0bdb35435 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/EntityConfiguration.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/EntityConfiguration.java @@ -1,26 +1,26 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.handlers; - -/** - * The {@link EntityConfiguration} Common configuration class used by all entities at the moment. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class EntityConfiguration { - private int id; - - public int getId() { - return id; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.handlers; + +/** + * The {@link EntityConfiguration} Common configuration class used by all entities at the moment. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class EntityConfiguration { + private int id; + + public int getId() { + return id; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxAlarmBindingConstants.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxAlarmBindingConstants.java index 13203997792f0..0d794cdf562fd 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxAlarmBindingConstants.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxAlarmBindingConstants.java @@ -1,94 +1,93 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.handlers; - -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.ThingTypeUID; - -/** - * The {@link ParadoxAlarmBindingConstants} class defines common constants, which are - * used across the whole binding. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class ParadoxAlarmBindingConstants { - - public static final String BINDING_ID = "paradoxalarm"; - - public static final String PARADOX_COMMUNICATOR_THING_TYPE_ID = "ip150"; - - public static final String PARADOX_PANEL_THING_TYPE_ID = "panel"; - - public static final String PARTITION_THING_TYPE_ID = "partition"; - - public static final String ZONE_THING_TYPE_ID = "zone"; - - // List of all Thing Type UIDs - public static final ThingTypeUID COMMUNICATOR_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, - PARADOX_COMMUNICATOR_THING_TYPE_ID); - public static final ThingTypeUID PANEL_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, PARADOX_PANEL_THING_TYPE_ID); - public static final ThingTypeUID PARTITION_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, PARTITION_THING_TYPE_ID); - public static final ThingTypeUID ZONE_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, ZONE_THING_TYPE_ID); - - public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( - Stream.of(COMMUNICATOR_THING_TYPE_UID, PANEL_THING_TYPE_UID, PARTITION_THING_TYPE_UID, ZONE_THING_TYPE_UID) - .collect(Collectors.toSet())); - - // List of all Channel UIDs - public static final String IP150_COMMUNICATION_COMMAND_CHANNEL_UID = "communicationCommand"; - - public static final String PANEL_STATE_CHANNEL_UID = "state"; - public static final String PANEL_SERIAL_NUMBER_PROPERTY_NAME = "serialNumber"; - public static final String PANEL_TYPE_PROPERTY_NAME = "panelType"; - public static final String PANEL_HARDWARE_VERSION_PROPERTY_NAME = "hardwareVersion"; - public static final String PANEL_APPLICATION_VERSION_PROPERTY_NAME = "applicationVersion"; - public static final String PANEL_BOOTLOADER_VERSION_PROPERTY_NAME = "bootloaderVersion"; - - public static final String PARTITION_LABEL_CHANNEL_UID = "partitionLabel"; - public static final String PARTITION_STATE_CHANNEL_UID = "state"; - @Deprecated // After implementation of channels for every possible state, the summarized additional states is no - // longer needed. We'll keep it for backward compatibility - public static final String PARTITION_ADDITIONAL_STATES_CHANNEL_UID = "additionalStates"; - public static final String PARTITION_READY_TO_ARM_CHANNEL_UID = "readyToArm"; - public static final String PARTITION_IN_EXIT_DELAY_CHANNEL_UID = "inExitDelay"; - public static final String PARTITION_IN_ENTRY_DELAY_CHANNEL_UID = "inEntryDelay"; - public static final String PARTITION_IN_TROUBLE_CHANNEL_UID = "inTrouble"; - public static final String PARTITION_ALARM_IN_MEMORY_CHANNEL_UID = "alarmInMemory"; - public static final String PARTITION_ZONE_BYPASS_CHANNEL_UID = "zoneBypass"; - public static final String PARTITION_ZONE_IN_TAMPER_CHANNEL_UID = "zoneInTamperTrouble"; - public static final String PARTITION_ZONE_IN_LOW_BATTERY_CHANNEL_UID = "zoneInLowBatteryTrouble"; - public static final String PARTITION_ZONE_IN_FIRE_LOOP_CHANNEL_UID = "zoneInFireLoopTrouble"; - public static final String PARTITION_ZONE_IN_SUPERVISION_TROUBLE_CHANNEL_UID = "zoneInSupervisionTrouble"; - public static final String PARTITION_STAY_INSTANT_READY_CHANNEL_UID = "stayInstantReady"; - public static final String PARTITION_FORCE_READY_CHANNEL_UID = "forceReady"; - public static final String PARTITION_BYPASS_READY_CHANNEL_UID = "bypassReady"; - public static final String PARTITION_INHIBIT_READY_CHANNEL_UID = "inhibitReady"; - public static final String PARTITION_ALL_ZONES_CLOSED_CHANNEL_UID = "allZonesClosed"; - - public static final String ZONE_LABEL_CHANNEL_UID = "zoneLabel"; - public static final String ZONE_OPENED_CHANNEL_UID = "opened"; - public static final String ZONE_TAMPERED_CHANNEL_UID = "tampered"; - public static final String ZONE_LOW_BATTERY_CHANNEL_UID = "lowBattery"; - - // Misc constants - public static final StringType STATE_OFFLINE = new StringType("Offline"); - public static final StringType STATE_ONLINE = new StringType("Online"); - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.handlers; + +import java.util.Collections; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link ParadoxAlarmBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class ParadoxAlarmBindingConstants { + + public static final String BINDING_ID = "paradoxalarm"; + + public static final String PARADOX_COMMUNICATOR_THING_TYPE_ID = "ip150"; + + public static final String PARADOX_PANEL_THING_TYPE_ID = "panel"; + + public static final String PARTITION_THING_TYPE_ID = "partition"; + + public static final String ZONE_THING_TYPE_ID = "zone"; + + // List of all Thing Type UIDs + public static final ThingTypeUID COMMUNICATOR_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, + PARADOX_COMMUNICATOR_THING_TYPE_ID); + public static final ThingTypeUID PANEL_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, PARADOX_PANEL_THING_TYPE_ID); + public static final ThingTypeUID PARTITION_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, PARTITION_THING_TYPE_ID); + public static final ThingTypeUID ZONE_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, ZONE_THING_TYPE_ID); + + public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( + Stream.of(COMMUNICATOR_THING_TYPE_UID, PANEL_THING_TYPE_UID, PARTITION_THING_TYPE_UID, ZONE_THING_TYPE_UID) + .collect(Collectors.toSet())); + + // List of all Channel UIDs + public static final String IP150_COMMUNICATION_COMMAND_CHANNEL_UID = "communicationCommand"; + + public static final String PANEL_STATE_CHANNEL_UID = "state"; + public static final String PANEL_SERIAL_NUMBER_PROPERTY_NAME = "serialNumber"; + public static final String PANEL_TYPE_PROPERTY_NAME = "panelType"; + public static final String PANEL_HARDWARE_VERSION_PROPERTY_NAME = "hardwareVersion"; + public static final String PANEL_APPLICATION_VERSION_PROPERTY_NAME = "applicationVersion"; + public static final String PANEL_BOOTLOADER_VERSION_PROPERTY_NAME = "bootloaderVersion"; + + public static final String PARTITION_LABEL_CHANNEL_UID = "partitionLabel"; + public static final String PARTITION_STATE_CHANNEL_UID = "state"; + @Deprecated // After implementation of channels for every possible state, the summarized additional states is no + // longer needed. We'll keep it for backward compatibility + public static final String PARTITION_ADDITIONAL_STATES_CHANNEL_UID = "additionalStates"; + public static final String PARTITION_READY_TO_ARM_CHANNEL_UID = "readyToArm"; + public static final String PARTITION_IN_EXIT_DELAY_CHANNEL_UID = "inExitDelay"; + public static final String PARTITION_IN_ENTRY_DELAY_CHANNEL_UID = "inEntryDelay"; + public static final String PARTITION_IN_TROUBLE_CHANNEL_UID = "inTrouble"; + public static final String PARTITION_ALARM_IN_MEMORY_CHANNEL_UID = "alarmInMemory"; + public static final String PARTITION_ZONE_BYPASS_CHANNEL_UID = "zoneBypass"; + public static final String PARTITION_ZONE_IN_TAMPER_CHANNEL_UID = "zoneInTamperTrouble"; + public static final String PARTITION_ZONE_IN_LOW_BATTERY_CHANNEL_UID = "zoneInLowBatteryTrouble"; + public static final String PARTITION_ZONE_IN_FIRE_LOOP_CHANNEL_UID = "zoneInFireLoopTrouble"; + public static final String PARTITION_ZONE_IN_SUPERVISION_TROUBLE_CHANNEL_UID = "zoneInSupervisionTrouble"; + public static final String PARTITION_STAY_INSTANT_READY_CHANNEL_UID = "stayInstantReady"; + public static final String PARTITION_FORCE_READY_CHANNEL_UID = "forceReady"; + public static final String PARTITION_BYPASS_READY_CHANNEL_UID = "bypassReady"; + public static final String PARTITION_INHIBIT_READY_CHANNEL_UID = "inhibitReady"; + public static final String PARTITION_ALL_ZONES_CLOSED_CHANNEL_UID = "allZonesClosed"; + + public static final String ZONE_LABEL_CHANNEL_UID = "zoneLabel"; + public static final String ZONE_OPENED_CHANNEL_UID = "opened"; + public static final String ZONE_TAMPERED_CHANNEL_UID = "tampered"; + public static final String ZONE_LOW_BATTERY_CHANNEL_UID = "lowBattery"; + + // Misc constants + public static final StringType STATE_OFFLINE = new StringType("Offline"); + public static final StringType STATE_ONLINE = new StringType("Online"); +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxAlarmHandlerFactory.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxAlarmHandlerFactory.java index bdb1082675d45..3122bef2410c3 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxAlarmHandlerFactory.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxAlarmHandlerFactory.java @@ -1,97 +1,97 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.handlers; - -import static org.openhab.binding.paradoxalarm.internal.handlers.ParadoxAlarmBindingConstants.*; - -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.config.discovery.DiscoveryService; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.ThingUID; -import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; -import org.openhab.binding.paradoxalarm.internal.discovery.ParadoxDiscoveryService; -import org.osgi.framework.ServiceRegistration; -import org.osgi.service.component.annotations.Component; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link ParadoxAlarmHandlerFactory} is responsible for creating things and thing - * handlers. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -@Component(configurationPid = "binding.paradoxalarm", service = ThingHandlerFactory.class) -public class ParadoxAlarmHandlerFactory extends BaseThingHandlerFactory { - - private final Logger logger = LoggerFactory.getLogger(ParadoxAlarmHandlerFactory.class); - - private final Map> discoveryServiceRegs = new HashMap<>(); - - @Override - public boolean supportsThingType(ThingTypeUID thingTypeUID) { - return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); - } - - @Override - protected @Nullable ThingHandler createHandler(Thing thing) { - ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - if (COMMUNICATOR_THING_TYPE_UID.equals(thingTypeUID)) { - logger.debug("createHandler(): ThingHandler created for {}", thingTypeUID); - - ParadoxIP150BridgeHandler paradoxIP150BridgeHandler = new ParadoxIP150BridgeHandler((Bridge) thing); - registerDiscoveryService(paradoxIP150BridgeHandler); - - return paradoxIP150BridgeHandler; - } else if (PANEL_THING_TYPE_UID.equals(thingTypeUID)) { - logger.debug("createHandler(): ThingHandler created for {}", thingTypeUID); - return new ParadoxPanelHandler(thing); - } else if (PARTITION_THING_TYPE_UID.equals(thingTypeUID)) { - logger.debug("createHandler(): ThingHandler created for {}", thingTypeUID); - return new ParadoxPartitionHandler(thing); - } else if (ZONE_THING_TYPE_UID.equals(thingTypeUID)) { - logger.debug("createHandler(): ThingHandler created for {}", thingTypeUID); - return new ParadoxZoneHandler(thing); - } else { - logger.warn("Handler implementation not found for Thing: {}", thing.getLabel()); - } - return null; - } - - private void registerDiscoveryService(ParadoxIP150BridgeHandler paradoxIP150BridgeHandler) { - ParadoxDiscoveryService discoveryService = new ParadoxDiscoveryService(paradoxIP150BridgeHandler); - ServiceRegistration serviceRegistration = bundleContext.registerService(DiscoveryService.class.getName(), - discoveryService, new Hashtable<>()); - this.discoveryServiceRegs.put(paradoxIP150BridgeHandler.getThing().getUID(), serviceRegistration); - } - - @Override - protected void removeHandler(ThingHandler thingHandler) { - if (thingHandler instanceof ParadoxIP150BridgeHandler) { - ServiceRegistration serviceReg = this.discoveryServiceRegs.remove(thingHandler.getThing().getUID()); - if (serviceReg != null) { - serviceReg.unregister(); - } - } - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.handlers; + +import static org.openhab.binding.paradoxalarm.internal.handlers.ParadoxAlarmBindingConstants.*; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.paradoxalarm.internal.discovery.ParadoxDiscoveryService; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ParadoxAlarmHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.paradoxalarm", service = ThingHandlerFactory.class) +public class ParadoxAlarmHandlerFactory extends BaseThingHandlerFactory { + + private final Logger logger = LoggerFactory.getLogger(ParadoxAlarmHandlerFactory.class); + + private final Map> discoveryServiceRegs = new HashMap<>(); + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + if (COMMUNICATOR_THING_TYPE_UID.equals(thingTypeUID)) { + logger.debug("createHandler(): ThingHandler created for {}", thingTypeUID); + + ParadoxIP150BridgeHandler paradoxIP150BridgeHandler = new ParadoxIP150BridgeHandler((Bridge) thing); + registerDiscoveryService(paradoxIP150BridgeHandler); + + return paradoxIP150BridgeHandler; + } else if (PANEL_THING_TYPE_UID.equals(thingTypeUID)) { + logger.debug("createHandler(): ThingHandler created for {}", thingTypeUID); + return new ParadoxPanelHandler(thing); + } else if (PARTITION_THING_TYPE_UID.equals(thingTypeUID)) { + logger.debug("createHandler(): ThingHandler created for {}", thingTypeUID); + return new ParadoxPartitionHandler(thing); + } else if (ZONE_THING_TYPE_UID.equals(thingTypeUID)) { + logger.debug("createHandler(): ThingHandler created for {}", thingTypeUID); + return new ParadoxZoneHandler(thing); + } else { + logger.warn("Handler implementation not found for Thing: {}", thing.getLabel()); + } + return null; + } + + private void registerDiscoveryService(ParadoxIP150BridgeHandler paradoxIP150BridgeHandler) { + ParadoxDiscoveryService discoveryService = new ParadoxDiscoveryService(paradoxIP150BridgeHandler); + ServiceRegistration serviceRegistration = bundleContext.registerService(DiscoveryService.class.getName(), + discoveryService, new Hashtable<>()); + this.discoveryServiceRegs.put(paradoxIP150BridgeHandler.getThing().getUID(), serviceRegistration); + } + + @Override + protected void removeHandler(ThingHandler thingHandler) { + if (thingHandler instanceof ParadoxIP150BridgeHandler) { + ServiceRegistration serviceReg = this.discoveryServiceRegs.remove(thingHandler.getThing().getUID()); + if (serviceReg != null) { + serviceReg.unregister(); + } + } + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxIP150BridgeConfiguration.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxIP150BridgeConfiguration.java index 58e5c4f6d95bd..8f890dbeac7fc 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxIP150BridgeConfiguration.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxIP150BridgeConfiguration.java @@ -1,104 +1,103 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.handlers; - -/** - * The {@link ParadoxIP150BridgeConfiguration} class contains fields mapping thing configuration parameters. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxIP150BridgeConfiguration { - - private int refresh; - private String ip150Password; - private String pcPassword; - private String ipAddress; - private int port; - private String panelType; - private int reconnectWaitTime; - private Integer maxZones; - private Integer maxPartitions; - - public int getRefresh() { - return refresh; - } - - public void setRefresh(int refresh) { - this.refresh = refresh; - } - - public String getIp150Password() { - return ip150Password; - } - - public void setIp150Password(String ip150Password) { - this.ip150Password = ip150Password; - } - - public String getPcPassword() { - return pcPassword; - } - - public void setPcPassword(String pcPassword) { - this.pcPassword = pcPassword; - } - - public String getIpAddress() { - return ipAddress; - } - - public void setIpAddress(String ipAddress) { - this.ipAddress = ipAddress; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public String getPanelType() { - return panelType; - } - - public void setPanelType(String panelType) { - this.panelType = panelType; - } - - public int getReconnectWaitTime() { - return reconnectWaitTime; - } - - public void setReconnectWaitTime(int reconnectWaitTime) { - this.reconnectWaitTime = reconnectWaitTime; - } - - public Integer getMaxZones() { - return maxZones; - } - - public void setMaxZones(Integer maxZones) { - this.maxZones = maxZones; - } - - public Integer getMaxPartitions() { - return maxPartitions; - } - - public void setMaxPartitions(Integer maxPartitions) { - this.maxPartitions = maxPartitions; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.handlers; + +/** + * The {@link ParadoxIP150BridgeConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxIP150BridgeConfiguration { + + private int refresh; + private String ip150Password; + private String pcPassword; + private String ipAddress; + private int port; + private String panelType; + private int reconnectWaitTime; + private Integer maxZones; + private Integer maxPartitions; + + public int getRefresh() { + return refresh; + } + + public void setRefresh(int refresh) { + this.refresh = refresh; + } + + public String getIp150Password() { + return ip150Password; + } + + public void setIp150Password(String ip150Password) { + this.ip150Password = ip150Password; + } + + public String getPcPassword() { + return pcPassword; + } + + public void setPcPassword(String pcPassword) { + this.pcPassword = pcPassword; + } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getPanelType() { + return panelType; + } + + public void setPanelType(String panelType) { + this.panelType = panelType; + } + + public int getReconnectWaitTime() { + return reconnectWaitTime; + } + + public void setReconnectWaitTime(int reconnectWaitTime) { + this.reconnectWaitTime = reconnectWaitTime; + } + + public Integer getMaxZones() { + return maxZones; + } + + public void setMaxZones(Integer maxZones) { + this.maxZones = maxZones; + } + + public Integer getMaxPartitions() { + return maxPartitions; + } + + public void setMaxPartitions(Integer maxPartitions) { + this.maxPartitions = maxPartitions; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxIP150BridgeHandler.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxIP150BridgeHandler.java index 31dfe266ed03d..4ca4658173230 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxIP150BridgeHandler.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxIP150BridgeHandler.java @@ -298,5 +298,4 @@ public void onSocketTimeOutOccurred(IOException exception) { TimeUnit.SECONDS); } } - } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxPanelHandler.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxPanelHandler.java index 84d37ce273d4e..ca2be18c938f1 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxPanelHandler.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxPanelHandler.java @@ -1,56 +1,55 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.handlers; - -import static org.openhab.binding.paradoxalarm.internal.handlers.ParadoxAlarmBindingConstants.*; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.Thing; -import org.openhab.binding.paradoxalarm.internal.model.ParadoxInformation; -import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link ParadoxPanelHandler} This is the handler that takes care of the panel related stuff. - * - * @author Konstantin Polihronov - Initial contribution - */ -@NonNullByDefault -public class ParadoxPanelHandler extends EntityBaseHandler { - - private final Logger logger = LoggerFactory.getLogger(ParadoxPanelHandler.class); - - public ParadoxPanelHandler(Thing thing) { - super(thing); - } - - @Override - protected void updateEntity() { - ParadoxPanel panel = ParadoxPanel.getInstance(); - StringType panelState = panel.isOnline() ? STATE_ONLINE : STATE_OFFLINE; - updateState(PANEL_STATE_CHANNEL_UID, panelState); - - ParadoxInformation panelInformation = panel.getPanelInformation(); - if (panelInformation != null) { - updateProperty(PANEL_SERIAL_NUMBER_PROPERTY_NAME, panelInformation.getSerialNumber()); - updateProperty(PANEL_TYPE_PROPERTY_NAME, panelInformation.getPanelType().name()); - updateProperty(PANEL_HARDWARE_VERSION_PROPERTY_NAME, panelInformation.getHardwareVersion().toString()); - updateProperty(PANEL_APPLICATION_VERSION_PROPERTY_NAME, - panelInformation.getApplicationVersion().toString()); - updateProperty(PANEL_BOOTLOADER_VERSION_PROPERTY_NAME, - panelInformation.getBootLoaderVersion().toString()); - } - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.handlers; + +import static org.openhab.binding.paradoxalarm.internal.handlers.ParadoxAlarmBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Thing; +import org.openhab.binding.paradoxalarm.internal.model.ParadoxInformation; +import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ParadoxPanelHandler} This is the handler that takes care of the panel related stuff. + * + * @author Konstantin Polihronov - Initial contribution + */ +@NonNullByDefault +public class ParadoxPanelHandler extends EntityBaseHandler { + + private final Logger logger = LoggerFactory.getLogger(ParadoxPanelHandler.class); + + public ParadoxPanelHandler(Thing thing) { + super(thing); + } + + @Override + protected void updateEntity() { + ParadoxPanel panel = ParadoxPanel.getInstance(); + StringType panelState = panel.isOnline() ? STATE_ONLINE : STATE_OFFLINE; + updateState(PANEL_STATE_CHANNEL_UID, panelState); + + ParadoxInformation panelInformation = panel.getPanelInformation(); + if (panelInformation != null) { + updateProperty(PANEL_SERIAL_NUMBER_PROPERTY_NAME, panelInformation.getSerialNumber()); + updateProperty(PANEL_TYPE_PROPERTY_NAME, panelInformation.getPanelType().name()); + updateProperty(PANEL_HARDWARE_VERSION_PROPERTY_NAME, panelInformation.getHardwareVersion().toString()); + updateProperty(PANEL_APPLICATION_VERSION_PROPERTY_NAME, + panelInformation.getApplicationVersion().toString()); + updateProperty(PANEL_BOOTLOADER_VERSION_PROPERTY_NAME, panelInformation.getBootLoaderVersion().toString()); + } + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxPartitionHandler.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxPartitionHandler.java index 27e24daea6d42..4c7e8b99ce0e2 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxPartitionHandler.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxPartitionHandler.java @@ -1,87 +1,87 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.handlers; - -import static org.openhab.binding.paradoxalarm.internal.handlers.ParadoxAlarmBindingConstants.*; - -import java.util.List; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.OpenClosedType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.Thing; -import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; -import org.openhab.binding.paradoxalarm.internal.model.Partition; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link ParadoxPartitionHandler} Handler that updates states of paradox partitions from the cache. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxPartitionHandler extends EntityBaseHandler { - - private final Logger logger = LoggerFactory.getLogger(ParadoxPartitionHandler.class); - - public ParadoxPartitionHandler(@NonNull Thing thing) { - super(thing); - } - - @Override - protected void updateEntity() { - int index = calculateEntityIndex(); - List partitions = ParadoxPanel.getInstance().getPartitions(); - Partition partition = partitions.get(index); - if (partition != null) { - updateState(PARTITION_LABEL_CHANNEL_UID, new StringType(partition.getLabel())); - updateState(PARTITION_STATE_CHANNEL_UID, new StringType(partition.getState().getMainState())); - updateState(PARTITION_ADDITIONAL_STATES_CHANNEL_UID, - new StringType("Deprecated field. Use direct channels instead")); - updateState(PARTITION_READY_TO_ARM_CHANNEL_UID, booleanToSwitchState(partition.getState().isReadyToArm())); - updateState(PARTITION_IN_EXIT_DELAY_CHANNEL_UID, - booleanToSwitchState(partition.getState().isInExitDelay())); - updateState(PARTITION_IN_ENTRY_DELAY_CHANNEL_UID, - booleanToSwitchState(partition.getState().isInEntryDelay())); - updateState(PARTITION_IN_TROUBLE_CHANNEL_UID, booleanToSwitchState(partition.getState().isInTrouble())); - updateState(PARTITION_ALARM_IN_MEMORY_CHANNEL_UID, - booleanToSwitchState(partition.getState().isHasAlarmInMemory())); - updateState(PARTITION_ZONE_BYPASS_CHANNEL_UID, booleanToSwitchState(partition.getState().isInZoneBypass())); - updateState(PARTITION_ZONE_IN_TAMPER_CHANNEL_UID, - booleanToSwitchState(partition.getState().isHasZoneInTamperTrouble())); - updateState(PARTITION_ZONE_IN_LOW_BATTERY_CHANNEL_UID, - booleanToSwitchState(partition.getState().isHasZoneInLowBatteryTrouble())); - updateState(PARTITION_ZONE_IN_FIRE_LOOP_CHANNEL_UID, - booleanToSwitchState(partition.getState().isHasZoneInFireLoopTrouble())); - updateState(PARTITION_ZONE_IN_SUPERVISION_TROUBLE_CHANNEL_UID, - booleanToSwitchState(partition.getState().isHasZoneInSupervisionTrouble())); - updateState(PARTITION_STAY_INSTANT_READY_CHANNEL_UID, - booleanToSwitchState(partition.getState().isStayInstantReady())); - updateState(PARTITION_FORCE_READY_CHANNEL_UID, booleanToSwitchState(partition.getState().isForceReady())); - updateState(PARTITION_BYPASS_READY_CHANNEL_UID, booleanToSwitchState(partition.getState().isBypassReady())); - updateState(PARTITION_INHIBIT_READY_CHANNEL_UID, - booleanToSwitchState(partition.getState().isInhibitReady())); - updateState(PARTITION_ALL_ZONES_CLOSED_CHANNEL_UID, - booleanToContactState(partition.getState().isAreAllZoneclosed())); - } - } - - private OpenClosedType booleanToContactState(boolean value) { - return value ? OpenClosedType.OPEN : OpenClosedType.CLOSED; - } - - private OnOffType booleanToSwitchState(boolean value) { - return value ? OnOffType.ON : OnOffType.OFF; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.handlers; + +import static org.openhab.binding.paradoxalarm.internal.handlers.ParadoxAlarmBindingConstants.*; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Thing; +import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; +import org.openhab.binding.paradoxalarm.internal.model.Partition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ParadoxPartitionHandler} Handler that updates states of paradox partitions from the cache. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxPartitionHandler extends EntityBaseHandler { + + private final Logger logger = LoggerFactory.getLogger(ParadoxPartitionHandler.class); + + public ParadoxPartitionHandler(@NonNull Thing thing) { + super(thing); + } + + @Override + protected void updateEntity() { + int index = calculateEntityIndex(); + List partitions = ParadoxPanel.getInstance().getPartitions(); + Partition partition = partitions.get(index); + if (partition != null) { + updateState(PARTITION_LABEL_CHANNEL_UID, new StringType(partition.getLabel())); + updateState(PARTITION_STATE_CHANNEL_UID, new StringType(partition.getState().getMainState())); + updateState(PARTITION_ADDITIONAL_STATES_CHANNEL_UID, + new StringType("Deprecated field. Use direct channels instead")); + updateState(PARTITION_READY_TO_ARM_CHANNEL_UID, booleanToSwitchState(partition.getState().isReadyToArm())); + updateState(PARTITION_IN_EXIT_DELAY_CHANNEL_UID, + booleanToSwitchState(partition.getState().isInExitDelay())); + updateState(PARTITION_IN_ENTRY_DELAY_CHANNEL_UID, + booleanToSwitchState(partition.getState().isInEntryDelay())); + updateState(PARTITION_IN_TROUBLE_CHANNEL_UID, booleanToSwitchState(partition.getState().isInTrouble())); + updateState(PARTITION_ALARM_IN_MEMORY_CHANNEL_UID, + booleanToSwitchState(partition.getState().isHasAlarmInMemory())); + updateState(PARTITION_ZONE_BYPASS_CHANNEL_UID, booleanToSwitchState(partition.getState().isInZoneBypass())); + updateState(PARTITION_ZONE_IN_TAMPER_CHANNEL_UID, + booleanToSwitchState(partition.getState().isHasZoneInTamperTrouble())); + updateState(PARTITION_ZONE_IN_LOW_BATTERY_CHANNEL_UID, + booleanToSwitchState(partition.getState().isHasZoneInLowBatteryTrouble())); + updateState(PARTITION_ZONE_IN_FIRE_LOOP_CHANNEL_UID, + booleanToSwitchState(partition.getState().isHasZoneInFireLoopTrouble())); + updateState(PARTITION_ZONE_IN_SUPERVISION_TROUBLE_CHANNEL_UID, + booleanToSwitchState(partition.getState().isHasZoneInSupervisionTrouble())); + updateState(PARTITION_STAY_INSTANT_READY_CHANNEL_UID, + booleanToSwitchState(partition.getState().isStayInstantReady())); + updateState(PARTITION_FORCE_READY_CHANNEL_UID, booleanToSwitchState(partition.getState().isForceReady())); + updateState(PARTITION_BYPASS_READY_CHANNEL_UID, booleanToSwitchState(partition.getState().isBypassReady())); + updateState(PARTITION_INHIBIT_READY_CHANNEL_UID, + booleanToSwitchState(partition.getState().isInhibitReady())); + updateState(PARTITION_ALL_ZONES_CLOSED_CHANNEL_UID, + booleanToContactState(partition.getState().isAreAllZoneclosed())); + } + } + + private OpenClosedType booleanToContactState(boolean value) { + return value ? OpenClosedType.OPEN : OpenClosedType.CLOSED; + } + + private OnOffType booleanToSwitchState(boolean value) { + return value ? OnOffType.ON : OnOffType.OFF; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxZoneHandler.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxZoneHandler.java index 4bb17092b70ca..32b35a2e04832 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxZoneHandler.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/handlers/ParadoxZoneHandler.java @@ -1,68 +1,67 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.handlers; - -import static org.openhab.binding.paradoxalarm.internal.handlers.ParadoxAlarmBindingConstants.*; - -import java.util.List; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.library.types.OpenClosedType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.Thing; -import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; -import org.openhab.binding.paradoxalarm.internal.model.Zone; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link ParadoxZoneHandler} Handler that updates states of paradox zones from the cache. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxZoneHandler extends EntityBaseHandler { - - private final Logger logger = LoggerFactory.getLogger(ParadoxZoneHandler.class); - - public ParadoxZoneHandler(@NonNull Thing thing) { - super(thing); - } - - @Override - protected void updateEntity() { - int index = calculateEntityIndex(); - List zones = ParadoxPanel.getInstance().getZones(); - if (zones != null && zones.size() > index) { - Zone zone = zones.get(index); - if (zone != null) { - updateState(ZONE_LABEL_CHANNEL_UID, new StringType(zone.getLabel())); - updateState(ZONE_OPENED_CHANNEL_UID, booleanToContactState(zone.getZoneState().isOpened())); - updateState(ZONE_TAMPERED_CHANNEL_UID, booleanToSwitchState(zone.getZoneState().isTampered())); - updateState(ZONE_LOW_BATTERY_CHANNEL_UID, booleanToSwitchState(zone.getZoneState().hasLowBattery())); - } - } else { - logger.warn("Attempted to access zone out of bounds of current zone list. Index: {}, List: {}", index, - zones); - } - } - - private OpenClosedType booleanToContactState(boolean value) { - return value ? OpenClosedType.OPEN : OpenClosedType.CLOSED; - } - - private OnOffType booleanToSwitchState(boolean value) { - return value ? OnOffType.ON : OnOffType.OFF; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.handlers; + +import static org.openhab.binding.paradoxalarm.internal.handlers.ParadoxAlarmBindingConstants.*; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Thing; +import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; +import org.openhab.binding.paradoxalarm.internal.model.Zone; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ParadoxZoneHandler} Handler that updates states of paradox zones from the cache. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxZoneHandler extends EntityBaseHandler { + + private final Logger logger = LoggerFactory.getLogger(ParadoxZoneHandler.class); + + public ParadoxZoneHandler(@NonNull Thing thing) { + super(thing); + } + + @Override + protected void updateEntity() { + int index = calculateEntityIndex(); + List zones = ParadoxPanel.getInstance().getZones(); + if (zones != null && zones.size() > index) { + Zone zone = zones.get(index); + if (zone != null) { + updateState(ZONE_LABEL_CHANNEL_UID, new StringType(zone.getLabel())); + updateState(ZONE_OPENED_CHANNEL_UID, booleanToContactState(zone.getZoneState().isOpened())); + updateState(ZONE_TAMPERED_CHANNEL_UID, booleanToSwitchState(zone.getZoneState().isTampered())); + updateState(ZONE_LOW_BATTERY_CHANNEL_UID, booleanToSwitchState(zone.getZoneState().hasLowBattery())); + } + } else { + logger.warn("Attempted to access zone out of bounds of current zone list. Index: {}, List: {}", index, + zones); + } + } + + private OpenClosedType booleanToContactState(boolean value) { + return value ? OpenClosedType.OPEN : OpenClosedType.CLOSED; + } + + private OnOffType booleanToSwitchState(boolean value) { + return value ? OnOffType.ON : OnOffType.OFF; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Entity.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Entity.java index 9768810a67785..27a1f7dbb4ecf 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Entity.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Entity.java @@ -1,57 +1,56 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link Entity} Entity - base abstract class for Paradox entities (Partitions, zones, etc). - * Extend this class and add entity specific data (states, troubles, etc). - * - * @author Konstantin Polihronov - Initial contribution - */ -public abstract class Entity { - private final Logger logger = LoggerFactory.getLogger(Entity.class); - - private int id; - private String label; - - public Entity(int id, String label) { - this.id = id; - this.label = label.trim(); - logger.debug("Creating entity with label: {} and ID: {}", label, id); - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } - - @Override - public String toString() { - return "Entity [id=" + id + ", label=" + label + "]"; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link Entity} Entity - base abstract class for Paradox entities (Partitions, zones, etc). + * Extend this class and add entity specific data (states, troubles, etc). + * + * @author Konstantin Polihronov - Initial contribution + */ +public abstract class Entity { + private final Logger logger = LoggerFactory.getLogger(Entity.class); + + private int id; + private String label; + + public Entity(int id, String label) { + this.id = id; + this.label = label.trim(); + logger.debug("Creating entity with label: {} and ID: {}", label, id); + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + @Override + public String toString() { + return "Entity [id=" + id + ", label=" + label + "]"; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/PanelType.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/PanelType.java index 3aca55fc42d5b..5611914964676 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/PanelType.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/PanelType.java @@ -1,83 +1,82 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -/** - * The {@link PanelType} Enum of all panel types - * - * @author Konstantin Polihronov - Initial contribution - */ -public enum PanelType { - EVO48(4, 48, 2, 16), - EVO96(4, 96, 3, 16), - EVO192(8, 192, 5, 16), - EVOHD(8, 192, 5, 16), - SP5500, - SP6000, - SP7000, - MG5000, - MG5050, - SP4000, - SP65, - UNKNOWN; - - private int partitions; - private int zones; - private int pgms; // Programmable outputs - private int ramPagesNumber; // Ram pages 64 bytes each - - private PanelType() { - this(0, 0, 0, 0); - } - - private PanelType(int numberPartitions, int numberZones, int pgms, int ramPages) { - this.partitions = numberPartitions; - this.zones = numberZones; - this.pgms = pgms; - this.ramPagesNumber = ramPages; - } - - public static PanelType from(String panelTypeStr) { - if (panelTypeStr == null) { - return PanelType.UNKNOWN; - } - - try { - return PanelType.valueOf(panelTypeStr); - } catch (IllegalArgumentException e) { - return PanelType.UNKNOWN; - } - } - - public int getPartitions() { - return partitions; - } - - public int getZones() { - return zones; - } - - @Override - public String toString() { - return this.name(); - } - - public int getPgms() { - return pgms; - } - - public int getRamPagesNumber() { - return ramPagesNumber; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +/** + * The {@link PanelType} Enum of all panel types + * + * @author Konstantin Polihronov - Initial contribution + */ +public enum PanelType { + EVO48(4, 48, 2, 16), + EVO96(4, 96, 3, 16), + EVO192(8, 192, 5, 16), + EVOHD(8, 192, 5, 16), + SP5500, + SP6000, + SP7000, + MG5000, + MG5050, + SP4000, + SP65, + UNKNOWN; + + private int partitions; + private int zones; + private int pgms; // Programmable outputs + private int ramPagesNumber; // Ram pages 64 bytes each + + private PanelType() { + this(0, 0, 0, 0); + } + + private PanelType(int numberPartitions, int numberZones, int pgms, int ramPages) { + this.partitions = numberPartitions; + this.zones = numberZones; + this.pgms = pgms; + this.ramPagesNumber = ramPages; + } + + public static PanelType from(String panelTypeStr) { + if (panelTypeStr == null) { + return PanelType.UNKNOWN; + } + + try { + return PanelType.valueOf(panelTypeStr); + } catch (IllegalArgumentException e) { + return PanelType.UNKNOWN; + } + } + + public int getPartitions() { + return partitions; + } + + public int getZones() { + return zones; + } + + @Override + public String toString() { + return this.name(); + } + + public int getPgms() { + return pgms; + } + + public int getRamPagesNumber() { + return ramPagesNumber; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxInformation.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxInformation.java index f1c3c353466c3..782feaead6189 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxInformation.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxInformation.java @@ -1,73 +1,72 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -import java.util.Arrays; - -import org.eclipse.smarthome.core.util.HexUtils; -import org.openhab.binding.paradoxalarm.internal.parsers.IParadoxParser; - -/** - * The {@link ParadoxInformation} Class that provides the basic panel - * information (serial number, panel type, application, hardware and bootloader - * versions. It's the object representation of 37 bytes 0x72 serial response. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxInformation { - - private PanelType panelType; - private String serialNumber; - private Version applicationVersion; - private Version hardwareVersion; - private Version bootloaderVersion; - - public ParadoxInformation(byte[] panelInfoBytes, IParadoxParser parser) { - panelType = ParadoxInformationConstants.parsePanelType(panelInfoBytes); - - applicationVersion = parser.parseApplicationVersion(panelInfoBytes); - hardwareVersion = parser.parseHardwareVersion(panelInfoBytes); - bootloaderVersion = parser.parseBootloaderVersion(panelInfoBytes); - - byte[] serialNumberBytes = Arrays.copyOfRange(panelInfoBytes, 12, 16); - serialNumber = HexUtils.bytesToHex(serialNumberBytes); - } - - public PanelType getPanelType() { - return panelType; - } - - public Version getApplicationVersion() { - return applicationVersion; - } - - public Version getHardwareVersion() { - return hardwareVersion; - } - - public Version getBootLoaderVersion() { - return bootloaderVersion; - } - - public String getSerialNumber() { - return serialNumber; - } - - @Override - public String toString() { - return "ParadoxInformation [panelType=" + panelType + ", serialNumber=" + serialNumber + ", applicationVersion=" - + applicationVersion + ", hardwareVersion=" + hardwareVersion + ", bootloaderVersion=" - + bootloaderVersion + "]"; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +import java.util.Arrays; + +import org.eclipse.smarthome.core.util.HexUtils; +import org.openhab.binding.paradoxalarm.internal.parsers.IParadoxParser; + +/** + * The {@link ParadoxInformation} Class that provides the basic panel + * information (serial number, panel type, application, hardware and bootloader + * versions. It's the object representation of 37 bytes 0x72 serial response. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxInformation { + + private PanelType panelType; + private String serialNumber; + private Version applicationVersion; + private Version hardwareVersion; + private Version bootloaderVersion; + + public ParadoxInformation(byte[] panelInfoBytes, IParadoxParser parser) { + panelType = ParadoxInformationConstants.parsePanelType(panelInfoBytes); + + applicationVersion = parser.parseApplicationVersion(panelInfoBytes); + hardwareVersion = parser.parseHardwareVersion(panelInfoBytes); + bootloaderVersion = parser.parseBootloaderVersion(panelInfoBytes); + + byte[] serialNumberBytes = Arrays.copyOfRange(panelInfoBytes, 12, 16); + serialNumber = HexUtils.bytesToHex(serialNumberBytes); + } + + public PanelType getPanelType() { + return panelType; + } + + public Version getApplicationVersion() { + return applicationVersion; + } + + public Version getHardwareVersion() { + return hardwareVersion; + } + + public Version getBootLoaderVersion() { + return bootloaderVersion; + } + + public String getSerialNumber() { + return serialNumber; + } + + @Override + public String toString() { + return "ParadoxInformation [panelType=" + panelType + ", serialNumber=" + serialNumber + ", applicationVersion=" + + applicationVersion + ", hardwareVersion=" + hardwareVersion + ", bootloaderVersion=" + + bootloaderVersion + "]"; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxInformationConstants.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxInformationConstants.java index 9965c734d7626..435f06b625d30 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxInformationConstants.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxInformationConstants.java @@ -55,5 +55,4 @@ public static PanelType parsePanelType(byte[] infoPacket) { return ParadoxInformationConstants.panelTypes.getOrDefault(key, PanelType.UNKNOWN); } - } diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxPanel.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxPanel.java index 32db382dc4edc..0da84fd4db207 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxPanel.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ParadoxPanel.java @@ -1,149 +1,148 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.openhab.binding.paradoxalarm.internal.communication.IDataUpdateListener; -import org.openhab.binding.paradoxalarm.internal.communication.IParadoxCommunicator; -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; -import org.openhab.binding.paradoxalarm.internal.parsers.EvoParser; -import org.openhab.binding.paradoxalarm.internal.parsers.IParadoxParser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link ParadoxPanel} Composition class which contains all Paradox entities. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxPanel implements IDataUpdateListener { - - private final Logger logger = LoggerFactory.getLogger(ParadoxPanel.class); - - private static ParadoxPanel paradoxPanel = new ParadoxPanel(); - - private ParadoxInformation panelInformation; - private List partitions; - private List zones; - private IParadoxParser parser; - private IParadoxCommunicator communicator; - - private ParadoxPanel() { - this.parser = new EvoParser(); - } - - public void createModelEntities() { - byte[] panelInfoBytes = communicator.getPanelInfoBytes(); - panelInformation = new ParadoxInformation(panelInfoBytes, parser); - - if (isPanelSupported()) { - logger.info("Paradox system is supported. Panel data retrieved={} ", panelInformation); - createPartitions(); - createZones(); - updateEntitiesStates(); - } else { - throw new ParadoxRuntimeException( - "Unsupported panel type. Type: " + panelInformation.getPanelType().name()); - } - } - - public static ParadoxPanel getInstance() { - return paradoxPanel; - } - - public boolean isPanelSupported() { - PanelType panelType = panelInformation.getPanelType(); - return panelType == PanelType.EVO48 || panelType == PanelType.EVO192 || panelType == PanelType.EVOHD; - } - - public void updateEntitiesStates() { - if (!isOnline()) { - logger.debug("Not online. Unable to update entities states. "); - return; - } - - List currentPartitionFlags = communicator.getPartitionFlags(); - for (int i = 0; i < partitions.size(); i++) { - Partition partition = partitions.get(i); - partition.setState(parser.calculatePartitionState(currentPartitionFlags.get(i))); - } - - ZoneStateFlags zoneStateFlags = communicator.getZoneStateFlags(); - for (int i = 0; i < zones.size(); i++) { - Zone zone = zones.get(i); - zone.setZoneState(parser.calculateZoneState(zone.getId(), zoneStateFlags)); - } - } - - private List createZones() { - zones = new ArrayList<>(); - Map zoneLabels = communicator.getZoneLabels(); - for (int i = 0; i < zoneLabels.size(); i++) { - Zone zone = new Zone(i + 1, zoneLabels.get(i)); - zones.add(zone); - } - return zones; - } - - private List createPartitions() { - partitions = new ArrayList<>(); - Map partitionLabels = communicator.getPartitionLabels(); - for (int i = 0; i < partitionLabels.size(); i++) { - Partition partition = new Partition(i + 1, partitionLabels.get(i)); - partitions.add(partition); - logger.debug("Partition {}:\t{}", i + 1, partition.getState().getMainState()); - } - return partitions; - } - - public ParadoxInformation getPanelInformation() { - return panelInformation; - } - - public List getPartitions() { - return partitions; - } - - public void setPartitions(List partitions) { - this.partitions = partitions; - } - - public List getZones() { - return zones; - } - - public void setZones(List zones) { - this.zones = zones; - } - - public boolean isOnline() { - return communicator.isOnline(); - } - - @Override - public void update() { - if (panelInformation == null || partitions == null || zones == null) { - createModelEntities(); - } else { - updateEntitiesStates(); - } - } - - public void setCommunicator(IParadoxCommunicator communicator) { - this.communicator = communicator; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.openhab.binding.paradoxalarm.internal.communication.IDataUpdateListener; +import org.openhab.binding.paradoxalarm.internal.communication.IParadoxCommunicator; +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxRuntimeException; +import org.openhab.binding.paradoxalarm.internal.parsers.EvoParser; +import org.openhab.binding.paradoxalarm.internal.parsers.IParadoxParser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ParadoxPanel} Composition class which contains all Paradox entities. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxPanel implements IDataUpdateListener { + + private final Logger logger = LoggerFactory.getLogger(ParadoxPanel.class); + + private static ParadoxPanel paradoxPanel = new ParadoxPanel(); + + private ParadoxInformation panelInformation; + private List partitions; + private List zones; + private IParadoxParser parser; + private IParadoxCommunicator communicator; + + private ParadoxPanel() { + this.parser = new EvoParser(); + } + + public void createModelEntities() { + byte[] panelInfoBytes = communicator.getPanelInfoBytes(); + panelInformation = new ParadoxInformation(panelInfoBytes, parser); + + if (isPanelSupported()) { + logger.info("Paradox system is supported. Panel data retrieved={} ", panelInformation); + createPartitions(); + createZones(); + updateEntitiesStates(); + } else { + throw new ParadoxRuntimeException( + "Unsupported panel type. Type: " + panelInformation.getPanelType().name()); + } + } + + public static ParadoxPanel getInstance() { + return paradoxPanel; + } + + public boolean isPanelSupported() { + PanelType panelType = panelInformation.getPanelType(); + return panelType == PanelType.EVO48 || panelType == PanelType.EVO192 || panelType == PanelType.EVOHD; + } + + public void updateEntitiesStates() { + if (!isOnline()) { + logger.debug("Not online. Unable to update entities states. "); + return; + } + + List currentPartitionFlags = communicator.getPartitionFlags(); + for (int i = 0; i < partitions.size(); i++) { + Partition partition = partitions.get(i); + partition.setState(parser.calculatePartitionState(currentPartitionFlags.get(i))); + } + + ZoneStateFlags zoneStateFlags = communicator.getZoneStateFlags(); + for (int i = 0; i < zones.size(); i++) { + Zone zone = zones.get(i); + zone.setZoneState(parser.calculateZoneState(zone.getId(), zoneStateFlags)); + } + } + + private List createZones() { + zones = new ArrayList<>(); + Map zoneLabels = communicator.getZoneLabels(); + for (int i = 0; i < zoneLabels.size(); i++) { + Zone zone = new Zone(i + 1, zoneLabels.get(i)); + zones.add(zone); + } + return zones; + } + + private List createPartitions() { + partitions = new ArrayList<>(); + Map partitionLabels = communicator.getPartitionLabels(); + for (int i = 0; i < partitionLabels.size(); i++) { + Partition partition = new Partition(i + 1, partitionLabels.get(i)); + partitions.add(partition); + logger.debug("Partition {}:\t{}", i + 1, partition.getState().getMainState()); + } + return partitions; + } + + public ParadoxInformation getPanelInformation() { + return panelInformation; + } + + public List getPartitions() { + return partitions; + } + + public void setPartitions(List partitions) { + this.partitions = partitions; + } + + public List getZones() { + return zones; + } + + public void setZones(List zones) { + this.zones = zones; + } + + public boolean isOnline() { + return communicator.isOnline(); + } + + @Override + public void update() { + if (panelInformation == null || partitions == null || zones == null) { + createModelEntities(); + } else { + updateEntitiesStates(); + } + } + + public void setCommunicator(IParadoxCommunicator communicator) { + this.communicator = communicator; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Partition.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Partition.java index 6147c8b6bc9cf..de68fb4fbfbde 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Partition.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Partition.java @@ -1,43 +1,43 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link Partition} Paradox partition. - * ID is always numeric (1-8 for Evo192) - * - * @author Konstantin Polihronov - Initial contribution - */ -public class Partition extends Entity { - - private final Logger logger = LoggerFactory.getLogger(Partition.class); - - private PartitionState state = new PartitionState(); - - public Partition(int id, String label) { - super(id, label); - } - - public PartitionState getState() { - return state; - } - - public Partition setState(PartitionState state) { - this.state = state; - logger.debug("Partition {}:\t{}", getLabel(), getState().getMainState()); - return this; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link Partition} Paradox partition. + * ID is always numeric (1-8 for Evo192) + * + * @author Konstantin Polihronov - Initial contribution + */ +public class Partition extends Entity { + + private final Logger logger = LoggerFactory.getLogger(Partition.class); + + private PartitionState state = new PartitionState(); + + public Partition(int id, String label) { + super(id, label); + } + + public PartitionState getState() { + return state; + } + + public Partition setState(PartitionState state) { + this.state = state; + logger.debug("Partition {}:\t{}", getLabel(), getState().getMainState()); + return this; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/PartitionState.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/PartitionState.java index d10292ac718e8..a1eb488034721 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/PartitionState.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/PartitionState.java @@ -1,263 +1,263 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -/** - * The {@link Partition} Paradox partition states. Retrieved and parsed from RAM memory responses. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class PartitionState { - - private boolean isArmed; - private boolean isArmedInAway; - private boolean isArmedInStay; - private boolean isArmedInNoEntry; - private boolean isInAlarm; - private boolean isInSilentAlarm; - private boolean isInAudibleAlarm; - private boolean isInFireAlarm; - - private boolean isReadyToArm; - private boolean isInExitDelay; - private boolean isInEntryDelay; - private boolean isInTrouble; - private boolean hasAlarmInMemory; - private boolean isInZoneBypass; - - private boolean hasZoneInTamperTrouble; - private boolean hasZoneInLowBatteryTrouble; - private boolean hasZoneInFireLoopTrouble; - private boolean hasZoneInSupervisionTrouble; - - private boolean isStayInstantReady; - private boolean isForceReady; - private boolean isBypassReady; - private boolean isInhibitReady; - private boolean areAllZoneclosed; - - public String getMainState() { - if (isInAlarm) { - return "InAlarm"; - } else { - return isArmed || isArmedInAway || isArmedInStay || isArmedInNoEntry ? "Armed" : "Disarmed"; - } - } - - @Override - public String toString() { - return "PartitionState [isArmed=" + isArmed + ", isArmedInAway=" + isArmedInAway + ", isArmedInStay=" - + isArmedInStay + ", isArmedInNoEntry=" + isArmedInNoEntry + ", isInAlarm=" + isInAlarm - + ", isInSilentAlarm=" + isInSilentAlarm + ", isInAudibleAlarm=" + isInAudibleAlarm + ", isInFireAlarm=" - + isInFireAlarm + ", isReadyToArm=" + isReadyToArm + ", isInExitDelay=" + isInExitDelay - + ", isInEntryDelay=" + isInEntryDelay + ", isInTrouble=" + isInTrouble + ", hasAlarmInMemory=" - + hasAlarmInMemory + ", isInZoneBypass=" + isInZoneBypass + ", hasZoneInTamperTrouble=" - + hasZoneInTamperTrouble + ", hasZoneInLowBatteryTrouble=" + hasZoneInLowBatteryTrouble - + ", hasZoneInFireLoopTrouble=" + hasZoneInFireLoopTrouble + ", hasZoneInSupervisionTrouble=" - + hasZoneInSupervisionTrouble + ", isStayInstantReady=" + isStayInstantReady + ", isForceReady=" - + isForceReady + ", isBypassReady=" + isBypassReady + ", isInhibitReady=" + isInhibitReady - + ", areAllZoneclosed=" + areAllZoneclosed + "]"; - } - - public boolean isArmed() { - return isArmed; - } - - public void setArmed(boolean isArmed) { - this.isArmed = isArmed; - } - - public boolean isArmedInAway() { - return isArmedInAway; - } - - public void setArmedInAway(boolean isArmedInAway) { - this.isArmedInAway = isArmedInAway; - } - - public boolean isArmedInStay() { - return isArmedInStay; - } - - public void setArmedInStay(boolean isArmedInStay) { - this.isArmedInStay = isArmedInStay; - } - - public boolean isArmedInNoEntry() { - return isArmedInNoEntry; - } - - public void setArmedInNoEntry(boolean isArmedInNoEntry) { - this.isArmedInNoEntry = isArmedInNoEntry; - } - - public boolean isInAlarm() { - return isInAlarm; - } - - public void setInAlarm(boolean isInAlarm) { - this.isInAlarm = isInAlarm; - } - - public boolean isInSilentAlarm() { - return isInSilentAlarm; - } - - public void setInSilentAlarm(boolean isInSilentAlarm) { - this.isInSilentAlarm = isInSilentAlarm; - } - - public boolean isInAudibleAlarm() { - return isInAudibleAlarm; - } - - public void setInAudibleAlarm(boolean isInAudibleAlarm) { - this.isInAudibleAlarm = isInAudibleAlarm; - } - - public boolean isInFireAlarm() { - return isInFireAlarm; - } - - public void setInFireAlarm(boolean isInFireAlarm) { - this.isInFireAlarm = isInFireAlarm; - } - - public boolean isReadyToArm() { - return isReadyToArm; - } - - public void setReadyToArm(boolean isReadyToArm) { - this.isReadyToArm = isReadyToArm; - } - - public boolean isInExitDelay() { - return isInExitDelay; - } - - public void setInExitDelay(boolean isInExitDelay) { - this.isInExitDelay = isInExitDelay; - } - - public boolean isInEntryDelay() { - return isInEntryDelay; - } - - public void setInEntryDelay(boolean isInEntryDelay) { - this.isInEntryDelay = isInEntryDelay; - } - - public boolean isInTrouble() { - return isInTrouble; - } - - public void setInTrouble(boolean isInTrouble) { - this.isInTrouble = isInTrouble; - } - - public boolean isHasAarmInMemory() { - return hasAlarmInMemory; - } - - public void setHasAarmInMemory(boolean hasAarmInMemory) { - this.hasAlarmInMemory = hasAarmInMemory; - } - - public boolean isInZoneBypass() { - return isInZoneBypass; - } - - public void setInZoneBypass(boolean isInZoneBypass) { - this.isInZoneBypass = isInZoneBypass; - } - - public boolean isHasZoneInTamperTrouble() { - return hasZoneInTamperTrouble; - } - - public void setHasZoneInTamperTrouble(boolean hasZoneInTamperTrouble) { - this.hasZoneInTamperTrouble = hasZoneInTamperTrouble; - } - - public boolean isHasZoneInLowBatteryTrouble() { - return hasZoneInLowBatteryTrouble; - } - - public void setHasZoneInLowBatteryTrouble(boolean hasZoneInLowBatteryTrouble) { - this.hasZoneInLowBatteryTrouble = hasZoneInLowBatteryTrouble; - } - - public boolean isHasZoneInFireLoopTrouble() { - return hasZoneInFireLoopTrouble; - } - - public void setHasZoneInFireLoopTrouble(boolean hasZoneInFireLoopTrouble) { - this.hasZoneInFireLoopTrouble = hasZoneInFireLoopTrouble; - } - - public boolean isHasZoneInSupervisionTrouble() { - return hasZoneInSupervisionTrouble; - } - - public void setHasZoneInSupervisionTrouble(boolean hasZoneInSupervisionTrouble) { - this.hasZoneInSupervisionTrouble = hasZoneInSupervisionTrouble; - } - - public boolean isStayInstantReady() { - return isStayInstantReady; - } - - public void setStayInstantReady(boolean isStayInstantReady) { - this.isStayInstantReady = isStayInstantReady; - } - - public boolean isForceReady() { - return isForceReady; - } - - public void setForceReady(boolean isForceReady) { - this.isForceReady = isForceReady; - } - - public boolean isBypassReady() { - return isBypassReady; - } - - public void setBypassReady(boolean isBypassReady) { - this.isBypassReady = isBypassReady; - } - - public boolean isInhibitReady() { - return isInhibitReady; - } - - public void setInhibitReady(boolean isInhibitReady) { - this.isInhibitReady = isInhibitReady; - } - - public boolean isAreAllZoneclosed() { - return areAllZoneclosed; - } - - public void setAllZoneClosed(boolean areAllZoneclosed) { - this.areAllZoneclosed = areAllZoneclosed; - } - - public boolean isHasAlarmInMemory() { - return hasAlarmInMemory; - } - - public void setHasAlarmInMemory(boolean hasAlarmInMemory) { - this.hasAlarmInMemory = hasAlarmInMemory; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +/** + * The {@link Partition} Paradox partition states. Retrieved and parsed from RAM memory responses. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class PartitionState { + + private boolean isArmed; + private boolean isArmedInAway; + private boolean isArmedInStay; + private boolean isArmedInNoEntry; + private boolean isInAlarm; + private boolean isInSilentAlarm; + private boolean isInAudibleAlarm; + private boolean isInFireAlarm; + + private boolean isReadyToArm; + private boolean isInExitDelay; + private boolean isInEntryDelay; + private boolean isInTrouble; + private boolean hasAlarmInMemory; + private boolean isInZoneBypass; + + private boolean hasZoneInTamperTrouble; + private boolean hasZoneInLowBatteryTrouble; + private boolean hasZoneInFireLoopTrouble; + private boolean hasZoneInSupervisionTrouble; + + private boolean isStayInstantReady; + private boolean isForceReady; + private boolean isBypassReady; + private boolean isInhibitReady; + private boolean areAllZoneclosed; + + public String getMainState() { + if (isInAlarm) { + return "InAlarm"; + } else { + return isArmed || isArmedInAway || isArmedInStay || isArmedInNoEntry ? "Armed" : "Disarmed"; + } + } + + @Override + public String toString() { + return "PartitionState [isArmed=" + isArmed + ", isArmedInAway=" + isArmedInAway + ", isArmedInStay=" + + isArmedInStay + ", isArmedInNoEntry=" + isArmedInNoEntry + ", isInAlarm=" + isInAlarm + + ", isInSilentAlarm=" + isInSilentAlarm + ", isInAudibleAlarm=" + isInAudibleAlarm + ", isInFireAlarm=" + + isInFireAlarm + ", isReadyToArm=" + isReadyToArm + ", isInExitDelay=" + isInExitDelay + + ", isInEntryDelay=" + isInEntryDelay + ", isInTrouble=" + isInTrouble + ", hasAlarmInMemory=" + + hasAlarmInMemory + ", isInZoneBypass=" + isInZoneBypass + ", hasZoneInTamperTrouble=" + + hasZoneInTamperTrouble + ", hasZoneInLowBatteryTrouble=" + hasZoneInLowBatteryTrouble + + ", hasZoneInFireLoopTrouble=" + hasZoneInFireLoopTrouble + ", hasZoneInSupervisionTrouble=" + + hasZoneInSupervisionTrouble + ", isStayInstantReady=" + isStayInstantReady + ", isForceReady=" + + isForceReady + ", isBypassReady=" + isBypassReady + ", isInhibitReady=" + isInhibitReady + + ", areAllZoneclosed=" + areAllZoneclosed + "]"; + } + + public boolean isArmed() { + return isArmed; + } + + public void setArmed(boolean isArmed) { + this.isArmed = isArmed; + } + + public boolean isArmedInAway() { + return isArmedInAway; + } + + public void setArmedInAway(boolean isArmedInAway) { + this.isArmedInAway = isArmedInAway; + } + + public boolean isArmedInStay() { + return isArmedInStay; + } + + public void setArmedInStay(boolean isArmedInStay) { + this.isArmedInStay = isArmedInStay; + } + + public boolean isArmedInNoEntry() { + return isArmedInNoEntry; + } + + public void setArmedInNoEntry(boolean isArmedInNoEntry) { + this.isArmedInNoEntry = isArmedInNoEntry; + } + + public boolean isInAlarm() { + return isInAlarm; + } + + public void setInAlarm(boolean isInAlarm) { + this.isInAlarm = isInAlarm; + } + + public boolean isInSilentAlarm() { + return isInSilentAlarm; + } + + public void setInSilentAlarm(boolean isInSilentAlarm) { + this.isInSilentAlarm = isInSilentAlarm; + } + + public boolean isInAudibleAlarm() { + return isInAudibleAlarm; + } + + public void setInAudibleAlarm(boolean isInAudibleAlarm) { + this.isInAudibleAlarm = isInAudibleAlarm; + } + + public boolean isInFireAlarm() { + return isInFireAlarm; + } + + public void setInFireAlarm(boolean isInFireAlarm) { + this.isInFireAlarm = isInFireAlarm; + } + + public boolean isReadyToArm() { + return isReadyToArm; + } + + public void setReadyToArm(boolean isReadyToArm) { + this.isReadyToArm = isReadyToArm; + } + + public boolean isInExitDelay() { + return isInExitDelay; + } + + public void setInExitDelay(boolean isInExitDelay) { + this.isInExitDelay = isInExitDelay; + } + + public boolean isInEntryDelay() { + return isInEntryDelay; + } + + public void setInEntryDelay(boolean isInEntryDelay) { + this.isInEntryDelay = isInEntryDelay; + } + + public boolean isInTrouble() { + return isInTrouble; + } + + public void setInTrouble(boolean isInTrouble) { + this.isInTrouble = isInTrouble; + } + + public boolean isHasAarmInMemory() { + return hasAlarmInMemory; + } + + public void setHasAarmInMemory(boolean hasAarmInMemory) { + this.hasAlarmInMemory = hasAarmInMemory; + } + + public boolean isInZoneBypass() { + return isInZoneBypass; + } + + public void setInZoneBypass(boolean isInZoneBypass) { + this.isInZoneBypass = isInZoneBypass; + } + + public boolean isHasZoneInTamperTrouble() { + return hasZoneInTamperTrouble; + } + + public void setHasZoneInTamperTrouble(boolean hasZoneInTamperTrouble) { + this.hasZoneInTamperTrouble = hasZoneInTamperTrouble; + } + + public boolean isHasZoneInLowBatteryTrouble() { + return hasZoneInLowBatteryTrouble; + } + + public void setHasZoneInLowBatteryTrouble(boolean hasZoneInLowBatteryTrouble) { + this.hasZoneInLowBatteryTrouble = hasZoneInLowBatteryTrouble; + } + + public boolean isHasZoneInFireLoopTrouble() { + return hasZoneInFireLoopTrouble; + } + + public void setHasZoneInFireLoopTrouble(boolean hasZoneInFireLoopTrouble) { + this.hasZoneInFireLoopTrouble = hasZoneInFireLoopTrouble; + } + + public boolean isHasZoneInSupervisionTrouble() { + return hasZoneInSupervisionTrouble; + } + + public void setHasZoneInSupervisionTrouble(boolean hasZoneInSupervisionTrouble) { + this.hasZoneInSupervisionTrouble = hasZoneInSupervisionTrouble; + } + + public boolean isStayInstantReady() { + return isStayInstantReady; + } + + public void setStayInstantReady(boolean isStayInstantReady) { + this.isStayInstantReady = isStayInstantReady; + } + + public boolean isForceReady() { + return isForceReady; + } + + public void setForceReady(boolean isForceReady) { + this.isForceReady = isForceReady; + } + + public boolean isBypassReady() { + return isBypassReady; + } + + public void setBypassReady(boolean isBypassReady) { + this.isBypassReady = isBypassReady; + } + + public boolean isInhibitReady() { + return isInhibitReady; + } + + public void setInhibitReady(boolean isInhibitReady) { + this.isInhibitReady = isInhibitReady; + } + + public boolean isAreAllZoneclosed() { + return areAllZoneclosed; + } + + public void setAllZoneClosed(boolean areAllZoneclosed) { + this.areAllZoneclosed = areAllZoneclosed; + } + + public boolean isHasAlarmInMemory() { + return hasAlarmInMemory; + } + + public void setHasAlarmInMemory(boolean hasAlarmInMemory) { + this.hasAlarmInMemory = hasAlarmInMemory; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Version.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Version.java index 982d4931ca1b7..8721b6f907c8d 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Version.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Version.java @@ -1,99 +1,98 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -import java.util.Date; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link Version} This class holds version information - * - * @author Konstantin Polihronov - Initial contribution - */ -public class Version { - private final Logger logger = LoggerFactory.getLogger(Version.class); - - private Byte version; - private Byte revision; - private Byte build; - private Date buildTime; - - public Version(Byte version, Byte revision) { - this(version, revision, null); - } - - public Version(Byte version, Byte revision, Byte build) { - this(version, revision, build, null); - } - - public Version(Byte version, Byte revision, Byte build, Date buildTime) { - this.version = version; - this.revision = revision; - this.build = build; - this.buildTime = buildTime; - logger.debug("version={}", this); - } - - public Byte getVersion() { - return version; - } - - public void setVersion(Byte version) { - this.version = version; - } - - public Byte getRevision() { - return revision; - } - - public void setRevision(Byte revision) { - this.revision = revision; - } - - public Byte getBuild() { - return build; - } - - public void setBuild(Byte build) { - this.build = build; - } - - public Date getBuildTime() { - return buildTime; - } - - public void setBuildTime(Date buildTime) { - this.buildTime = buildTime; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Version: "); - sb.append(version); - sb.append("."); - sb.append(revision); - if (build != null) { - sb.append("."); - sb.append(build); - } - if (buildTime != null) { - sb.append("/"); - sb.append(buildTime); - } - return sb.toString(); - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +import java.util.Date; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link Version} This class holds version information + * + * @author Konstantin Polihronov - Initial contribution + */ +public class Version { + private final Logger logger = LoggerFactory.getLogger(Version.class); + + private Byte version; + private Byte revision; + private Byte build; + private Date buildTime; + + public Version(Byte version, Byte revision) { + this(version, revision, null); + } + + public Version(Byte version, Byte revision, Byte build) { + this(version, revision, build, null); + } + + public Version(Byte version, Byte revision, Byte build, Date buildTime) { + this.version = version; + this.revision = revision; + this.build = build; + this.buildTime = buildTime; + logger.debug("version={}", this); + } + + public Byte getVersion() { + return version; + } + + public void setVersion(Byte version) { + this.version = version; + } + + public Byte getRevision() { + return revision; + } + + public void setRevision(Byte revision) { + this.revision = revision; + } + + public Byte getBuild() { + return build; + } + + public void setBuild(Byte build) { + this.build = build; + } + + public Date getBuildTime() { + return buildTime; + } + + public void setBuildTime(Date buildTime) { + this.buildTime = buildTime; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Version: "); + sb.append(version); + sb.append("."); + sb.append(revision); + if (build != null) { + sb.append("."); + sb.append(build); + } + if (buildTime != null) { + sb.append("/"); + sb.append(buildTime); + } + return sb.toString(); + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Zone.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Zone.java index f8517a9961261..6629466e640ae 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Zone.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/Zone.java @@ -1,44 +1,44 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link Zone} Paradox zone. - * ID is always numeric (1-8 for Evo192) - * States are taken from cached RAM memory map and parsed. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class Zone extends Entity { - - private final Logger logger = LoggerFactory.getLogger(Zone.class); - - private ZoneState zoneState; - - public Zone(int id, String label) { - super(id, label); - } - - public ZoneState getZoneState() { - return zoneState; - } - - public void setZoneState(ZoneState zoneState) { - this.zoneState = zoneState; - logger.debug("Zone {} state updated to:\tOpened: {}, Tampered: {}, LowBattery: {}", getLabel(), - zoneState.isOpened(), zoneState.isTampered(), zoneState.hasLowBattery()); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link Zone} Paradox zone. + * ID is always numeric (1-8 for Evo192) + * States are taken from cached RAM memory map and parsed. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class Zone extends Entity { + + private final Logger logger = LoggerFactory.getLogger(Zone.class); + + private ZoneState zoneState; + + public Zone(int id, String label) { + super(id, label); + } + + public ZoneState getZoneState() { + return zoneState; + } + + public void setZoneState(ZoneState zoneState) { + this.zoneState = zoneState; + logger.debug("Zone {} state updated to:\tOpened: {}, Tampered: {}, LowBattery: {}", getLabel(), + zoneState.isOpened(), zoneState.isTampered(), zoneState.hasLowBattery()); + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ZoneState.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ZoneState.java index e0847130df425..313ca7d07c37f 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ZoneState.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ZoneState.java @@ -1,54 +1,54 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -/** - * The {@link ZoneStateFlags} Paradox zone state flags. Retrieved and parsed from RAM memory responses. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ZoneState { - private boolean isOpened; - private boolean isTampered; - private boolean hasLowBattery; - - public ZoneState(boolean isOpened, boolean isTampered, boolean hasLowBattery) { - this.isOpened = isOpened; - this.isTampered = isTampered; - this.hasLowBattery = hasLowBattery; - } - - public boolean isOpened() { - return isOpened; - } - - public void setOpened(boolean isOpened) { - this.isOpened = isOpened; - } - - public boolean isTampered() { - return isTampered; - } - - public void setTampered(boolean isTampered) { - this.isTampered = isTampered; - } - - public boolean hasLowBattery() { - return hasLowBattery; - } - - public void setHasLowBattery(boolean hasLowBattery) { - this.hasLowBattery = hasLowBattery; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +/** + * The {@link ZoneStateFlags} Paradox zone state flags. Retrieved and parsed from RAM memory responses. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ZoneState { + private boolean isOpened; + private boolean isTampered; + private boolean hasLowBattery; + + public ZoneState(boolean isOpened, boolean isTampered, boolean hasLowBattery) { + this.isOpened = isOpened; + this.isTampered = isTampered; + this.hasLowBattery = hasLowBattery; + } + + public boolean isOpened() { + return isOpened; + } + + public void setOpened(boolean isOpened) { + this.isOpened = isOpened; + } + + public boolean isTampered() { + return isTampered; + } + + public void setTampered(boolean isTampered) { + this.isTampered = isTampered; + } + + public boolean hasLowBattery() { + return hasLowBattery; + } + + public void setHasLowBattery(boolean hasLowBattery) { + this.hasLowBattery = hasLowBattery; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ZoneStateFlags.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ZoneStateFlags.java index 41bad2a9e9079..c30bf6711b9e7 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ZoneStateFlags.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/model/ZoneStateFlags.java @@ -1,49 +1,48 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.model; - -/** - * The {@link ZoneStateFlags} Paradox zone state flags. Retrieved and parsed from RAM memory responses. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ZoneStateFlags { - private byte[] zonesOpened; - private byte[] zonesTampered; - private byte[] zonesLowBattery; - - public byte[] getZonesOpened() { - return zonesOpened; - } - - public void setZonesOpened(byte[] zonesOpened) { - this.zonesOpened = zonesOpened; - } - - public byte[] getZonesTampered() { - return zonesTampered; - } - - public void setZonesTampered(byte[] zonesTampered) { - this.zonesTampered = zonesTampered; - } - - public byte[] getZonesLowBattery() { - return zonesLowBattery; - } - - public void setZonesLowBattery(byte[] zonesLowBattery) { - this.zonesLowBattery = zonesLowBattery; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.model; + +/** + * The {@link ZoneStateFlags} Paradox zone state flags. Retrieved and parsed from RAM memory responses. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ZoneStateFlags { + private byte[] zonesOpened; + private byte[] zonesTampered; + private byte[] zonesLowBattery; + + public byte[] getZonesOpened() { + return zonesOpened; + } + + public void setZonesOpened(byte[] zonesOpened) { + this.zonesOpened = zonesOpened; + } + + public byte[] getZonesTampered() { + return zonesTampered; + } + + public void setZonesTampered(byte[] zonesTampered) { + this.zonesTampered = zonesTampered; + } + + public byte[] getZonesLowBattery() { + return zonesLowBattery; + } + + public void setZonesLowBattery(byte[] zonesLowBattery) { + this.zonesLowBattery = zonesLowBattery; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/AbstractParser.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/AbstractParser.java index 117c7e0760c83..745f200aeacb1 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/AbstractParser.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/AbstractParser.java @@ -1,42 +1,42 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.parsers; - -import org.openhab.binding.paradoxalarm.internal.model.Version; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link AbstractParser} Contains parsing methods irelevant from panel type - * - * @author Konstantin Polihronov - Initial contribution - */ -public abstract class AbstractParser implements IParadoxParser { - - private final Logger logger = LoggerFactory.getLogger(AbstractParser.class); - - @Override - public Version parseApplicationVersion(byte[] panelInfoBytes) { - return new Version(panelInfoBytes[9], panelInfoBytes[10], panelInfoBytes[11]); - } - - @Override - public Version parseHardwareVersion(byte[] panelInfoBytes) { - return new Version(panelInfoBytes[16], panelInfoBytes[17]); - } - - @Override - public Version parseBootloaderVersion(byte[] panelInfoBytes) { - return new Version(panelInfoBytes[18], panelInfoBytes[19], panelInfoBytes[20]); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.parsers; + +import org.openhab.binding.paradoxalarm.internal.model.Version; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link AbstractParser} Contains parsing methods irelevant from panel type + * + * @author Konstantin Polihronov - Initial contribution + */ +public abstract class AbstractParser implements IParadoxParser { + + private final Logger logger = LoggerFactory.getLogger(AbstractParser.class); + + @Override + public Version parseApplicationVersion(byte[] panelInfoBytes) { + return new Version(panelInfoBytes[9], panelInfoBytes[10], panelInfoBytes[11]); + } + + @Override + public Version parseHardwareVersion(byte[] panelInfoBytes) { + return new Version(panelInfoBytes[16], panelInfoBytes[17]); + } + + @Override + public Version parseBootloaderVersion(byte[] panelInfoBytes) { + return new Version(panelInfoBytes[18], panelInfoBytes[19], panelInfoBytes[20]); + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/EvoParser.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/EvoParser.java index 9de9b616cd88f..b8fbe175a9f8a 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/EvoParser.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/EvoParser.java @@ -1,82 +1,81 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.parsers; - -import org.openhab.binding.paradoxalarm.internal.model.PartitionState; -import org.openhab.binding.paradoxalarm.internal.model.ZoneState; -import org.openhab.binding.paradoxalarm.internal.model.ZoneStateFlags; -import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; - -/** - * The {@link EvoParser} Implementation of parser interface for EVO type panels - * - * @author Konstantin Polihronov - Initial contribution - */ -public class EvoParser extends AbstractParser { - - @Override - public PartitionState calculatePartitionState(byte[] partitionFlags) { - byte firstByte = partitionFlags[0]; - PartitionState state = new PartitionState(); - state.setArmed(ParadoxUtil.isBitSet(firstByte, 0)); - state.setArmedInAway(ParadoxUtil.isBitSet(firstByte, 1)); - state.setArmedInStay(ParadoxUtil.isBitSet(firstByte, 2)); - state.setArmedInNoEntry(ParadoxUtil.isBitSet(firstByte, 3)); - - state.setInAlarm(ParadoxUtil.isBitSet(firstByte, 4)); - state.setInSilentAlarm(ParadoxUtil.isBitSet(firstByte, 5)); - state.setInAudibleAlarm(ParadoxUtil.isBitSet(firstByte, 6)); - state.setInFireAlarm(ParadoxUtil.isBitSet(firstByte, 7)); - - byte secondByte = partitionFlags[1]; - state.setReadyToArm(ParadoxUtil.isBitSet(secondByte, 0)); - state.setInExitDelay(ParadoxUtil.isBitSet(secondByte, 1)); - state.setInEntryDelay(ParadoxUtil.isBitSet(secondByte, 2)); - state.setInTrouble(ParadoxUtil.isBitSet(secondByte, 3)); - state.setHasAlarmInMemory(ParadoxUtil.isBitSet(secondByte, 4)); - state.setInZoneBypass(ParadoxUtil.isBitSet(secondByte, 5)); - - byte thirdByte = partitionFlags[2]; - state.setHasZoneInTamperTrouble(ParadoxUtil.isBitSet(thirdByte, 4)); - state.setHasZoneInLowBatteryTrouble(ParadoxUtil.isBitSet(thirdByte, 5)); - state.setHasZoneInFireLoopTrouble(ParadoxUtil.isBitSet(thirdByte, 6)); - state.setHasZoneInSupervisionTrouble(ParadoxUtil.isBitSet(thirdByte, 7)); - - byte sixthByte = partitionFlags[5]; - state.setStayInstantReady(ParadoxUtil.isBitSet(sixthByte, 0)); - state.setForceReady(ParadoxUtil.isBitSet(sixthByte, 1)); - state.setBypassReady(ParadoxUtil.isBitSet(sixthByte, 2)); - state.setInhibitReady(ParadoxUtil.isBitSet(sixthByte, 3)); - state.setAllZoneClosed(ParadoxUtil.isBitSet(sixthByte, 4)); - - return state; - } - - @Override - public ZoneState calculateZoneState(int id, ZoneStateFlags zoneStateFlags) { - int index = (id - 1) / 8; - int bitNumber = id % 8 - 1; - - byte[] zonesOpened = zoneStateFlags.getZonesOpened(); - boolean isOpened = ParadoxUtil.isBitSet(zonesOpened[index], bitNumber); - - byte[] zonesTampered = zoneStateFlags.getZonesTampered(); - boolean isTampered = ParadoxUtil.isBitSet(zonesTampered[index], bitNumber); - - byte[] zonesLowBattery = zoneStateFlags.getZonesLowBattery(); - boolean hasLowBattery = ParadoxUtil.isBitSet(zonesLowBattery[index], bitNumber); - - return new ZoneState(isOpened, isTampered, hasLowBattery); - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.parsers; + +import org.openhab.binding.paradoxalarm.internal.model.PartitionState; +import org.openhab.binding.paradoxalarm.internal.model.ZoneState; +import org.openhab.binding.paradoxalarm.internal.model.ZoneStateFlags; +import org.openhab.binding.paradoxalarm.internal.util.ParadoxUtil; + +/** + * The {@link EvoParser} Implementation of parser interface for EVO type panels + * + * @author Konstantin Polihronov - Initial contribution + */ +public class EvoParser extends AbstractParser { + + @Override + public PartitionState calculatePartitionState(byte[] partitionFlags) { + byte firstByte = partitionFlags[0]; + PartitionState state = new PartitionState(); + state.setArmed(ParadoxUtil.isBitSet(firstByte, 0)); + state.setArmedInAway(ParadoxUtil.isBitSet(firstByte, 1)); + state.setArmedInStay(ParadoxUtil.isBitSet(firstByte, 2)); + state.setArmedInNoEntry(ParadoxUtil.isBitSet(firstByte, 3)); + + state.setInAlarm(ParadoxUtil.isBitSet(firstByte, 4)); + state.setInSilentAlarm(ParadoxUtil.isBitSet(firstByte, 5)); + state.setInAudibleAlarm(ParadoxUtil.isBitSet(firstByte, 6)); + state.setInFireAlarm(ParadoxUtil.isBitSet(firstByte, 7)); + + byte secondByte = partitionFlags[1]; + state.setReadyToArm(ParadoxUtil.isBitSet(secondByte, 0)); + state.setInExitDelay(ParadoxUtil.isBitSet(secondByte, 1)); + state.setInEntryDelay(ParadoxUtil.isBitSet(secondByte, 2)); + state.setInTrouble(ParadoxUtil.isBitSet(secondByte, 3)); + state.setHasAlarmInMemory(ParadoxUtil.isBitSet(secondByte, 4)); + state.setInZoneBypass(ParadoxUtil.isBitSet(secondByte, 5)); + + byte thirdByte = partitionFlags[2]; + state.setHasZoneInTamperTrouble(ParadoxUtil.isBitSet(thirdByte, 4)); + state.setHasZoneInLowBatteryTrouble(ParadoxUtil.isBitSet(thirdByte, 5)); + state.setHasZoneInFireLoopTrouble(ParadoxUtil.isBitSet(thirdByte, 6)); + state.setHasZoneInSupervisionTrouble(ParadoxUtil.isBitSet(thirdByte, 7)); + + byte sixthByte = partitionFlags[5]; + state.setStayInstantReady(ParadoxUtil.isBitSet(sixthByte, 0)); + state.setForceReady(ParadoxUtil.isBitSet(sixthByte, 1)); + state.setBypassReady(ParadoxUtil.isBitSet(sixthByte, 2)); + state.setInhibitReady(ParadoxUtil.isBitSet(sixthByte, 3)); + state.setAllZoneClosed(ParadoxUtil.isBitSet(sixthByte, 4)); + + return state; + } + + @Override + public ZoneState calculateZoneState(int id, ZoneStateFlags zoneStateFlags) { + int index = (id - 1) / 8; + int bitNumber = id % 8 - 1; + + byte[] zonesOpened = zoneStateFlags.getZonesOpened(); + boolean isOpened = ParadoxUtil.isBitSet(zonesOpened[index], bitNumber); + + byte[] zonesTampered = zoneStateFlags.getZonesTampered(); + boolean isTampered = ParadoxUtil.isBitSet(zonesTampered[index], bitNumber); + + byte[] zonesLowBattery = zoneStateFlags.getZonesLowBattery(); + boolean hasLowBattery = ParadoxUtil.isBitSet(zonesLowBattery[index], bitNumber); + + return new ZoneState(isOpened, isTampered, hasLowBattery); + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/IParadoxParser.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/IParadoxParser.java index 5459fb7e89973..b31ec6da9b982 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/IParadoxParser.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/parsers/IParadoxParser.java @@ -1,35 +1,35 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.parsers; - -import org.openhab.binding.paradoxalarm.internal.model.PartitionState; -import org.openhab.binding.paradoxalarm.internal.model.Version; -import org.openhab.binding.paradoxalarm.internal.model.ZoneState; -import org.openhab.binding.paradoxalarm.internal.model.ZoneStateFlags; - -/** - * The {@link IParadoxParser} Interface for Paradox Parsers implementations - * - * @author Konstantin Polihronov - Initial contribution - */ -public interface IParadoxParser { - PartitionState calculatePartitionState(byte[] partitionFlags); - - ZoneState calculateZoneState(int id, ZoneStateFlags zoneStateFlags); - - Version parseApplicationVersion(byte[] panelInfoBytes); - - Version parseHardwareVersion(byte[] panelInfoBytes); - - Version parseBootloaderVersion(byte[] panelInfoBytes); -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.parsers; + +import org.openhab.binding.paradoxalarm.internal.model.PartitionState; +import org.openhab.binding.paradoxalarm.internal.model.Version; +import org.openhab.binding.paradoxalarm.internal.model.ZoneState; +import org.openhab.binding.paradoxalarm.internal.model.ZoneStateFlags; + +/** + * The {@link IParadoxParser} Interface for Paradox Parsers implementations + * + * @author Konstantin Polihronov - Initial contribution + */ +public interface IParadoxParser { + PartitionState calculatePartitionState(byte[] partitionFlags); + + ZoneState calculateZoneState(int id, ZoneStateFlags zoneStateFlags); + + Version parseApplicationVersion(byte[] panelInfoBytes); + + Version parseHardwareVersion(byte[] panelInfoBytes); + + Version parseBootloaderVersion(byte[] panelInfoBytes); +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/util/ParadoxUtil.java b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/util/ParadoxUtil.java index d5a26f9df7e80..86552845517ca 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/util/ParadoxUtil.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/java/org/openhab/binding/paradoxalarm/internal/util/ParadoxUtil.java @@ -1,135 +1,134 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.paradoxalarm.internal.util; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link ParadoxUtil} Utility class for different calculations / manipulations of data in the model and - * communicators. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class ParadoxUtil { - - private static final Logger logger = LoggerFactory.getLogger(ParadoxUtil.class); - - public static byte calculateChecksum(byte[] payload) { - int result = 0; - for (byte everyByte : payload) { - result += everyByte; - } - - return (byte) (result % 256); - } - - public static byte getBit(int value, int bitNumber) { - return (byte) ((value >> bitNumber) & 1); - } - - public static boolean isBitSet(int value, int bitNumber) { - return ((value >> bitNumber) & 1) == 1; - } - - public static void printPacket(String description, byte[] array) { - if (logger.isTraceEnabled()) { - logger.trace("Packet payload size: {}", array[1]); - printByteArray(description, array, array[1] + 16); - } - } - - private static void printByteArray(String description, byte[] array, int length) { - if (description != null && !description.isEmpty()) { - logger.trace("{}", description); - } - int countBytes = 0; - String result = ""; - for (int index = 0; index < length; index++) { - countBytes++; - String st = String.format("0x%02X,\t", array[index]); - result += st; - if (countBytes > 7) { - logger.trace(result); - countBytes = 0; - result = ""; - continue; - } - } - if (!result.isEmpty()) { - logger.trace(result); - } - - } - - public static byte setBit(byte byteValue, int i, int j) { - if (j == 1) { - return (byte) (byteValue | (1 << i)); - } else { - return (byte) (byteValue & ~(1 << i)); - } - } - - public static byte getHighNibble(byte value) { - return (byte) ((value & 0xF0) >> 4); - } - - public static byte getLowNibble(byte value) { - return (byte) (value & 0x0F); - } - - public static byte[] mergeByteArrays(byte[]... arrays) { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - for (byte[] array : arrays) { - outputStream.write(array); - } - byte[] byteArray = outputStream.toByteArray(); - return byteArray; - } catch (IOException e) { - logger.warn("Exception merging arrays:", e); - return new byte[0]; - } - } - - public static byte[] intToByteArray(int value) { - return ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).order(ByteOrder.BIG_ENDIAN).putInt(value).array(); - } - - public static byte[] shortToByteArray(short value) { - return ByteBuffer.allocate(Short.SIZE / Byte.SIZE).order(ByteOrder.BIG_ENDIAN).putShort(value).array(); - } - - public static byte[] stringToBCD(String pcPassword) { - return stringToBCD(pcPassword, 4); - } - - public static byte[] stringToBCD(String pcPassword, int numberOfDigits) { - byte[] result = new byte[numberOfDigits / 2]; - for (int i = 0, j = 0; i < 2; i++, j += 2) { - String substring = pcPassword.substring(j, j + 1); - int parseInt = Integer.parseInt(substring); - result[i] = (byte) ((parseInt & 0x0F) << 4); - - substring = pcPassword.substring(j + 1, j + 2); - parseInt = Integer.parseInt(substring); - result[i] |= (byte) (parseInt & 0x0F); - } - return result; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.paradoxalarm.internal.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link ParadoxUtil} Utility class for different calculations / manipulations of data in the model and + * communicators. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class ParadoxUtil { + + private static final Logger logger = LoggerFactory.getLogger(ParadoxUtil.class); + + public static byte calculateChecksum(byte[] payload) { + int result = 0; + for (byte everyByte : payload) { + result += everyByte; + } + + return (byte) (result % 256); + } + + public static byte getBit(int value, int bitNumber) { + return (byte) ((value >> bitNumber) & 1); + } + + public static boolean isBitSet(int value, int bitNumber) { + return ((value >> bitNumber) & 1) == 1; + } + + public static void printPacket(String description, byte[] array) { + if (logger.isTraceEnabled()) { + logger.trace("Packet payload size: {}", array[1]); + printByteArray(description, array, array[1] + 16); + } + } + + private static void printByteArray(String description, byte[] array, int length) { + if (description != null && !description.isEmpty()) { + logger.trace("{}", description); + } + int countBytes = 0; + String result = ""; + for (int index = 0; index < length; index++) { + countBytes++; + String st = String.format("0x%02X,\t", array[index]); + result += st; + if (countBytes > 7) { + logger.trace(result); + countBytes = 0; + result = ""; + continue; + } + } + if (!result.isEmpty()) { + logger.trace(result); + } + } + + public static byte setBit(byte byteValue, int i, int j) { + if (j == 1) { + return (byte) (byteValue | (1 << i)); + } else { + return (byte) (byteValue & ~(1 << i)); + } + } + + public static byte getHighNibble(byte value) { + return (byte) ((value & 0xF0) >> 4); + } + + public static byte getLowNibble(byte value) { + return (byte) (value & 0x0F); + } + + public static byte[] mergeByteArrays(byte[]... arrays) { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + for (byte[] array : arrays) { + outputStream.write(array); + } + byte[] byteArray = outputStream.toByteArray(); + return byteArray; + } catch (IOException e) { + logger.warn("Exception merging arrays:", e); + return new byte[0]; + } + } + + public static byte[] intToByteArray(int value) { + return ByteBuffer.allocate(Integer.SIZE / Byte.SIZE).order(ByteOrder.BIG_ENDIAN).putInt(value).array(); + } + + public static byte[] shortToByteArray(short value) { + return ByteBuffer.allocate(Short.SIZE / Byte.SIZE).order(ByteOrder.BIG_ENDIAN).putShort(value).array(); + } + + public static byte[] stringToBCD(String pcPassword) { + return stringToBCD(pcPassword, 4); + } + + public static byte[] stringToBCD(String pcPassword, int numberOfDigits) { + byte[] result = new byte[numberOfDigits / 2]; + for (int i = 0, j = 0; i < 2; i++, j += 2) { + String substring = pcPassword.substring(j, j + 1); + int parseInt = Integer.parseInt(substring); + result[i] = (byte) ((parseInt & 0x0F) << 4); + + substring = pcPassword.substring(j + 1, j + 2); + parseInt = Integer.parseInt(substring); + result[i] |= (byte) (parseInt & 0x0F); + } + return result; + } +} diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/binding/binding.xml index eecdcc6d2f912..8138874b4ca7a 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/binding/binding.xml @@ -1,10 +1,10 @@ - - - - ParadoxAlarm Binding - This is the binding for ParadoxAlarm. - Konstantin Polihronov - - + + + + ParadoxAlarm Binding + This is the binding for ParadoxAlarm. + Konstantin Polihronov + + diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/ip150connector.xml b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/ip150connector.xml index f138639905b5a..e85fdf43800f3 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/ip150connector.xml +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/ip150connector.xml @@ -1,69 +1,69 @@ - - - - - - Paradox IP150 module connector - - - - - - - - - Specifies the refresh interval in seconds. - 5 - - - - PanelType - - - - Password for accessing IP150 - password - - - - PC Password (section 3012 of configuration) - 0000 - password - - - - IP address or host name of IP150 - network-address - - - - Port to connect to IP150 - 10000 - - - - The time to wait before a reconnect occurs after socket timeout. Value is in seconds - 30 - - - - Maximum number of configured zones to check (from zone 1 to maxZones) - 0 - - - - Maximum number of configured partitions to check (from partition 1 to maxPartitions) - 0 - - - - - - String - - Send Command - - + + + + + + Paradox IP150 module connector + + + + + + + + + Specifies the refresh interval in seconds. + 5 + + + + PanelType + + + + Password for accessing IP150 + password + + + + PC Password (section 3012 of configuration) + 0000 + password + + + + IP address or host name of IP150 + network-address + + + + Port to connect to IP150 + 10000 + + + + The time to wait before a reconnect occurs after socket timeout. Value is in seconds + 30 + + + + Maximum number of configured zones to check (from zone 1 to maxZones) + 0 + + + + Maximum number of configured partitions to check (from partition 1 to maxPartitions) + 0 + + + + + + String + + Send Command + + diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/panel.xml b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/panel.xml index f6122b607a3ed..6b3186bce7015 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/panel.xml +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/panel.xml @@ -1,64 +1,64 @@ - - - - - - - - - - Paradox panel various information - - - - - - - - - - - - - - - String - - Shows the state of the communication to panel (online/offline) - - - - String - - Panel serial number - - - - String - - Panel type (Evo, SP, etc) - - - - String - - Panel hardware version - - - - String - - Panel application version - - - - String - - Boot loader version - - - - + + + + + + + + + + Paradox panel various information + + + + + + + + + + + + + + + String + + Shows the state of the communication to panel (online/offline) + + + + String + + Panel serial number + + + + String + + Panel type (Evo, SP, etc) + + + + String + + Panel hardware version + + + + String + + Panel application version + + + + String + + Boot loader version + + + + diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/partition.xml b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/partition.xml index 57d3041f9ce5d..bdb1b384744da 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/partition.xml +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/partition.xml @@ -1,152 +1,152 @@ - - - - - - - - - - Paradox Partition - - - - - - - - - - - - - - - - - - - - - - - - - - This is the partition ID of the Paradox partition (1-8 for Evo) - - - - - - String - - Label of partition - - - - String - - State of partition - - - - String - - Additional states provided by panel (deprecated channel) - - - - switch - - Partition ready to arm - - - - switch - - Partition in Exit Delay - - - - switch - - Partition in Entry Delay - - - - switch - - Partition in Trouble - - - - switch - - Partition has Alarm in Memory - - - - switch - - Partition has Zone Bypass - - - - switch - - Partition has in Tamper Trouble - - - - switch - - Partition has in Low Battery Trouble - - - - switch - - Partition has in Fire Loop Trouble - - - - switch - - Partition has in Supervision Trouble - - - - switch - - Partition is Stay Instant Ready - - - - switch - - Partition is Force Ready - - - - switch - - Partition is Bypass Ready - - - - switch - - Partition is Inhibit Ready - - - - contact - - Partition has All Zones closed - - - + + + + + + + + + + Paradox Partition + + + + + + + + + + + + + + + + + + + + + + + + + + This is the partition ID of the Paradox partition (1-8 for Evo) + + + + + + String + + Label of partition + + + + String + + State of partition + + + + String + + Additional states provided by panel (deprecated channel) + + + + switch + + Partition ready to arm + + + + switch + + Partition in Exit Delay + + + + switch + + Partition in Entry Delay + + + + switch + + Partition in Trouble + + + + switch + + Partition has Alarm in Memory + + + + switch + + Partition has Zone Bypass + + + + switch + + Partition has in Tamper Trouble + + + + switch + + Partition has in Low Battery Trouble + + + + switch + + Partition has in Fire Loop Trouble + + + + switch + + Partition has in Supervision Trouble + + + + switch + + Partition is Stay Instant Ready + + + + switch + + Partition is Force Ready + + + + switch + + Partition is Bypass Ready + + + + switch + + Partition is Inhibit Ready + + + + contact + + Partition has All Zones closed + + + diff --git a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/zone.xml b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/zone.xml index e7ea634cd22aa..e49683063287d 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/zone.xml +++ b/bundles/org.openhab.binding.paradoxalarm/src/main/resources/ESH-INF/thing/zone.xml @@ -1,47 +1,47 @@ - - - - - - - - - Paradox zone - - - - - - - - - - - - This is the zone ID in the Paradox configuration - - - - - - String - - Label of zone - - - - contact - - State of zone - - - - switch - - State of zone - - - + + + + + + + + + Paradox zone + + + + + + + + + + + + This is the zone ID in the Paradox configuration + + + + + + String + + Label of zone + + + + contact + + State of zone + + + + switch + + State of zone + + + diff --git a/bundles/org.openhab.binding.paradoxalarm/src/test/java/main/Main.java b/bundles/org.openhab.binding.paradoxalarm/src/test/java/main/Main.java index ee2a54e66e42c..d783ad5f600e8 100644 --- a/bundles/org.openhab.binding.paradoxalarm/src/test/java/main/Main.java +++ b/bundles/org.openhab.binding.paradoxalarm/src/test/java/main/Main.java @@ -1,144 +1,143 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package main; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.openhab.binding.paradoxalarm.internal.communication.ICommunicatorBuilder; -import org.openhab.binding.paradoxalarm.internal.communication.IParadoxCommunicator; -import org.openhab.binding.paradoxalarm.internal.communication.ParadoxBuilderFactory; -import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; -import org.openhab.binding.paradoxalarm.internal.model.PanelType; -import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; -import org.openhab.binding.paradoxalarm.internal.model.Partition; -import org.openhab.binding.paradoxalarm.internal.model.Zone; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The {@link Main} - used for testing purposes of low-level stuff. - * - * @author Konstantin Polihronov - Initial contribution - */ -public class Main { - - private static Logger logger = LoggerFactory.getLogger(Main.class); - - private static String ipAddress; - private static int port; - - // PASSWORD is your IP150 password - private static String ip150Password; - - // PC Password is the value of section 3012, i.e. if value is 0987, PC Password is two bytes 0x09, 0x87 - private static String pcPassword; - - private static ScheduledExecutorService scheduler; - - private static final String LOG_LEVEL = "DEBUG"; - - private static IParadoxCommunicator communicator; - - public static void main(String[] args) { - System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, LOG_LEVEL); - - readArguments(args); - - try { - scheduler = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors()); - - ParadoxBuilderFactory factory = new ParadoxBuilderFactory(); - ICommunicatorBuilder builder = factory.createBuilder(PanelType.EVO192); - communicator = builder.withIp150Password(ip150Password).withPcPassword(pcPassword).withIpAddress(ipAddress) - .withTcpPort(port).withMaxPartitions(4).withMaxZones(60).withScheduler(scheduler).build(); - - ParadoxPanel panel = ParadoxPanel.getInstance(); - panel.setCommunicator(communicator); - - communicator.setListeners(Arrays.asList(panel)); - - panel.setCommunicator(communicator); - - // scheduler.schedule(communicator::initializeEpromData, 2, TimeUnit.SECONDS); - // scheduler.schedule(communicator::refreshMemoryMap, 2, TimeUnit.SECONDS); - - scheduler.scheduleWithFixedDelay(() -> { - updateDataCache(communicator, false); - }, 7, 5, TimeUnit.SECONDS); - } catch (Exception e) { - logger.error("Exception: ", e); - System.exit(0); - } - } - - private static void updateDataCache(IParadoxCommunicator communicator, boolean withEpromValues) { - logger.debug("Refreshing memory map"); - communicator.refreshMemoryMap(); - } - - private static List initializeZones(IParadoxCommunicator paradoxSystem) - throws IOException, InterruptedException, ParadoxException { - Map zoneLabels = paradoxSystem.getZoneLabels(); - List zones = new ArrayList<>(); - for (int i = 0; i < 40; i++) { - Zone zone = new Zone(i + 1, zoneLabels.get(i)); - zones.add(zone); - } - return zones; - } - - private static List initializePartitions(IParadoxCommunicator paradoxSystem) - throws IOException, InterruptedException, ParadoxException { - Map partitionLabels = paradoxSystem.getPartitionLabels(); - List partitions = new ArrayList<>(); - for (int i = 0; i < partitionLabels.size(); i++) { - Partition partition = new Partition(i + 1, partitionLabels.get(i)); - partitions.add(partition); - logger.debug("Partition {}:\t{}", i + 1, partition.getState().getMainState()); - } - return partitions; - } - - private static void readArguments(String[] args) { - if (args == null || args.length < 8 || !"--password".equals(args[0]) || args[1] == null || args[1].isEmpty() - || args[2] == null || !"--pc_password".equals(args[2]) || args[3] == null || args[3].isEmpty() - || !"--ip_address".equals(args[4]) || args[5] == null || args[5].isEmpty() || !"--port".equals(args[6]) - || args[7] == null || args[7].isEmpty()) { - logger.error( - "Usage: application --password --pc_password --ip_address

    --port \n (pc password default is 0000, can be obtained by checking section 3012), default port is 10000"); - System.exit(0); - } else { - logger.info("Arguments retrieved successfully from CLI."); - - ip150Password = args[1]; - logger.info("IP150 Password: {}", ip150Password); - - pcPassword = args[3]; - logger.info("PC Password: {}", pcPassword); - - ipAddress = args[5]; - logger.info("IP150 IP Address: {}", ipAddress); - - port = new Integer(args[7]); - logger.info("IP150 port: {}", port); - } - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package main; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.openhab.binding.paradoxalarm.internal.communication.ICommunicatorBuilder; +import org.openhab.binding.paradoxalarm.internal.communication.IParadoxCommunicator; +import org.openhab.binding.paradoxalarm.internal.communication.ParadoxBuilderFactory; +import org.openhab.binding.paradoxalarm.internal.exceptions.ParadoxException; +import org.openhab.binding.paradoxalarm.internal.model.PanelType; +import org.openhab.binding.paradoxalarm.internal.model.ParadoxPanel; +import org.openhab.binding.paradoxalarm.internal.model.Partition; +import org.openhab.binding.paradoxalarm.internal.model.Zone; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link Main} - used for testing purposes of low-level stuff. + * + * @author Konstantin Polihronov - Initial contribution + */ +public class Main { + + private static Logger logger = LoggerFactory.getLogger(Main.class); + + private static String ipAddress; + private static int port; + + // PASSWORD is your IP150 password + private static String ip150Password; + + // PC Password is the value of section 3012, i.e. if value is 0987, PC Password is two bytes 0x09, 0x87 + private static String pcPassword; + + private static ScheduledExecutorService scheduler; + + private static final String LOG_LEVEL = "DEBUG"; + + private static IParadoxCommunicator communicator; + + public static void main(String[] args) { + System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, LOG_LEVEL); + + readArguments(args); + + try { + scheduler = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors()); + + ParadoxBuilderFactory factory = new ParadoxBuilderFactory(); + ICommunicatorBuilder builder = factory.createBuilder(PanelType.EVO192); + communicator = builder.withIp150Password(ip150Password).withPcPassword(pcPassword).withIpAddress(ipAddress) + .withTcpPort(port).withMaxPartitions(4).withMaxZones(60).withScheduler(scheduler).build(); + + ParadoxPanel panel = ParadoxPanel.getInstance(); + panel.setCommunicator(communicator); + + communicator.setListeners(Arrays.asList(panel)); + + panel.setCommunicator(communicator); + + // scheduler.schedule(communicator::initializeEpromData, 2, TimeUnit.SECONDS); + // scheduler.schedule(communicator::refreshMemoryMap, 2, TimeUnit.SECONDS); + + scheduler.scheduleWithFixedDelay(() -> { + updateDataCache(communicator, false); + }, 7, 5, TimeUnit.SECONDS); + } catch (Exception e) { + logger.error("Exception: ", e); + System.exit(0); + } + } + + private static void updateDataCache(IParadoxCommunicator communicator, boolean withEpromValues) { + logger.debug("Refreshing memory map"); + communicator.refreshMemoryMap(); + } + + private static List initializeZones(IParadoxCommunicator paradoxSystem) + throws IOException, InterruptedException, ParadoxException { + Map zoneLabels = paradoxSystem.getZoneLabels(); + List zones = new ArrayList<>(); + for (int i = 0; i < 40; i++) { + Zone zone = new Zone(i + 1, zoneLabels.get(i)); + zones.add(zone); + } + return zones; + } + + private static List initializePartitions(IParadoxCommunicator paradoxSystem) + throws IOException, InterruptedException, ParadoxException { + Map partitionLabels = paradoxSystem.getPartitionLabels(); + List partitions = new ArrayList<>(); + for (int i = 0; i < partitionLabels.size(); i++) { + Partition partition = new Partition(i + 1, partitionLabels.get(i)); + partitions.add(partition); + logger.debug("Partition {}:\t{}", i + 1, partition.getState().getMainState()); + } + return partitions; + } + + private static void readArguments(String[] args) { + if (args == null || args.length < 8 || !"--password".equals(args[0]) || args[1] == null || args[1].isEmpty() + || args[2] == null || !"--pc_password".equals(args[2]) || args[3] == null || args[3].isEmpty() + || !"--ip_address".equals(args[4]) || args[5] == null || args[5].isEmpty() || !"--port".equals(args[6]) + || args[7] == null || args[7].isEmpty()) { + logger.error( + "Usage: application --password --pc_password --ip_address
    --port \n (pc password default is 0000, can be obtained by checking section 3012), default port is 10000"); + System.exit(0); + } else { + logger.info("Arguments retrieved successfully from CLI."); + + ip150Password = args[1]; + logger.info("IP150 Password: {}", ip150Password); + + pcPassword = args[3]; + logger.info("PC Password: {}", pcPassword); + + ipAddress = args[5]; + logger.info("IP150 IP Address: {}", ipAddress); + + port = new Integer(args[7]); + logger.info("IP150 port: {}", port); + } + } +} diff --git a/bundles/org.openhab.binding.pentair/pom.xml b/bundles/org.openhab.binding.pentair/pom.xml index 3b93daeb7613b..efe3c32439ee1 100644 --- a/bundles/org.openhab.binding.pentair/pom.xml +++ b/bundles/org.openhab.binding.pentair/pom.xml @@ -1,15 +1,21 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.pentair openHAB Add-ons :: Bundles :: Pentair Binding + + gnu.io;version="[3.12,6)" + + diff --git a/bundles/org.openhab.binding.pentair/src/main/feature/feature.xml b/bundles/org.openhab.binding.pentair/src/main/feature/feature.xml index 94a9ff71af590..e310d86ecc3ff 100644 --- a/bundles/org.openhab.binding.pentair/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.pentair/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.pentair/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.pentair/${project.version} + diff --git a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/binding/binding.xml index 0ead44bc8c49b..186badac8deaf 100644 --- a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Pentair Binding This is the binding for Pentair pool systems. diff --git a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/easytouch.xml b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/easytouch.xml index 5a801f483cfed..37db93dac7412 100644 --- a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/easytouch.xml +++ b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/easytouch.xml @@ -1,13 +1,13 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - - + + @@ -66,7 +66,7 @@ Number - Spa water temperature. Only valide when in spa mode. + Spa water temperature. Only valide when in spa mode. diff --git a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/intellichlor.xml b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/intellichlor.xml index 28b6e6cd7263f..a5f133af04b96 100644 --- a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/intellichlor.xml +++ b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/intellichlor.xml @@ -1,13 +1,13 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - - + + diff --git a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/intelliflo.xml b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/intelliflo.xml index bb774482bb40e..f8968beeb6eba 100644 --- a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/intelliflo.xml +++ b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/intelliflo.xml @@ -1,13 +1,13 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - - + + @@ -72,5 +72,5 @@ Pump Error - + diff --git a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/serial_bridge.xml b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/serial_bridge.xml index da17b66d803fd..40b04c7f553f7 100644 --- a/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/serial_bridge.xml +++ b/bundles/org.openhab.binding.pentair/src/main/resources/ESH-INF/thing/serial_bridge.xml @@ -1,7 +1,8 @@ - + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> diff --git a/bundles/org.openhab.binding.phc/README.md b/bundles/org.openhab.binding.phc/README.md index 2214361d4a8d6..2b21885034b28 100644 --- a/bundles/org.openhab.binding.phc/README.md +++ b/bundles/org.openhab.binding.phc/README.md @@ -1,25 +1,13 @@ ---- -layout: documentation ---- - -{% include base.html %} - # PHC Binding -This binding allows you to integrate modules(at the Moment AM, EM and JRM) of PHC, without the PHC control (STM), in openHAB. +This binding allows you to integrate modules(at the Moment AM, EM, JRM and DIM) of PHC, without the PHC control (STM), in openHAB. The serial protocol is mainly extracted, with thanks to the developers from the projects [PHCtoUDP](https://sourceforge.net/projects/phctoudp/) and [OpenHC](https://sourceforge.net/projects/openhc/?source=directory). -## Bridge - -The Bridge manages the communication between the things and the modules via a serial port (RS485). It represents the STM. -At the Moment you can only use one Bridge (like one STM). - -#### Configurations - -**Serial Port:** Type the serial port of the RS485 adaptor, e.g. COM3 (Windows) or /dev/ttyUSB0 (Linux). +The basics of the module bus protocol can also be found in the [Wiki of the PHC-Forum (german)](https://wiki.phc-forum.de/index.php/PHC-Protokoll_des_internen_Bus). +While the Wiki is offline you can find a PDF version [here](https://phc-forum.de/index.php/forum/phc-programmierung/129-phc-protokoll?start=15#1329). -#### Serial Communication +## Serial Communication The binding was tested with QinHeng Electronics HL-340 USB-Serial adapter (RS485) and the Digitus DA-70157 (FTDI/FT323RL) on Raspbian Ubilinux (Up Board) and Windows 10: @@ -31,18 +19,56 @@ The binding was tested with QinHeng Electronics HL-340 USB-Serial adapter (RS485 | | FTDI | doesn´t work | | | on board | bad | | Up Board/ubilinux(Jessie)| HL-340 | not reliable | -| | FTDI | ok | +| | FTDI | good | -Sometimes it is a bit slowly and you have to switch two times for reaction, but all in all it works ok. -I'm trying to get a faster solution for communication in the next few weeks. +If there are many modules on one bridge, the initialization can take a few minutes. If it does not work you can plug in the modules one after the other. +Sometimes after initialization, you might have to switch two times or the reaction could be a bit slow, but after you used a channel it should all work fine. For all devices running with Linux that use the ch341 driver (HL-340), the new version (ch34x) is needed. A guide how to install this can be found here: [CH340/341 UART Driver for Raspberry Pi](https://github.com/aperepel/raspberrypi-ch340-driver). If you don´t have the same kernel as used in the guide you have to compile the module yourself. In the guide is described a specific way for the Raspberry Pi. With another Linux version you can go the normal way with linux-headers. +According to the [Wiki of the PHC-Forum](https://wiki.phc-forum.de/index.php/PHC-Protokoll_des_internen_Bus#USB_RS-485_Adapter) the newer version of the FTDI adapter doesn't really work anymore either. + In Linux amongst others the user 'openhab' must be added to the group 'dialout': ```sudo usermod -a -G dialout openhab``` For more information read the [installation guide](https://www.openhab.org/docs/installation/linux.html#recommended-additional-setup-steps). +### Connection + +There are two alternatives, the first of which is much simpler. + +#### Connection via power supply (simpler, preferred) + +The simplest way would be to connect the RS485 adaptor to the PHC power supply like in the table below and Out at the power supply to the first module like the STM before. + +| adaptor | PHC power supply | +|----------|------------------| +| 485+ | +A | +| 485- | -B | + +#### Make a direct RJ12 connection + +Connect a RJ12 plug with the RS485 adaptor and the power supply as follows. + +| RJ12 like in picture below | The cores on the other side | +|----------------------------|-----------------------------| +| 0V | 0V on power supply | +| B- | 485- on adaptor | +| A+ | 485+ on adaptor | +| 24+ | +24V on power supply | + +![RJ12 Connector](doc/RJ12-Connector.png) + +## Bridge + +The Bridge manages the communication between the things and the modules via a serial port (RS485). +It represents the STM. +At the Moment you can only use one Bridge (like one STM). + +#### Configurations + +**Serial Port:** Type the serial port of the RS485 adaptor, e.g. COM3 (Windows) or /dev/ttyUSB0 (Linux). + ## Supported Things - **AM module:** This represents the AM module with 8 outgoing channels (relays). @@ -51,6 +77,8 @@ In Linux amongst others the user 'openhab' must be added to the group 'dialout': - **JRM module:** This represents the JRM module with 4 channels for Shutters. +- **DIM:** This represents the DM module with 2 dimmer channels. + ## Discovery Not implemented yet. @@ -58,7 +86,7 @@ Not implemented yet. ## Thing Configuration A thing accords with a module in the PHC software and the channels (with linked items) accord with the inputs and outputs. -Please note, if you define the things manually (not in the UI) that the ThingID always have to be the address. +Please note, if you define the things manually (not in the UI) that the ThingID always have to be the address (like the PID switches on the module). #### Parameters @@ -66,6 +94,8 @@ Please note, if you define the things manually (not in the UI) that the ThingID - **UpDownTime[1-4] (only JRM):** (advanced) The time in seconds that the shutter needs to move up or down. The default, if no value is specified, is 30 seconds. +- **DimTime[1-2] (only DIM):** (advanced) The time in seconds in that the dimmer should move 100%. The default is 2 seconds, then for example dimming from 0 to 100% takes 1 second. + ## Channels | Thing Type | Channel-Group Id | Channels | Item Type | @@ -75,6 +105,8 @@ Please note, if you define the things manually (not in the UI) that the ThingID | EM | emLed | 00-07 | Switch | | JRM | jrm | 00-03 | Rollershutter | | JRM | jrmT | 00-03 | Number | +| DIM | dim | 00-01 | Dimmer | +| DIM | dimT | 00-01 | Number | **Channel UID:** ```phc:::#``` e.g. ```phc:AM:01101:am#03``` @@ -82,7 +114,11 @@ Please note, if you define the things manually (not in the UI) that the ThingID - **em:** Incoming channels. - **emLed:** Outgoing switch channels e.g. for LEDs in light shutters. - **jrm:** Outgoing shutter channels. -- **jrmT:** Time for shutter channels in seconds with an accuracy of 1/10 seconds. These channels are used instead of the configuration parameters. If you send the time via this channel, the Binding uses this time till you send another. After reboot the config parameter is used by default. +- **jrmT:** Time for shutter channels in seconds with an accuracy of 1/10 seconds. +These channels are used instead of the configuration parameters. +If you send the time via this channel, the Binding uses this time till you send another. +After reboot the config parameter is used by default. +- **dim:** Outgoing dimmer channels. ## Full Example @@ -91,9 +127,10 @@ Please note, if you define the things manually (not in the UI) that the ThingID ``` Bridge phc:bridge:demo [port="/dev/ttyUSB0"]{ // The ThingID have to be the address. - Thing AM 10110 [address="01101"] + Thing AM 01101 [address="01101"] Thing EM 00110 [address="00110"] Thing JRM 10111 [address="10111", upDownTime3="60", upDownTime4="20"] + Thing DIM 00000 [address="00000"] ``` .items @@ -114,12 +151,16 @@ Rollershutter Shutter_4 {channel="phc:JRM:10111:jrm#03"} Number ShutterTime_1 {channel="phc:JRM:10111:jrmT#00"} +//DIM Module +Dimmer Dimmer_1 {channel="phc:DIM:00000:dim#00} +Dimmer Dimmer_2 {channel="phc:DIM:00000:dim#01} + // EM Module -Switch InputLed_1 {channel="phc:EM:00110:emLed#03"} +Switch InputLed_3 {channel="phc:EM:00110:emLed#03"} Switch Input_1 {channel="phc:EM:00110:em#00"} Switch Input_2 {channel="phc:EM:00110:em#01"} -Switch Input_3 {channel="phc:EM:00110:em#01"} +Switch Input_3 {channel="phc:EM:00110:em#02"} ... Switch Input_16 {channel="phc:EM:00110:em#15"} ``` diff --git a/bundles/org.openhab.binding.phc/doc/RJ12-Connector.png b/bundles/org.openhab.binding.phc/doc/RJ12-Connector.png new file mode 100644 index 0000000000000..4626f90bc288a Binary files /dev/null and b/bundles/org.openhab.binding.phc/doc/RJ12-Connector.png differ diff --git a/bundles/org.openhab.binding.phc/pom.xml b/bundles/org.openhab.binding.phc/pom.xml index 34b0307354077..6e4a03f77959d 100644 --- a/bundles/org.openhab.binding.phc/pom.xml +++ b/bundles/org.openhab.binding.phc/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.phc diff --git a/bundles/org.openhab.binding.phc/src/main/feature/feature.xml b/bundles/org.openhab.binding.phc/src/main/feature/feature.xml index eb6656f4501f0..c801b6f29f519 100644 --- a/bundles/org.openhab.binding.phc/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.phc/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.phc/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.phc/${project.version} + diff --git a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCBindingConstants.java b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCBindingConstants.java index cfcc249c45f31..9c48d9f21e6ee 100644 --- a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCBindingConstants.java +++ b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCBindingConstants.java @@ -12,14 +12,16 @@ */ package org.openhab.binding.phc.internal; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.ThingTypeUID; /** - * The {@link PHCBinding} class defines common constants, which are - * used across the whole binding. + * The {@link PHCBinding} class defines common constants, which are used across + * the whole binding. * * @author Jonas Hohaus - Initial contribution */ +@NonNullByDefault public class PHCBindingConstants { public static final String BINDING_ID = "phc"; @@ -30,6 +32,7 @@ public class PHCBindingConstants { public static final ThingTypeUID THING_TYPE_AM = new ThingTypeUID(BINDING_ID, "AM"); public static final ThingTypeUID THING_TYPE_EM = new ThingTypeUID(BINDING_ID, "EM"); public static final ThingTypeUID THING_TYPE_JRM = new ThingTypeUID(BINDING_ID, "JRM"); + public static final ThingTypeUID THING_TYPE_DIM = new ThingTypeUID(BINDING_ID, "DIM"); // List of all Channel Group IDs public static final String CHANNELS_AM = "am"; @@ -37,6 +40,7 @@ public class PHCBindingConstants { public static final String CHANNELS_EM_LED = "emLed"; public static final String CHANNELS_JRM = "jrm"; public static final String CHANNELS_JRM_TIME = "jrmT"; + public static final String CHANNELS_DIM = "dim"; // List of all configuration parameters public static final String PORT = "port"; @@ -45,4 +49,6 @@ public class PHCBindingConstants { public static final String UP_DOWN_TIME_2 = "upDownTime2"; public static final String UP_DOWN_TIME_3 = "upDownTime3"; public static final String UP_DOWN_TIME_4 = "upDownTime4"; + public static final String DIM_TIME_1 = "dimTime1"; + public static final String DIM_TIME_2 = "dimTime2"; } diff --git a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCHandlerFactory.java b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCHandlerFactory.java index 86a81dac9d86f..0528bcaedfc6c 100644 --- a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCHandlerFactory.java +++ b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCHandlerFactory.java @@ -19,6 +19,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; @@ -27,9 +29,11 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.phc.internal.handler.PHCBridgeHandler; import org.openhab.binding.phc.internal.handler.PHCHandler; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link PHCHandlerFactory} is responsible for creating things and thing @@ -37,11 +41,24 @@ * * @author Jonas Hohaus - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.phc") public class PHCHandlerFactory extends BaseThingHandlerFactory { - private static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( - Stream.of(THING_TYPE_BRIDGE, THING_TYPE_AM, THING_TYPE_EM, THING_TYPE_JRM).collect(Collectors.toSet())); + private static final Set SUPPORTED_THING_TYPES_UIDS = Collections + .unmodifiableSet(Stream.of(THING_TYPE_BRIDGE, THING_TYPE_AM, THING_TYPE_EM, THING_TYPE_JRM, THING_TYPE_DIM) + .collect(Collectors.toSet())); + + private @NonNullByDefault({}) SerialPortManager serialPortManager; + + @Reference + protected void setSerialPortManager(final SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + + protected void unsetSerialPortManager(final SerialPortManager serialPortManager) { + this.serialPortManager = null; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -49,15 +66,15 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, ThingUID thingUID, - ThingUID bridgeUID) { + public @Nullable Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, + @Nullable ThingUID thingUID, @Nullable ThingUID bridgeUID) { Thing thing; if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { if (thingTypeUID.equals(THING_TYPE_BRIDGE)) { thing = super.createThing(thingTypeUID, configuration, thingUID, null); } else { - ThingUID phcThingUID = new ThingUID(thingTypeUID, configuration.get(ADDRESS).toString().toUpperCase()); + ThingUID phcThingUID = new ThingUID(thingTypeUID, configuration.get(ADDRESS).toString()); thing = super.createThing(thingTypeUID, configuration, phcThingUID, bridgeUID); } } else { @@ -69,13 +86,13 @@ public Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration, } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); ThingHandler handler = null; if (thingTypeUID.equals(THING_TYPE_BRIDGE)) { - handler = new PHCBridgeHandler((Bridge) thing); + handler = new PHCBridgeHandler((Bridge) thing, serialPortManager); } else if (SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) { handler = new PHCHandler(thing); } diff --git a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCHelper.java b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCHelper.java index 2deaa2a608fa4..c320fa13216ed 100644 --- a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCHelper.java +++ b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/PHCHelper.java @@ -13,15 +13,17 @@ package org.openhab.binding.phc.internal; import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.ThingUID; /** - * The {@link PHCHelper} is responsible for finding the appropriate Thing(UID) to the Channel of the PHC module. + * The {@link PHCHelper} is responsible for finding the appropriate Thing(UID) + * to the Channel of the PHC module. * * @author Jonas Hohaus - Initial contribution */ - +@NonNullByDefault public class PHCHelper { /** @@ -47,17 +49,13 @@ public static ThingUID getThingUIDreverse(ThingTypeUID thingTypeUID, byte module * @param b * @return */ - public static Object byteToBinaryString(byte b) { - return StringUtils.leftPad(StringUtils.trim(Integer.toBinaryString(b & 0xFF)), 8, '0') + " "; - } - - /** - * Convert the byte b into an hex String - * - * @param b - * @return - */ - public static Object byteToHexString(byte b) { - return Integer.toHexString(b & 0xFF) + " "; + public static Object bytesToBinaryString(byte[] bytes) { + StringBuilder bin = new StringBuilder(); + for (byte b : bytes) { + bin.append(StringUtils.leftPad(StringUtils.trim(Integer.toBinaryString(b & 0xFF)), 8, '0')); + bin.append(' '); + } + + return bin.toString(); } } diff --git a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/InternalBuffer.java b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/InternalBuffer.java new file mode 100644 index 0000000000000..962492ae4ef66 --- /dev/null +++ b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/InternalBuffer.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.phc.internal.handler; + +import java.util.Arrays; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * Buffer for received messages + * + * @author Jonas Hohaus - Initial contribution + */ +class InternalBuffer { + private static final int MAX_SIZE = 512; + + private final BlockingQueue byteQueue = new LinkedBlockingQueue<>(); + private byte[] buffer; + private int bufferIndex = 0; + private int size; + + public void offer(byte[] buffer) { + // If the buffer becomes too large, already processed commands accumulate and + // the reaction becomes slow. + if (size < MAX_SIZE) { + byte[] localBuffer = Arrays.copyOf(buffer, Math.min(MAX_SIZE - size, buffer.length)); + byteQueue.offer(localBuffer); + synchronized (this) { + size += localBuffer.length; + } + } + } + + public boolean hasNext() { + return (size > 0); + } + + public byte get() throws InterruptedException { + byte[] buf = getBuffer(); + if (buf != null) { + byte result = buf[bufferIndex++]; + synchronized (this) { + size--; + } + + return result; + } + + throw new IllegalStateException("get without hasNext"); + } + + public int size() { + return size; + } + + private byte[] getBuffer() throws InterruptedException { + if (buffer == null || bufferIndex == buffer.length) { + buffer = byteQueue.take(); + bufferIndex = 0; + } + + return buffer; + } +} diff --git a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/PHCBridgeHandler.java b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/PHCBridgeHandler.java index 35068c1be073f..c34e6af03b6ca 100644 --- a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/PHCBridgeHandler.java +++ b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/PHCBridgeHandler.java @@ -16,20 +16,20 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TooManyListenersException; -import java.util.concurrent.ConcurrentNavigableMap; -import java.util.concurrent.ConcurrentSkipListMap; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ScheduledThreadPoolExecutor; -import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; import org.eclipse.smarthome.core.library.types.StopMoveType; -import org.eclipse.smarthome.core.library.types.UpDownType; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; @@ -38,64 +38,72 @@ import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.util.HexUtils; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.phc.internal.PHCBindingConstants; import org.openhab.binding.phc.internal.PHCHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.PortInUseException; -import gnu.io.RXTXPort; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * The {@link PHCBridgeHandler} is responsible for handling the serial Communication to and from the PHC Modules. * * @author Jonas Hohaus - Initial contribution */ - +@NonNullByDefault public class PHCBridgeHandler extends BaseBridgeHandler implements SerialPortEventListener { private final Logger logger = LoggerFactory.getLogger(PHCBridgeHandler.class); private static final int BAUD = 19200; - private static final int SEND_RETRY_COUNT = 15; // max count to send the same message - private static final int SEND_RETRY_TIME_MILLIS = 80; // time to wait for an acknowledge before send the message + private static final int SEND_RETRY_COUNT = 20; // max count to send the same message + private static final int SEND_RETRY_TIME_MILLIS = 60; // time to wait for an acknowledge before send the message // again in milliseconds - private InputStream serialIn; - private OutputStream serialOut; - short lastReceivedCrc; - byte[] messageFragment; - RXTXPort serialPort; + private @Nullable InputStream serialIn; + private @Nullable OutputStream serialOut; + private @Nullable SerialPort commPort; + private final SerialPortManager serialPortManager; - private final Map toggleMap = new HashMap<>(); - private final ConcurrentNavigableMap queue = new ConcurrentSkipListMap<>(); + private final Map toggleMap = new HashMap<>(); + private final InternalBuffer buffer = new InternalBuffer(); + private final BlockingQueue receiveQueue = new LinkedBlockingQueue<>(); + private final BlockingQueue sendQueue = new LinkedBlockingQueue<>(); + private final ScheduledThreadPoolExecutor threadPoolExecutor = new ScheduledThreadPoolExecutor(3); private final byte emLedOutputState[] = new byte[32]; private final byte amOutputState[] = new byte[32]; + private final byte dmOutputState[] = new byte[32]; private final List modules = new ArrayList<>(); - public PHCBridgeHandler(Bridge phcBridge) { + public PHCBridgeHandler(Bridge phcBridge, SerialPortManager serialPortManager) { super(phcBridge); + this.serialPortManager = serialPortManager; } @Override public void initialize() { String port = ((String) getConfig().get(PHCBindingConstants.PORT)); - try { - // find the given port - CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(port); + // find the given port + SerialPortIdentifier portId = serialPortManager.getIdentifier(port); + if (portId == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Serial port '" + port + "' could not be found."); + return; + } + + try { // initialize serial port - serialPort = portId.open(this.getClass().getName(), 2000); // owner, timeout + SerialPort serialPort = portId.open(this.getClass().getName(), 2000); // owner, timeout serialIn = serialPort.getInputStream(); // set port parameters serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_2, SerialPort.PARITY_NONE); @@ -104,210 +112,358 @@ public void initialize() { serialPort.addEventListener(this); // activate the DATA_AVAILABLE notifier serialPort.notifyOnDataAvailable(true); - serialPort.setRTS(true); // get the output stream serialOut = serialPort.getOutputStream(); - sendPorBroadcast((byte) 0xFF); + commPort = serialPort; + + sendPorBroadcast(); byte[] b = { 0x01 }; for (int j = 0; j <= 0x1F; j++) { serialWrite(buildMessage((byte) j, 0, b, false)); - } updateStatus(ThingStatus.ONLINE); - new Thread() { + // receive messages + threadPoolExecutor.execute(new Runnable() { @Override public void run() { - processQueueLoop(); + processReceivedBytes(); } + }); + + // process received messages + threadPoolExecutor.execute(new Runnable() { - }.start(); + @Override + public void run() { + processReceiveQueue(); + } + }); + + // sendig commands to the modules + threadPoolExecutor.execute(new Runnable() { + + @Override + public void run() { + processSendQueue(); + } + }); } catch (PortInUseException | TooManyListenersException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not open serial port " + serialPort + ": " + e.getMessage()); + "Could not open serial port " + port + ": " + e.getMessage()); } catch (UnsupportedCommOperationException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not configure serial port " + serialPort + ": " + e.getMessage()); - } catch (NoSuchPortException e) { - StringBuilder sb = new StringBuilder(); - @SuppressWarnings("unchecked") - Enumeration portList = CommPortIdentifier.getPortIdentifiers(); - while (portList.hasMoreElements()) { - CommPortIdentifier id = portList.nextElement(); - if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) { - sb.append(id.getName() + "\n"); - } - } - logger.warn("Serial port '{}' could not be found. Available ports are:\n {}", port, sb); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Serial port '" + port + "' could not be found."); + "Could not configure serial port " + port + ": " + e.getMessage()); + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Failed to get input or output stream for serialPort: " + e.getMessage()); + logger.debug("Failed to get inputstream for serialPort", e); } } /** - * Puts the available data on serial port into a buffer and transfer it to the processing method. + * Reads the data on serial port and puts it into the internal buffer. */ @Override public void serialEvent(SerialPortEvent event) { - if (event.getEventType() != SerialPortEvent.DATA_AVAILABLE) { - return; + if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE && serialIn != null) { + try { + byte[] bytes = new byte[serialIn.available()]; + serialIn.read(bytes); + + buffer.offer(bytes); + + if (logger.isTraceEnabled()) { + logger.trace("buffer offered {}", HexUtils.bytesToHex(bytes, " ")); + } + } catch (IOException e) { + logger.warn("Error on reading input stream to internal buffer", e); + } } + } - byte[] buffer; + /** + * process internal incoming buffer (recognize on read messages) + */ + private void processReceivedBytes() { + int faultCounter = 0; try { - if (serialIn.available() <= 0) { - return; - } + byte module = buffer.get(); + + while (true) { + // Recognition of messages from byte buffer. + // not a known module address + if (!modules.contains(module)) { + module = buffer.get(); + continue; + } + + if (logger.isDebugEnabled()) { + logger.debug("get module: {}", new String(HexUtils.byteToHex(module))); + } - Thread.sleep(5); - buffer = new byte[serialIn.available()]; - serialIn.read(buffer); + byte sizeToggle = buffer.get(); - if (messageFragment != null) { - processInputStream(ArrayUtils.addAll(messageFragment, buffer)); - } else { - processInputStream(buffer); + // read length of command and check if makes sense + if ((sizeToggle < 1 || sizeToggle > 3) && ((sizeToggle & 0xFF) < 0x81 || (sizeToggle & 0xFF) > 0x83)) { + if (logger.isDebugEnabled()) { + logger.debug("get invalid sizeToggle: {}", new String(HexUtils.byteToHex(sizeToggle))); + } + + module = sizeToggle; + continue; + } + + // read toggle, size and command + int size = (sizeToggle & 0x7F); + boolean toggle = (sizeToggle & 0x80) == 0x80; + + logger.debug("get toggle: {}", toggle); + + byte[] command = new byte[size]; + + for (int i = 0; i < size; i++) { + command[i] = buffer.get(); + } + + // log command + if (logger.isTraceEnabled()) { + logger.trace("command read: {}", PHCHelper.bytesToBinaryString(command)); + } + + // read crc + byte crcByte1 = buffer.get(); + byte crcByte2 = buffer.get(); + + short crc = (short) (crcByte1 & 0xFF); + crc |= (crcByte2 << 8); + + // calculate checkCrc + short checkCrc = calcCrc(module, sizeToggle, command); + + // check crc + if (crc != checkCrc) { + logger.debug("CRC not correct (crc from message, calculated crc): {}, {}", crc, checkCrc); + + faultCounter = handleCrcFault(faultCounter); + + module = buffer.get(); + continue; + } + + if (logger.isTraceEnabled()) { + logger.trace("get crc: {}", HexUtils.bytesToHex(new byte[] { crcByte1, crcByte2 }, " ")); + } + + faultCounter = 0; + + processReceivedMsg(module, toggle, command); + module = buffer.get(); } - } catch (IOException e) { - // ignore } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } - /** - * Split and process the given buffer to single messages. - * - * @param buffer - */ - private void processInputStream(byte[] buffer) { - List result = new ArrayList<>(); - List repeat = new ArrayList<>(); - int pos = 0; - messageFragment = null; - Byte moduleAddress = null; - - while (pos < buffer.length) { - int messageStart = 0; - - for (byte b : buffer) { - if (modules.contains(b)) { - moduleAddress = b; - messageStart = pos++; - break; + private int handleCrcFault(int faultCounter) throws InterruptedException { + if (faultCounter > 0) { + // Normally in this case we read the message repeatedly offset to the real -> skip one to 6 bytes + for (int i = 0; i < faultCounter; i++) { + if (buffer.hasNext()) { + buffer.get(); } - pos++; } + } + + int resCounter = faultCounter + 1; + if (resCounter > 6) { + resCounter = 0; + } + return resCounter; + } - if (moduleAddress == null) { - return; + private void processReceivedMsg(byte module, boolean toggle, byte[] command) { + // Acknowledgement received (command first byte 0) + if (command[0] == 0) { + String moduleType; + byte channel = 0; // only needed for dim + if ((module & 0xE0) == 0x40) { + moduleType = PHCBindingConstants.CHANNELS_AM; + } else if ((module & 0xE0) == 0xA0) { + moduleType = PHCBindingConstants.CHANNELS_DIM; + channel = (byte) ((command[0] >>> 5) & 0x0F); + } else { + moduleType = PHCBindingConstants.CHANNELS_EM_LED; } - if (buffer.length - 1 - pos < 3) { - messageFragment = new byte[buffer.length - pos + 1]; - System.arraycopy(buffer, messageStart, messageFragment, 0, messageFragment.length); + setModuleOutputState(moduleType, (byte) (module & 0x1F), command[1], channel); + toggleMap.put(module, !toggle); + + // initialization (first byte FF) + } else if (command[0] == (byte) 0xFF) { + if ((module & 0xE0) == 0x00) { // EM + sendEmConfig(module); + } else if ((module & 0xE0) == 0x40 || (module & 0xE0) == 0xA0) { // AM, JRM and DIM + sendAmConfig(module); } - byte size = 0; - result.add(buffer[pos]); - size = (byte) (buffer[pos] & 0x7F); + logger.debug("initialization: {}", module); - if (size > 0 && size < 4) { - if (buffer.length - 1 - pos < size + 2) { - messageFragment = new byte[buffer.length - pos + 1]; - System.arraycopy(buffer, messageStart, messageFragment, 0, messageFragment.length); - } + // ignored - ping (first byte 01) + } else if (command[0] == 0x01) { + logger.debug("first byte 0x01 -> ignored"); + + // EM command / update + } else { + if (((module & 0xE0) == 0x00)) { + sendEmAcknowledge(module, toggle); + logger.debug("send acknowledge (modul, toggle) {} {}", module, toggle); - byte[] message = new byte[size + 4]; - message[0] = moduleAddress; - message[1] = buffer[pos++]; + byte channel = (byte) ((command[0] >>> 4) & 0x0F); - for (int i = 2; i < size + 4; i++) { - message[i] = buffer[pos++]; - result.add(message[i]); + OnOffType onOff = OnOffType.OFF; + + if ((command[0] & 0x0F) == 2) { + onOff = OnOffType.ON; } - if (!repeat.contains(Arrays.toString(message))) { // avoids multiple processing of the same message - processIncomingMessage(message, size); - repeat.add(Arrays.toString(message)); + QueueObject qo = new QueueObject(PHCBindingConstants.CHANNELS_EM, module, channel, onOff); + + // put recognized message into queue + if (!receiveQueue.contains(qo)) { + receiveQueue.offer(qo); } + + // ignore if message not from EM module + } else if (logger.isDebugEnabled()) { + logger.debug("Incoming message (module, toggle, command) not from EM module: {} {} {}", + new String(HexUtils.byteToHex(module)), toggle, PHCHelper.bytesToBinaryString(command)); } } } - private void processQueueLoop() { + /** + * process receive queue + */ + private void processReceiveQueue() { while (true) { - long limit = System.currentTimeMillis(); - - Map subQueue = queue.subMap(0L, true, limit, true); - - for (Long key : subQueue.keySet()) { - QueueObject qo = subQueue.get(key); - queue.remove(key); - if (qo.getCounter() < SEND_RETRY_COUNT && !qo.getCommand() - .equals(isChannelOutputStateSet(qo.getModuleType(), qo.getModuleAddress(), qo.getChannel()))) { - qo.increaseCounter(); - - switch (qo.getModuleType()) { - case PHCBindingConstants.CHANNELS_AM: - sendAm(qo.getModuleAddress(), qo.getChannel(), qo.getCommand()); - break; - case PHCBindingConstants.CHANNELS_EM_LED: - sendEm(qo.getModuleAddress(), qo.getChannel(), qo.getCommand()); - break; - case PHCBindingConstants.CHANNELS_JRM: - sendJRM(qo.getModuleAddress(), qo.getChannel(), qo.getCommand(), qo.getUpDownTime()); - break; - } + try { + QueueObject qo = receiveQueue.take(); - queue.put(System.currentTimeMillis() + SEND_RETRY_TIME_MILLIS, qo); - } else if (qo.getCounter() >= SEND_RETRY_COUNT - && !qo.getModuleType().equals(PHCBindingConstants.CHANNELS_JRM)) { - // Can´t process the acknowledgement of JRM yet. - logger.info("No acknowlgdge from the module {} received.", qo.getModuleAddress()); - } + logger.debug("Consume Receive QueueObject: {}", qo); + handleIncomingCommand(qo.getModuleAddress(), qo.getChannel(), (OnOffType) qo.getCommand()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); } } } - private void setModuleOutputState(String moduleType, byte moduleAddress, byte state) { - if (moduleType == PHCBindingConstants.CHANNELS_EM_LED) { - emLedOutputState[moduleAddress] = state; - } else if (moduleType == PHCBindingConstants.CHANNELS_AM) { - amOutputState[moduleAddress & 0x1F] = state; - } else if (moduleType == PHCBindingConstants.CHANNELS_JRM) { - // not implemented yet + /** + * process send queue + */ + private void processSendQueue() { + while (true) { + try { + QueueObject qo = sendQueue.take(); + + sendQueueObject(qo); + } catch (InterruptedException e1) { + Thread.currentThread().interrupt(); + } } } - private State isChannelOutputStateSet(String moduleType, byte moduleAddress, byte channel) { - State set = null; + private void sendQueueObject(QueueObject qo) { + int sendCount = 0; + // Send the command to the module until a response is received. Max. SEND_RETRY_COUNT repeats. + do { + switch (qo.getModuleType()) { + case PHCBindingConstants.CHANNELS_AM: + sendAm(qo.getModuleAddress(), qo.getChannel(), qo.getCommand()); + break; + case PHCBindingConstants.CHANNELS_EM_LED: + sendEm(qo.getModuleAddress(), qo.getChannel(), qo.getCommand()); + break; + case PHCBindingConstants.CHANNELS_JRM: + sendJrm(qo.getModuleAddress(), qo.getChannel(), qo.getCommand(), qo.getTime()); + break; + case PHCBindingConstants.CHANNELS_DIM: + sendDim(qo.getModuleAddress(), qo.getChannel(), qo.getCommand(), qo.getTime()); + break; + } + + sendCount++; + try { + Thread.sleep(SEND_RETRY_TIME_MILLIS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } while (!isChannelOutputState(qo.getModuleType(), qo.getModuleAddress(), qo.getChannel(), qo.getCommand()) + && sendCount < SEND_RETRY_COUNT); + + if (PHCBindingConstants.CHANNELS_JRM.equals(qo.getModuleType())) { + // there aren't state per channel for JRM modules + amOutputState[qo.getModuleAddress() & 0x1F] = -1; + } else if (PHCBindingConstants.CHANNELS_DIM.equals(qo.getModuleType())) { + // state ist the same for every dim level except zero/off -> inizialize state + // with 0x0F after sending an command. + dmOutputState[qo.getModuleAddress() & 0x1F] |= (0x0F << (qo.getChannel() * 4)); + } + + if (sendCount >= SEND_RETRY_COUNT) { + // change the toggle: if no acknowledge received it may be wrong. + byte module = qo.getModuleAddress(); + if (PHCBindingConstants.CHANNELS_AM.equals(qo.getModuleType()) + || PHCBindingConstants.CHANNELS_JRM.equals(qo.getModuleType())) { + module |= 0x40; + } else if (PHCBindingConstants.CHANNELS_DIM.equals(qo.getModuleType())) { + module |= 0xA0; + } + toggleMap.put(module, !getToggle(module)); - if (moduleType.equals(PHCBindingConstants.CHANNELS_EM_LED)) { - set = ((emLedOutputState[moduleAddress] >> channel) & 0x01) == 1 ? OnOffType.ON : OnOffType.OFF; - } else if (moduleType.equals(PHCBindingConstants.CHANNELS_AM)) { - set = ((amOutputState[moduleAddress & 0x1F] >> channel) & 0x01) == 1 ? OnOffType.ON : OnOffType.OFF; - } else if (moduleType.equals(PHCBindingConstants.CHANNELS_JRM)) { - set = ((amOutputState[moduleAddress & 0x1F] >> channel) & 0x01) == 1 ? OnOffType.ON : OnOffType.OFF; + if (logger.isDebugEnabled()) { + logger.debug("No acknowledge from the module {} received.", qo.getModuleAddress()); + } } + } - return set; + private void setModuleOutputState(String moduleType, byte moduleAddress, byte state, byte channel) { + if (PHCBindingConstants.CHANNELS_EM_LED.equals(moduleType)) { + emLedOutputState[moduleAddress] = state; + } else if (PHCBindingConstants.CHANNELS_AM.equals(moduleType)) { + amOutputState[moduleAddress & 0x1F] = state; + } else if (PHCBindingConstants.CHANNELS_DIM.equals(moduleType)) { + dmOutputState[moduleAddress & 0x1F] = (byte) (state << channel * 4); + } + } + + private boolean isChannelOutputState(String moduleType, byte moduleAddress, byte channel, Command cmd) { + int state = OnOffType.OFF.equals(cmd) ? 0 : 1; + + if (PHCBindingConstants.CHANNELS_EM_LED.equals(moduleType)) { + return ((emLedOutputState[moduleAddress & 0x1F] >>> channel) & 0x01) == state; + } else if (PHCBindingConstants.CHANNELS_AM.equals(moduleType)) { + return ((amOutputState[moduleAddress & 0x1F] >>> channel) & 0x01) == state; + } else if (PHCBindingConstants.CHANNELS_JRM.equals(moduleType)) { + return (amOutputState[moduleAddress & 0x1F] != -1); + } else if (PHCBindingConstants.CHANNELS_DIM.equals(moduleType)) { + return ((dmOutputState[moduleAddress & 0x1F] >>> channel * 4) & 0x0F) != 0x0F; + } else { + return false; + } } - private boolean toggleChannel(byte moduleAddress, byte channel) { - String key = new String(new byte[] { moduleAddress, channel }); - boolean toggle = false; - if (toggleMap.containsKey(key)) { - toggle = toggleMap.get(key); + private boolean getToggle(byte moduleAddress) { + if (!toggleMap.containsKey(moduleAddress)) { + toggleMap.put(moduleAddress, false); } - toggleMap.put(key, !toggle); - return toggle; + return toggleMap.get(moduleAddress); } /** @@ -319,46 +475,49 @@ private boolean toggleChannel(byte moduleAddress, byte channel) { * @param command * @param upDownTime */ - public void send(String moduleType, String moduleAddress, String channel, Command command, short upDownTime) { - if (command instanceof OnOffType || command instanceof UpDownType || command.equals(StopMoveType.STOP)) { - if (moduleType.equals(PHCBindingConstants.CHANNELS_JRM)) { // can´t process acknowledge yet - queue.put(System.currentTimeMillis(), - new QueueObject(moduleType, moduleAddress, channel, command, 9, upDownTime)); - } else { - queue.put(System.currentTimeMillis(), new QueueObject(moduleType, moduleAddress, channel, command)); - } + public void send(@Nullable String moduleType, int moduleAddress, String channel, Command command, + short upDownTime) { + if (PHCBindingConstants.CHANNELS_JRM.equals(moduleType) + || PHCBindingConstants.CHANNELS_DIM.equals(moduleType)) { + sendQueue.offer(new QueueObject(moduleType, moduleAddress, channel, command, upDownTime)); + } else { + sendQueue.offer(new QueueObject(moduleType, moduleAddress, channel, command)); } } private void sendAm(byte moduleAddress, byte channel, Command command) { - moduleAddress |= 0x40; + byte module = (byte) (moduleAddress | 0x40); + byte[] cmd = { (byte) (channel << 5) }; - if (command.equals(OnOffType.ON)) { + if (OnOffType.ON.equals(command)) { cmd[0] |= 2; } else { cmd[0] |= 3; } - serialWrite(buildMessage(moduleAddress, channel, cmd, toggleChannel(moduleAddress, channel))); + serialWrite(buildMessage(module, channel, cmd, getToggle(module))); } private void sendEm(byte moduleAddress, byte channel, Command command) { byte[] cmd = { (byte) (channel << 4) }; - if (command.equals(OnOffType.ON)) { + if (OnOffType.ON.equals(command)) { cmd[0] |= 2; } else { cmd[0] |= 3; } - serialWrite(buildMessage(moduleAddress, channel, cmd, toggleChannel(moduleAddress, channel))); + serialWrite(buildMessage(moduleAddress, channel, cmd, getToggle(moduleAddress))); } - private void sendJRM(byte moduleAddress, byte channel, Command command, short upDownTime) { + private void sendJrm(byte moduleAddress, byte channel, Command command, short upDownTime) { // The up and the down message needs two additional bytes for the time. int size = (command == StopMoveType.STOP) ? 2 : 4; byte[] cmd = new byte[size]; + if (channel == 0) { + channel = 4; + } - moduleAddress |= 0x40; + byte module = (byte) (moduleAddress | 0x40); cmd[0] = (byte) (channel << 5); cmd[1] = 0x3F; @@ -379,12 +538,39 @@ private void sendJRM(byte moduleAddress, byte channel, Command command, short up break; } - serialWrite(buildMessage(moduleAddress, channel, cmd, toggleChannel(moduleAddress, channel))); + serialWrite(buildMessage(module, channel, cmd, getToggle(module))); } - private void sendPorBroadcast(byte b) { - byte[] cmd = { 0 }; - writeMsg(buildMessage((byte) 0xFF, 0, cmd, false), 20); // 20 times needed? + private void sendDim(byte moduleAddress, byte channel, Command command, short dimTime) { + byte module = (byte) (moduleAddress | 0xA0); + byte[] cmd = new byte[(command instanceof PercentType && !(((PercentType) command).byteValue() == 0)) ? 3 : 1]; + + cmd[0] = (byte) (channel << 5); + + if (command instanceof OnOffType) { + if (OnOffType.ON.equals(command)) { + cmd[0] |= 3; + } else if (OnOffType.OFF.equals(command)) { + cmd[0] |= 4; + } + } else { + if (((PercentType) command).byteValue() == 0) { + cmd[0] |= 4; + } else { + cmd[0] |= 22; + cmd[1] = (byte) (((PercentType) command).byteValue() * 2.55); + cmd[2] = (byte) dimTime; + } + } + serialWrite(buildMessage(module, channel, cmd, getToggle(module))); + } + + private void sendPorBroadcast() { + byte[] msg = buildMessage((byte) 0xFF, 0, new byte[] { 0 }, false); + for (int i = 0; i < 20; i++) { + serialWrite(msg); + + } } private void sendAmConfig(byte moduleAddress) { @@ -417,8 +603,11 @@ private void sendEmConfig(byte moduleAddress) { } private void sendEmAcknowledge(byte module, boolean toggle) { - byte[] cmd = { 0 }; - writeMsg(buildMessage(module, 0, cmd, toggle), 2); // 2 times needed? + byte[] msg = buildMessage(module, 0, new byte[] { 0 }, toggle); + for (int i = 0; i < 3; i++) { // send three times stops the module faster from sending messages if the first + // response is not recognized. + serialWrite(msg); + } } /** @@ -437,16 +626,9 @@ private byte[] buildMessage(byte modulAddr, int channel, byte[] cmd, boolean tog buffer[0] = modulAddr; buffer[1] = (byte) (toggle ? (len | 0x80) : len); // 0x80: 1000 0000 - for (int i = 0; i < len; i++) { - buffer[2 + i] = cmd[i]; - } - - short crc = (short) 0xFFFF; + System.arraycopy(cmd, 0, buffer, 2, len); - for (int i = 0; i < (2 + len); i++) { - crc = crc16Update(crc, buffer[i]); - } - crc ^= 0xFFFF; + short crc = calcCrc(modulAddr, buffer[1], cmd); buffer[2 + len] = (byte) (crc & 0xFF); buffer[3 + len] = (byte) ((crc >> 8) & 0xFF); @@ -455,97 +637,41 @@ private byte[] buildMessage(byte modulAddr, int channel, byte[] cmd, boolean tog } /** - * Calculate/update the 16 bit crc of the message. + * Calculate the 16 bit crc of the message. * - * @param crc - * @param data + * @param module + * @param sizeToggle + * @param cmd * @return */ - private short crc16Update(short crc, byte data) { - data ^= crc & 0xFF; - data ^= data << 4; - short data16 = data; + private short calcCrc(byte module, byte sizeToggle, byte[] cmd) { + short crc = (short) 0xFFFF; - crc = (short) (((data16 << 8) | (((crc >> 8) & 0xFF) & 0xFF)) ^ ((data >> 4) & 0xF) - ^ ((data16 << 3) & 0b11111111111)); + crc = crc16Update(crc, module); + crc = crc16Update(crc, sizeToggle); + + for (byte b : cmd) { + crc = crc16Update(crc, b); + } + + crc ^= 0xFFFF; return crc; } /** - * Process the incoming message and start the reaction. + * Update the 16 bit crc of the message. * - * @param inByte - * @param size + * @param crc + * @param data + * @return */ - private void processIncomingMessage(byte[] inByte, int size) { - short calcCrc = (short) 0xFFFF; - short rcvCrc = (short) (inByte[2 + size] & 0xFF); - rcvCrc |= (inByte[size + 3] << 8); - boolean toggleIn = false; - - if ((inByte[1] & 0x80) == 0x80) { - toggleIn = true; - } - - for (int i = 0; i < (size + 2); i++) { - calcCrc = crc16Update(calcCrc, inByte[i]); - } - calcCrc ^= 0xFFFF; - - if (rcvCrc != calcCrc) { - return; - } - - byte moduleAddress = inByte[0]; - - byte[] cmd = new byte[size]; - for (int i = 0; i < cmd.length; i++) { - cmd[i] = inByte[2 + i]; - } - - int[] channel = new int[size]; - for (int i = 0; i < cmd.length; i++) { - channel[i] = (inByte[2 + i] >> 4) & 0xF; - } - - if ((moduleAddress & 0xE0) != 0xE0) { - if (cmd[0] == 0) { - if ((((moduleAddress & 0xE0) == 0x40) || ((moduleAddress & 0xE0) == 0x00)) && (cmd.length == 2)) { - String moduleType = ((moduleAddress & 0xE0) == 0x40) ? PHCBindingConstants.CHANNELS_AM - : PHCBindingConstants.CHANNELS_EM_LED; - setModuleOutputState(moduleType, moduleAddress, cmd[1]); - } - } else if (cmd[0] == (byte) 0xFF) { - if ((moduleAddress & 0xE0) == 0x00) { // EM - sendEmConfig(moduleAddress); - } - if ((moduleAddress & 0xE0) == 0x40) { // AM and JRM - sendAmConfig(moduleAddress); - } - - } else if (cmd[0] != 0x01) { // I'm not sure what the command 0x01 means. It isn't relevant for normal - // functionality. - if ((moduleAddress & 0xE0) == 0) { - if (rcvCrc == lastReceivedCrc) { - sendEmAcknowledge(moduleAddress, toggleIn); // Just send the acknowledge message again, when - // PHC didn't recognize it. - } else { - sendEmAcknowledge(moduleAddress, toggleIn); - handleIncomingCommand(moduleAddress, channel[0], cmd); - - } - } - } - } + private short crc16Update(short crc, byte messagePart) { + byte data = (byte) (messagePart ^ (crc & 0xFF)); + data ^= data << 4; + short data16 = data; - if (logger.isDebugEnabled()) { - StringBuilder logMessage = new StringBuilder(); - for (int i = 0; i < inByte.length; i++) { - logMessage.append(PHCHelper.byteToBinaryString(inByte[i])); - } - logMessage.append(", " + inByte.length); - logger.debug("received: {}", logMessage); - } + return (short) (((data16 << 8) | (((crc >> 8) & 0xFF) & 0xFF)) ^ ((data >> 4) & 0xF) + ^ ((data16 << 3) & 0b11111111111)); } /** @@ -556,55 +682,40 @@ private void processIncomingMessage(byte[] inByte, int size) { * @param cmd * @param rcvCrc */ - private void handleIncomingCommand(byte moduleAddress, int channel, byte[] cmd) { + private void handleIncomingCommand(byte moduleAddress, int channel, OnOffType onOff) { ThingUID uid = PHCHelper.getThingUIDreverse(PHCBindingConstants.THING_TYPE_EM, moduleAddress); - Thing thing = getThingByUID(uid); + Thing thing = getThing().getThing(uid); String channelId = "em#" + StringUtils.leftPad(Integer.toString(channel), 2, '0'); - if (thing != null) { - OnOffType state = OnOffType.OFF; - if ((cmd[0] & 0x0F) == 2) { - state = OnOffType.ON; - } + if (thing != null && thing.getHandler() != null) { + logger.debug("Input: {}, {}, {}", thing.getUID(), channelId, onOff); - logger.debug("{}, {}", thing.getUID(), state); - ((PHCHandler) thing.getHandler()).handleIncoming(channelId, state); + PHCHandler handler = (PHCHandler) thing.getHandler(); + if (handler != null) { + handler.handleIncoming(channelId, onOff); + } else { + logger.debug("No Handler for Thing {} available.", thing.getUID()); + } } else { - logger.info("No Thing with UID {} available.", uid.getAsString()); - } - } - - /** - * Send message to to serial port x times. - * - * @param msg - * @param sendCnt - */ - private void writeMsg(byte[] msg, int sendCnt) { - while (0 < sendCnt) { - serialWrite(msg); - sendCnt--; + logger.debug("No Thing with UID {} available.", uid.getAsString()); } } private void serialWrite(byte[] msg) { - try { - // write to serial port - serialOut.write(msg); - serialOut.flush(); - } catch (IOException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Error writing '" + msg + "' to serial port : " + e.getMessage()); - } + if (serialOut != null) { + try { + // write to serial port + serialOut.write(msg); + serialOut.flush(); + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Error writing '" + msg + "' to serial port : " + e.getMessage()); + } - if (logger.isDebugEnabled()) { - StringBuilder log = new StringBuilder(); - for (byte b : msg) { - log.append(PHCHelper.byteToBinaryString(b)); - log.append(' '); + if (logger.isTraceEnabled()) { + logger.trace("send: {}", PHCHelper.bytesToBinaryString(msg)); } - logger.debug("send: {}", log); } } @@ -621,4 +732,13 @@ public void addModule(byte module) { public void handleCommand(ChannelUID channelUID, Command command) { // unnecessary } + + @Override + public void dispose() { + threadPoolExecutor.shutdownNow(); + if (commPort != null) { + commPort.close(); + commPort = null; + } + } } diff --git a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/PHCHandler.java b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/PHCHandler.java index 9f80f00d6a7e0..adadb484d00b7 100644 --- a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/PHCHandler.java +++ b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/PHCHandler.java @@ -12,6 +12,8 @@ */ package org.openhab.binding.phc.internal.handler; +import static org.openhab.binding.phc.internal.PHCBindingConstants.*; + import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; @@ -20,6 +22,7 @@ import org.eclipse.smarthome.config.core.Configuration; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.PercentType; import org.eclipse.smarthome.core.library.types.StopMoveType; import org.eclipse.smarthome.core.library.types.UpDownType; import org.eclipse.smarthome.core.thing.Bridge; @@ -31,7 +34,6 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.State; -import org.openhab.binding.phc.internal.PHCBindingConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,7 +49,8 @@ public class PHCHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(PHCHandler.class); private String moduleAddress; // like DIP switches - private final short[] upDownTimes = new short[4]; + private byte module; + private final short[] times = new short[4]; private final Map channelState = new HashMap<>(); private PHCBridgeHandler bridgeHandler; @@ -57,27 +60,30 @@ public PHCHandler(Thing thing) { @Override public void initialize() { - moduleAddress = (String) getConfig().get(PHCBindingConstants.ADDRESS); + moduleAddress = (String) getConfig().get(ADDRESS); if (getPHCBridgeHandler() == null) { return; } - getPHCBridgeHandler() - .addModule(Byte.parseByte(getThing().getThingTypeUID().equals(PHCBindingConstants.THING_TYPE_EM) - ? new StringBuilder(moduleAddress).reverse().toString() - : ("010" + new StringBuilder(moduleAddress).reverse().toString()), 2)); // 010x = 0x4x for - // AM and JRM - - if (getThing().getThingTypeUID().equals(PHCBindingConstants.THING_TYPE_JRM)) { - upDownTimes[0] = (short) (((BigDecimal) getConfig().get(PHCBindingConstants.UP_DOWN_TIME_1)).shortValue() - * 10); - upDownTimes[1] = (short) (((BigDecimal) getConfig().get(PHCBindingConstants.UP_DOWN_TIME_2)).shortValue() - * 10); - upDownTimes[2] = (short) (((BigDecimal) getConfig().get(PHCBindingConstants.UP_DOWN_TIME_3)).shortValue() - * 10); - upDownTimes[3] = (short) (((BigDecimal) getConfig().get(PHCBindingConstants.UP_DOWN_TIME_4)).shortValue() - * 10); + module = Byte.parseByte(new StringBuilder(moduleAddress).reverse().toString(), 2); + + if (getThing().getThingTypeUID().equals(THING_TYPE_AM) || getThing().getThingTypeUID().equals(THING_TYPE_JRM)) { + module |= 0x40; + } else if (getThing().getThingTypeUID().equals(THING_TYPE_DIM)) { + module |= 0xA0; + } + getPHCBridgeHandler().addModule(module); + + if (getThing().getThingTypeUID().equals(THING_TYPE_JRM)) { + times[0] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_1)).shortValue() * 10); + times[1] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_2)).shortValue() * 10); + times[2] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_3)).shortValue() * 10); + times[3] = (short) (((BigDecimal) getConfig().get(UP_DOWN_TIME_4)).shortValue() * 10); + + } else if (getThing().getThingTypeUID().equals(THING_TYPE_DIM)) { + times[0] = (((BigDecimal) getConfig().get(DIM_TIME_1)).shortValue()); + times[1] = (((BigDecimal) getConfig().get(DIM_TIME_2)).shortValue()); } Bridge bridge = getBridge(); @@ -89,35 +95,40 @@ public void initialize() { } public void handleIncoming(String channelId, OnOffType state) { + if (logger.isDebugEnabled()) { + logger.debug("EM command: {}, last: {}, in: {}", channelId, channelState.get(channelId), state); + } + if (!channelState.containsKey(channelId) || !channelState.get(channelId).equals(state)) { postCommand(channelId, state); channelState.put(channelId, state); } - logger.debug("EM command: {}, last: {}, in: {}", channelId, channelState.get(channelId), state); } @Override public void handleCommand(ChannelUID channelUID, Command command) { - if ((PHCBindingConstants.CHANNELS_AM.equals(channelUID.getGroupId())) || PHCBindingConstants.CHANNELS_JRM - .equals(channelUID.getGroupId()) - && (command instanceof OnOffType || command instanceof UpDownType || command instanceof StopMoveType)) { - if (getThing().getStatus().equals(ThingStatus.ONLINE)) { - getPHCBridgeHandler().send(channelUID.getGroupId(), - new StringBuilder(moduleAddress).reverse().toString(), channelUID.getIdWithoutGroup(), command, - PHCBindingConstants.CHANNELS_JRM.equals(channelUID.getGroupId()) - ? upDownTimes[Integer.parseInt(channelUID.getIdWithoutGroup())] - : 0); - logger.debug("send command: {}, {}", channelUID, command); - } else { - logger.info("The Thing {} is offline it requires to select a Bridge", getThing().getUID()); + final String groupId = channelUID.getGroupId(); + if (getThing().getStatus().equals(ThingStatus.ONLINE)) { + if ((CHANNELS_JRM.equals(groupId) && (command instanceof UpDownType || command instanceof StopMoveType)) + || (CHANNELS_DIM.equals(groupId) + && (command instanceof OnOffType || command instanceof PercentType))) { + getPHCBridgeHandler().send(groupId, module & 0x1F, channelUID.getIdWithoutGroup(), command, + times[Integer.parseInt(channelUID.getIdWithoutGroup())]); + } else if ((CHANNELS_AM.equals(groupId) || CHANNELS_EM_LED.equals(groupId)) + && command instanceof OnOffType) { + getPHCBridgeHandler().send(groupId, module & 0x1F, channelUID.getIdWithoutGroup(), command, (short) 0); } + + logger.debug("send command: {}, {}", channelUID, command); + } else { + logger.info("The Thing {} is offline.", getThing().getUID()); } } @Override public void handleUpdate(ChannelUID channelUID, State newState) { - if (PHCBindingConstants.CHANNELS_JRM_TIME.equals(channelUID.getGroupId())) { - upDownTimes[Integer + if (CHANNELS_JRM_TIME.equals(channelUID.getGroupId())) { + times[Integer .parseInt(channelUID.getIdWithoutGroup())] = (short) (((DecimalType) newState).floatValue() * 10); } } @@ -129,7 +140,7 @@ public void handleConfigurationUpdate(Map configurationParameter Configuration configuration = editConfiguration(); for (Entry configurationParmeter : configurationParameters.entrySet()) { - if (!configurationParmeter.getKey().equals(PHCBindingConstants.ADDRESS)) { + if (!configurationParmeter.getKey().equals(ADDRESS)) { configuration.put(configurationParmeter.getKey(), configurationParmeter.getValue()); } else { configuration.put(configurationParmeter.getKey(), moduleAddress); @@ -159,6 +170,10 @@ private PHCBridgeHandler getPHCBridgeHandler() { bridgeHandler = (PHCBridgeHandler) handler; } else { logger.debug("No available bridge handler for {}.", bridge.getUID()); + + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_MISSING_ERROR, + "No available bridge handler."); + return null; } } diff --git a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/QueueObject.java b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/QueueObject.java index 0ac16a75edc16..50ee754d11cf4 100644 --- a/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/QueueObject.java +++ b/bundles/org.openhab.binding.phc/src/main/java/org/openhab/binding/phc/internal/handler/QueueObject.java @@ -25,24 +25,25 @@ class QueueObject { private final byte channel; private final Command command; - private int counter; - private short upDownTime; + private short time; - public QueueObject(String moduleType, String moduleAddress, String channel, Command command) { + public QueueObject(String moduleType, byte moduleAddress, byte channel, Command command) { this.moduleType = moduleType; - this.moduleAddress = Byte.parseByte(moduleAddress, 2); - this.channel = Byte.parseByte(channel); + this.moduleAddress = moduleAddress; + this.channel = channel; this.command = command; } - public QueueObject(String moduleType, String moduleAddress, String channel, Command command, int counter, - short upDownTime) { + public QueueObject(String moduleType, int moduleAddress, String channel, Command command) { this.moduleType = moduleType; - this.moduleAddress = Byte.parseByte(moduleAddress, 2); + this.moduleAddress = (byte) moduleAddress; this.channel = Byte.parseByte(channel); this.command = command; - this.counter = counter; - this.upDownTime = upDownTime; + } + + public QueueObject(String moduleType, int moduleAddress, String channel, Command command, short time) { + this(moduleType, moduleAddress, channel, command); + this.time = time; } public String getModuleType() { @@ -61,15 +62,20 @@ public Command getCommand() { return command; } - public void increaseCounter() { - counter++; + public short getTime() { + return time; } - public int getCounter() { - return counter; - } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("moduleType: "); + sb.append(moduleType); + sb.append(", moduleAddress: "); + sb.append(moduleAddress); + sb.append(", channel: "); + sb.append(channel); - public short getUpDownTime() { - return upDownTime; + return sb.toString(); } } diff --git a/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/binding/binding.xml index 8af693fb72b86..947c51567a097 100644 --- a/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/binding/binding.xml @@ -1,9 +1,10 @@ - - + PHC Binding - This is a binding for PHC modules (EM, AM and JRM). It communicates with the PHC Modulbus (RS485). + This is a binding for PHC modules (EM, AM, JRM and DIM). It communicates with the PHC Modulbus (RS485). Jonas Hohaus diff --git a/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/thing/channel-types.xml index ec0a247bc1a04..a5d66e1995124 100644 --- a/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/thing/channel-types.xml @@ -8,14 +8,14 @@ Outgoing switch channels (relay). - - - - - - - - + + + + + + + + @@ -23,44 +23,22 @@ Incoming channels. - - - - - - - - - - - - - - - - - - - - - - Outgoing shutter channels (relay). - - - - - - - - - - - Time for shutter channels in seconds with an accuracy of 1/10 seconds. - - - - - + + + + + + + + + + + + + + + + @@ -88,6 +66,13 @@ Number The Time in seconds for an JRM channel. + + + + + Dimmer + + Channel for a DIM module. diff --git a/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/thing/thing-types.xml index ae5e9787d7085..cbf2412f3c81b 100644 --- a/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.phc/src/main/resources/ESH-INF/thing/thing-types.xml @@ -15,6 +15,7 @@ Serial Port the PHC modules are connected to true serial-port + false @@ -23,14 +24,14 @@ - + - Thing for an AM channel. + Thing for an output/relay module (AM). - + @@ -45,15 +46,15 @@ - + - Thing for an EM channel. + Thing for an input/switch module (EM). - - + + @@ -67,16 +68,22 @@ - + - Thing for an JRM channel. - - - - - + Thing for an shutter module (JRM). + + + + + + + + + + + @@ -84,35 +91,65 @@ Address of the module as binary, like the DIP switches. true - + true The Time which the first shutter needs to move up/down. - false 30 - + true The Time which the second shutter needs to move up/down. - false 30 - + true The Time which the third shutter needs to move up/down. - false 30 - + true The Time which the fourth shutter needs to move up/down. - false 30 + + + + + + + Thing for a dimmer module (DM). + + + + + + + + + + Address of the module as binary, like the DIP switches. + true + + + true + + The time (in seconds) in which the first dimmer should dim 100%. + 2 + + + true + + The time (in seconds) in which the second dimmer should dim 100%. + 2 + + + + diff --git a/bundles/org.openhab.binding.pioneeravr/pom.xml b/bundles/org.openhab.binding.pioneeravr/pom.xml index 23eca8112441f..b080179704c78 100644 --- a/bundles/org.openhab.binding.pioneeravr/pom.xml +++ b/bundles/org.openhab.binding.pioneeravr/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.pioneeravr diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/feature/feature.xml b/bundles/org.openhab.binding.pioneeravr/src/main/feature/feature.xml index 4ac9cd5f60c0a..092114ad1bef4 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.pioneeravr/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.pioneeravr/${project.version} - + + openhab-runtime-base + openhab-transport-serial + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.pioneeravr/${project.version} + diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/PioneerAvrBindingConstants.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/PioneerAvrBindingConstants.java index 7e7d56a9855cb..5c207daefe71f 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/PioneerAvrBindingConstants.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/PioneerAvrBindingConstants.java @@ -45,26 +45,22 @@ public class PioneerAvrBindingConstants { Stream.of("SC-89", "SC-LX88", "SC-87", "SC-LX78", "SC-85", "SC-LX58", "SC-82", "SC-2024", "SC-81", "VSX-80") .collect(Collectors.toSet())); - public static final Set SUPPORTED_DEVICE_MODELS2016 = Collections.unmodifiableSet( - Stream.of("SC-99", "SC-LX89", "SC-97", "SC-LX79", "SC-95", "SC-LX59", "SC-92", "SC-91", "VSX-90", "VSX-45", - "VSX-830", "VSX-930", "VSX-1130") - .collect(Collectors.toSet())); + public static final Set SUPPORTED_DEVICE_MODELS2016 = Collections + .unmodifiableSet(Stream.of("SC-99", "SC-LX89", "SC-97", "SC-LX79", "SC-95", "SC-LX59", "SC-92", "SC-91", + "VSX-90", "VSX-45", "VSX-830", "VSX-930", "VSX-1130").collect(Collectors.toSet())); public static final Set SUPPORTED_DEVICE_MODELS2017 = Collections.unmodifiableSet( Stream.of("VSX-531", "VSX-531D", "VSX-831", "VSX-1131", "VSX-LX101", "VSX-LX301", "VSX-LX501") .collect(Collectors.toSet())); - public static final Set SUPPORTED_DEVICE_MODELS2018 = Collections.unmodifiableSet( - Stream.of("VSX-532", "VSX-832", "VSX-932", "VSX-LX102", "VSX-LX302", "VSX-LX502") - .collect(Collectors.toSet())); + public static final Set SUPPORTED_DEVICE_MODELS2018 = Collections.unmodifiableSet(Stream + .of("VSX-532", "VSX-832", "VSX-932", "VSX-LX102", "VSX-LX302", "VSX-LX502").collect(Collectors.toSet())); public static final Set SUPPORTED_DEVICE_MODELS2019 = Collections.unmodifiableSet( - Stream.of("VSX-833", "VSX-933", "VSX-LX103", "VSX-LX303", "VSX-LX503") - .collect(Collectors.toSet())); + Stream.of("VSX-833", "VSX-933", "VSX-LX103", "VSX-LX303", "VSX-LX503").collect(Collectors.toSet())); - public static final Set SUPPORTED_DEVICE_MODELS2020 = Collections.unmodifiableSet( - Stream.of("VSX-534", "VSX-534D", "VSX-934", "VSX-LX104", "VSX-LX304", "VSX-LX504") - .collect(Collectors.toSet())); + public static final Set SUPPORTED_DEVICE_MODELS2020 = Collections.unmodifiableSet(Stream + .of("VSX-534", "VSX-534D", "VSX-934", "VSX-LX104", "VSX-LX304", "VSX-LX504").collect(Collectors.toSet())); // List of all Thing Type UIDs public static final ThingTypeUID IP_AVR_THING_TYPE = new ThingTypeUID(BINDING_ID, "ipAvr"); @@ -108,5 +104,4 @@ public class PioneerAvrBindingConstants { IP_AVR_THING_TYPE2020, IP_AVR_THING_TYPE2019, IP_AVR_THING_TYPE2018, IP_AVR_THING_TYPE2017, IP_AVR_THING_TYPE2016, IP_AVR_THING_TYPE2015, IP_AVR_THING_TYPE2014, IP_AVR_UNSUPPORTED_THING_TYPE) .collect(Collectors.toSet()); - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/AbstractAvrHandler.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/AbstractAvrHandler.java index ff7ccf6aa5680..65f4be281d3b8 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/AbstractAvrHandler.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/AbstractAvrHandler.java @@ -25,6 +25,7 @@ import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.pioneeravr.internal.PioneerAvrBindingConstants; import org.openhab.binding.pioneeravr.internal.protocol.RequestResponseFactory; @@ -120,7 +121,7 @@ public void onPowerOn(int zone) { // When the AVR is Powered ON, query the volume, the mute state and the source input of the zone connection.sendVolumeQuery(zone); connection.sendMuteQuery(zone); - connection.sendSourceInputQuery(zone); + connection.sendInputSourceQuery(zone); connection.sendListeningModeQuery(zone); } @@ -166,16 +167,37 @@ public void handleCommand(ChannelUID channelUID, Command command) { boolean unknownCommand = false; if (channelUID.getId().contains(PioneerAvrBindingConstants.POWER_CHANNEL)) { - commandSent = connection.sendPowerCommand(command, getZoneFromChannelUID(channelUID.getId())); + if (command == RefreshType.REFRESH) { + commandSent = connection.sendPowerQuery(getZoneFromChannelUID(channelUID.getId())); + } else { + commandSent = connection.sendPowerCommand(command, getZoneFromChannelUID(channelUID.getId())); + } } else if (channelUID.getId().contains(PioneerAvrBindingConstants.VOLUME_DIMMER_CHANNEL) || channelUID.getId().contains(PioneerAvrBindingConstants.VOLUME_DB_CHANNEL)) { - commandSent = connection.sendVolumeCommand(command, getZoneFromChannelUID(channelUID.getId())); + if (command == RefreshType.REFRESH) { + commandSent = connection.sendVolumeQuery(getZoneFromChannelUID(channelUID.getId())); + } else { + commandSent = connection.sendVolumeCommand(command, getZoneFromChannelUID(channelUID.getId())); + } } else if (channelUID.getId().contains(PioneerAvrBindingConstants.SET_INPUT_SOURCE_CHANNEL)) { - commandSent = connection.sendInputSourceCommand(command, getZoneFromChannelUID(channelUID.getId())); + if (command == RefreshType.REFRESH) { + commandSent = connection.sendInputSourceQuery(getZoneFromChannelUID(channelUID.getId())); + } else { + commandSent = connection.sendInputSourceCommand(command, getZoneFromChannelUID(channelUID.getId())); + } } else if (channelUID.getId().contains(PioneerAvrBindingConstants.LISTENING_MODE_CHANNEL)) { - commandSent = connection.sendListeningModeCommand(command, getZoneFromChannelUID(channelUID.getId())); + if (command == RefreshType.REFRESH) { + commandSent = connection.sendListeningModeQuery(getZoneFromChannelUID(channelUID.getId())); + } else { + commandSent = connection.sendListeningModeCommand(command, + getZoneFromChannelUID(channelUID.getId())); + } } else if (channelUID.getId().contains(PioneerAvrBindingConstants.MUTE_CHANNEL)) { - commandSent = connection.sendMuteCommand(command, getZoneFromChannelUID(channelUID.getId())); + if (command == RefreshType.REFRESH) { + commandSent = connection.sendMuteQuery(getZoneFromChannelUID(channelUID.getId())); + } else { + commandSent = connection.sendMuteCommand(command, getZoneFromChannelUID(channelUID.getId())); + } } else { unknownCommand = true; } @@ -359,5 +381,4 @@ protected int getZoneFromChannelUID(String channelUID) { } return zone; } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/AvrHandlerFactory.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/AvrHandlerFactory.java index 463f95acfd088..634ae78e64589 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/AvrHandlerFactory.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/AvrHandlerFactory.java @@ -13,25 +13,30 @@ package org.openhab.binding.pioneeravr.internal.handler; import java.util.Collections; -import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.pioneeravr.internal.PioneerAvrBindingConstants; import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link AvrHandlerFactory} is responsible for creating things and thing handlers. * * @author Antoine Besnard - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.pioneeravr") public class AvrHandlerFactory extends BaseThingHandlerFactory { @@ -43,8 +48,12 @@ public class AvrHandlerFactory extends BaseThingHandlerFactory { PioneerAvrBindingConstants.IP_AVR_UNSUPPORTED_THING_TYPE, PioneerAvrBindingConstants.SERIAL_AVR_THING_TYPE).collect(Collectors.toSet())); - protected void activate(ComponentContext componentContext, Map configProps) { + private SerialPortManager serialPortManager; + + @Activate + public AvrHandlerFactory(ComponentContext componentContext, final @Reference SerialPortManager serialPortManager) { super.activate(componentContext); + this.serialPortManager = serialPortManager; } @Override @@ -53,7 +62,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(PioneerAvrBindingConstants.IP_AVR_THING_TYPE) @@ -67,7 +76,7 @@ protected ThingHandler createHandler(Thing thing) { || thingTypeUID.equals(PioneerAvrBindingConstants.IP_AVR_UNSUPPORTED_THING_TYPE)) { return new IpAvrHandler(thing); } else if (thingTypeUID.equals(PioneerAvrBindingConstants.SERIAL_AVR_THING_TYPE)) { - return new SerialAvrHandler(thing); + return new SerialAvrHandler(thing, serialPortManager); } return null; diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/IpAvrHandler.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/IpAvrHandler.java index af15e931305d6..7cbe7d18e6c83 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/IpAvrHandler.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/IpAvrHandler.java @@ -35,5 +35,4 @@ protected AvrConnection createConnection() { return new IpAvrConnection(host, tcpPort); } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/SerialAvrHandler.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/SerialAvrHandler.java index f10c8a0d177a3..173b98b99ac34 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/SerialAvrHandler.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/handler/SerialAvrHandler.java @@ -13,6 +13,7 @@ package org.openhab.binding.pioneeravr.internal.handler; import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.pioneeravr.internal.PioneerAvrBindingConstants; import org.openhab.binding.pioneeravr.internal.protocol.avr.AvrConnection; import org.openhab.binding.pioneeravr.internal.protocol.serial.SerialAvrConnection; @@ -24,15 +25,17 @@ */ public class SerialAvrHandler extends AbstractAvrHandler { - public SerialAvrHandler(Thing thing) { + private SerialPortManager serialPortManager; + + public SerialAvrHandler(Thing thing, SerialPortManager serialPortManager) { super(thing); + this.serialPortManager = serialPortManager; } @Override protected AvrConnection createConnection() { String serialPort = (String) this.getConfig().get(PioneerAvrBindingConstants.SERIAL_PORT_PARAMETER); - return new SerialAvrConnection(serialPort); + return new SerialAvrConnection(serialPort, serialPortManager); } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/ParameterizedCommand.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/ParameterizedCommand.java index 79307c0d97875..b74e6f85f6a29 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/ParameterizedCommand.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/ParameterizedCommand.java @@ -92,5 +92,4 @@ public String getParameter() { public String getParameterPattern() { return parameterPattern; } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/RequestResponseFactory.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/RequestResponseFactory.java index 1ce7cf2dfe11d..b8dd8c24e89b7 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/RequestResponseFactory.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/RequestResponseFactory.java @@ -84,5 +84,4 @@ public static ParameterizedCommand getIpControlCommand(ParameterizedCommandType public static Response getIpControlResponse(String responseData) { return new Response(responseData); } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/Response.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/Response.java index ebbf648c78cc4..d4d291b01e709 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/Response.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/Response.java @@ -165,5 +165,4 @@ public boolean hasParameter() { public Integer getZone() { return this.zone; } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/SimpleCommand.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/SimpleCommand.java index 3f65fd1d13cea..846ae33f7ecb3 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/SimpleCommand.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/SimpleCommand.java @@ -76,5 +76,4 @@ public CommandType getCommandType() { public int getZone() { return zone; } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/StreamAvrConnection.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/StreamAvrConnection.java index b57396e32a60e..9527d15bdb05b 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/StreamAvrConnection.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/StreamAvrConnection.java @@ -186,7 +186,7 @@ public boolean sendMuteQuery(int zone) { } @Override - public boolean sendSourceInputQuery(int zone) { + public boolean sendInputSourceQuery(int zone) { return sendCommand(RequestResponseFactory.getIpControlCommand(SimpleCommandType.INPUT_QUERY, zone)); } @@ -278,10 +278,12 @@ public boolean sendListeningModeCommand(Command command, int zone) throws Comman AvrCommand commandToSend = null; if (command == IncreaseDecreaseType.INCREASE) { - commandToSend = RequestResponseFactory.getIpControlCommand(SimpleCommandType.LISTENING_MODE_CHANGE_CYCLIC, zone); + commandToSend = RequestResponseFactory.getIpControlCommand(SimpleCommandType.LISTENING_MODE_CHANGE_CYCLIC, + zone); } else if (command instanceof StringType) { String listeningModeValue = ((StringType) command).toString(); - commandToSend = RequestResponseFactory.getIpControlCommand(ParameterizedCommandType.LISTENING_MODE_SET, zone) + commandToSend = RequestResponseFactory + .getIpControlCommand(ParameterizedCommandType.LISTENING_MODE_SET, zone) .setParameter(listeningModeValue); } else { throw new CommandTypeNotSupportedException("Command type not supported."); @@ -380,7 +382,5 @@ public void stopReader() { // This exception should never happen. } } - } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrCommand.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrCommand.java index 8a744642dd2dc..f543aeed6b2c5 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrCommand.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrCommand.java @@ -61,5 +61,4 @@ public interface CommandType { * @return */ public CommandType getCommandType(); - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrConnection.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrConnection.java index 52e428c3b3eae..3ed4097883d3c 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrConnection.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrConnection.java @@ -86,7 +86,7 @@ public interface AvrConnection { * @param zone * @return */ - public boolean sendSourceInputQuery(int zone); + public boolean sendInputSourceQuery(int zone); /** * Send a listening mode state query to the AVR @@ -147,5 +147,4 @@ public interface AvrConnection { * @return */ public String getConnectionName(); - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrConnectionException.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrConnectionException.java index 8a1191315f917..ebdd413cfdb73 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrConnectionException.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrConnectionException.java @@ -38,5 +38,4 @@ public AvrConnectionException(String message, Throwable cause) { public AvrConnectionException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrResponse.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrResponse.java index 509b146fd82e4..78ee8e3034fba 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrResponse.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/AvrResponse.java @@ -94,5 +94,4 @@ public interface AvrResponseType { * @return */ public Integer getZone(); - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/CommandTypeNotSupportedException.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/CommandTypeNotSupportedException.java index 07e6e7e7bb6b5..db9c20e8806e0 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/CommandTypeNotSupportedException.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/avr/CommandTypeNotSupportedException.java @@ -36,5 +36,4 @@ public CommandTypeNotSupportedException(String message, Throwable cause) { public CommandTypeNotSupportedException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrDisconnectionEvent.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrDisconnectionEvent.java index f0aabb02c4728..2e5de9fa67931 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrDisconnectionEvent.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrDisconnectionEvent.java @@ -36,5 +36,4 @@ public AvrConnection getConnection() { public Throwable getCause() { return cause; } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrDisconnectionListener.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrDisconnectionListener.java index 25a5dce337f52..c83b4a519ab62 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrDisconnectionListener.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrDisconnectionListener.java @@ -25,5 +25,4 @@ public interface AvrDisconnectionListener { * @param event */ public void onDisconnection(AvrDisconnectionEvent event); - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrStatusUpdateEvent.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrStatusUpdateEvent.java index 2e196d2fc9b3d..1d5b61b804a5d 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrStatusUpdateEvent.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrStatusUpdateEvent.java @@ -36,5 +36,4 @@ public AvrConnection getConnection() { public String getData() { return data; } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrUpdateListener.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrUpdateListener.java index 1a153991b414a..89635f4aa7b27 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrUpdateListener.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/event/AvrUpdateListener.java @@ -28,5 +28,4 @@ public interface AvrUpdateListener extends EventListener { * Procedure for receive status update from Pioneer receiver. */ public void statusUpdateReceived(AvrStatusUpdateEvent event); - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/ip/IpAvrConnection.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/ip/IpAvrConnection.java index 4c63b60f89694..65bbaaafdb09d 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/ip/IpAvrConnection.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/ip/IpAvrConnection.java @@ -107,5 +107,4 @@ protected InputStream getInputStream() throws IOException { protected OutputStream getOutputStream() throws IOException { return ipControlSocket.getOutputStream(); } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/serial/SerialAvrConnection.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/serial/SerialAvrConnection.java index adc9589e5a8f6..439d3f25c8f25 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/serial/SerialAvrConnection.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/serial/SerialAvrConnection.java @@ -15,70 +15,76 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; - +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.pioneeravr.internal.protocol.StreamAvrConnection; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.NRSerialPort; - /** * A class that wraps the communication to a Pioneer AVR devices through a serial port * * @author Antoine Besnard - Initial contribution */ +@NonNullByDefault public class SerialAvrConnection extends StreamAvrConnection { private final Logger logger = LoggerFactory.getLogger(SerialAvrConnection.class); private static final Integer LINK_SPEED = 9600; - private String portName; + private final String portName; - private NRSerialPort serialPort; + private @Nullable SerialPort serialPort; - public SerialAvrConnection(String portName) { + private final SerialPortManager serialPortManager; + + public SerialAvrConnection(String portName, SerialPortManager serialPortManager) { this.portName = portName; + this.serialPortManager = serialPortManager; } @Override protected void openConnection() throws IOException { - if (isPortNameExist(portName)) { - serialPort = new NRSerialPort(portName, LINK_SPEED); - - boolean isConnected = serialPort.connect(); + SerialPortIdentifier serialPortIdentifier = serialPortManager.getIdentifier(portName); + if (serialPortIdentifier == null) { + String availablePorts = serialPortManager.getIdentifiers().map(id -> id.getName()) + .collect(Collectors.joining(", ")); + throw new IOException( + "Serial port with name " + portName + " does not exist. Available port names: " + availablePorts); - if (!isConnected) { - throw new IOException("Failed to connect on port " + portName); - } + } - logger.debug("Connected to {}", getConnectionName()); - } else { - throw new IOException("Serial port with name " + portName + " does not exist. Available port names: " - + NRSerialPort.getAvailableSerialPorts()); + try { + SerialPort localSerialPort = serialPortIdentifier.open(SerialAvrConnection.class.getSimpleName(), 2000); + localSerialPort.setSerialPortParams(LINK_SPEED, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, + SerialPort.PARITY_NONE); + serialPort = localSerialPort; + } catch (PortInUseException | UnsupportedCommOperationException e) { + throw new IOException("Failed to connect on port " + portName); } - } - /** - * Check if the Serial with the given name exist. - * - * @param portName - * @return - */ - private boolean isPortNameExist(String portName) { - return NRSerialPort.getAvailableSerialPorts().contains(portName); + logger.debug("Connected to {}", getConnectionName()); } @Override public boolean isConnected() { - return serialPort != null && serialPort.isConnected(); + return serialPort != null; } @Override public void close() { super.close(); - if (serialPort != null) { - serialPort.disconnect(); + SerialPort localSerialPort = serialPort; + if (localSerialPort != null) { + localSerialPort.close(); serialPort = null; logger.debug("Closed port {}", portName); } @@ -90,13 +96,14 @@ public String getConnectionName() { } @Override - protected InputStream getInputStream() throws IOException { - return serialPort.getInputStream(); + protected @Nullable InputStream getInputStream() throws IOException { + SerialPort localSerialPort = serialPort; + return localSerialPort != null ? localSerialPort.getInputStream() : null; } @Override - protected OutputStream getOutputStream() throws IOException { - return serialPort.getOutputStream(); + protected @Nullable OutputStream getOutputStream() throws IOException { + SerialPort localSerialPort = serialPort; + return localSerialPort != null ? localSerialPort.getOutputStream() : null; } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/states/MuteStateValues.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/states/MuteStateValues.java index 4ddabc4466413..23e3482cdec2a 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/states/MuteStateValues.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/states/MuteStateValues.java @@ -20,5 +20,4 @@ public interface MuteStateValues { public static final String ON_VALUE = "0"; public static final String OFF_VALUE = "1"; - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/states/PowerStateValues.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/states/PowerStateValues.java index 160f9399e2383..a17f7113ae94d 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/states/PowerStateValues.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/states/PowerStateValues.java @@ -21,5 +21,4 @@ public interface PowerStateValues { public static final String ON_VALUE = "0"; public static final String OFF_VALUE = "1"; public static final String NETWORK_STANDBY_VALUE = "2"; - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/utils/DisplayInformationConverter.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/utils/DisplayInformationConverter.java index c9d1e0b93a4b4..a13f708aa8e63 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/utils/DisplayInformationConverter.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/utils/DisplayInformationConverter.java @@ -47,5 +47,4 @@ public static String convertMessageFromIpControl(String responsePayload) throws } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/utils/VolumeConverter.java b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/utils/VolumeConverter.java index 1921ea6104e87..0441c12bd1360 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/utils/VolumeConverter.java +++ b/bundles/org.openhab.binding.pioneeravr/src/main/java/org/openhab/binding/pioneeravr/internal/protocol/utils/VolumeConverter.java @@ -96,5 +96,4 @@ private static void validateZone(int zone) { throw new IllegalArgumentException("An unexpected zone was received, the value should be in the range 0-3"); } } - } diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.pioneeravr/src/main/resources/ESH-INF/binding/binding.xml index 1a29866d15a8a..d6dde52474636 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.pioneeravr/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - PioneerAvr Binding diff --git a/bundles/org.openhab.binding.pioneeravr/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.pioneeravr/src/main/resources/ESH-INF/thing/thing-types.xml index f707c0d0ef7c0..3c0d161a457da 100644 --- a/bundles/org.openhab.binding.pioneeravr/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.pioneeravr/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,15 +1,19 @@ - - Control a classic Pioneer AVR (SC-57, SC-LX85, SC-55, SC-1526, SC-LX75, VSX-53, VSX-1326, VSX-LX55, VSX-2021, VSA-LX55, VSX-52, VSX-1126, VSX-1121, VSX-51, VSX-1021, VSX-1026, VSA-1021, VSX-50, VSX-926, VSX-921, VSA-921) over IP + Control a classic Pioneer AVR (SC-57, SC-LX85, SC-55, SC-1526, SC-LX75, VSX-53, VSX-1326, VSX-LX55, + VSX-2021, VSA-LX55, VSX-52, VSX-1126, VSX-1121, VSX-51, VSX-1021, VSX-1026, VSA-1021, VSX-50, VSX-926, VSX-921, + VSA-921) over IP + - + @@ -39,7 +43,7 @@ Control a 2014 Pioneer AVR (SC-LX87, SC-LX77, SC-LX57, SC-2023, SC-1223, VSX-1123, VSX-923) over IP - + @@ -70,10 +74,12 @@ - Control a 2015 Pioneer AVR (SC-89, SC-LX88, SC-87, SC-LX78, SC-85, SC-LX58, SC-82, SC-2024, SC-81, VSX-80) over IP + Control a 2015 Pioneer AVR (SC-89, SC-LX88, SC-87, SC-LX78, SC-85, SC-LX58, SC-82, SC-2024, SC-81, + VSX-80) over IP + - + @@ -104,10 +110,12 @@ - Control a 2016 Pioneer AVR (SC-99, SC-LX89, SC-97, SC-LX79, SC-95, SC-LX59, SC-92, SC-91, VSX-90, VSX-45, VSX-830, VSX-930, VSX-1130) over IP + Control a 2016 Pioneer AVR (SC-99, SC-LX89, SC-97, SC-LX79, SC-95, SC-LX59, SC-92, SC-91, VSX-90, VSX-45, + VSX-830, VSX-930, VSX-1130) over IP + - + @@ -138,10 +146,12 @@ - Control a 2017 Pioneer AVR (VSX-531, VSX-531D, VSX-831, VSX-1131, VSX-LX101, VSX-LX301, VSX-LX501) over IP + Control a 2017 Pioneer AVR (VSX-531, VSX-531D, VSX-831, VSX-1131, VSX-LX101, VSX-LX301, VSX-LX501) over + IP + - + @@ -175,7 +185,7 @@ Control a 2018 Pioneer AVR (VSX-532, VSX-832, VSX-932, VSX-LX102, VSX-LX302, VSX-LX502) over IP - + @@ -209,7 +219,7 @@ Control a 2019 Pioneer AVR (VSX-833, VSX-933, VSX-LX103, VSX-LX303, VSX-LX503) over IP - + @@ -243,7 +253,7 @@ Control a 2020 Pioneer AVR (VSX-534, VSX-534D, VSX-934, VSX-LX104, VSX-LX304, VSX-LX504) over IP - + @@ -275,13 +285,14 @@ - Control a Pioneer AVR over IP for models that are not officially supported. You may experience some odd behaviors. + Control a Pioneer AVR over IP for models that are not officially supported. You may experience some odd + behaviors. - - - - + + + + @@ -304,16 +315,17 @@ Control a Pioneer AVR over a Serial port (RS-232). - - - - + + + + serial-port + false The Serial port name to use to connect to the AVR. @@ -322,293 +334,293 @@ - + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + @@ -623,7 +635,7 @@ Increase/Decrease the volume (%) and mute/un-mute SoundVolume - + @@ -631,7 +643,7 @@ Set the volume level (dB) SoundVolume - + @@ -1291,7 +1303,7 @@ String Display the information displayed on the AVR front screen - + @@ -1363,7 +1375,7 @@ String Display the effective listening mode - + diff --git a/bundles/org.openhab.binding.pixometer/pom.xml b/bundles/org.openhab.binding.pixometer/pom.xml index 5ba4204dc7a29..67f1f859f13bd 100644 --- a/bundles/org.openhab.binding.pixometer/pom.xml +++ b/bundles/org.openhab.binding.pixometer/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.pixometer diff --git a/bundles/org.openhab.binding.pixometer/src/main/feature/feature.xml b/bundles/org.openhab.binding.pixometer/src/main/feature/feature.xml index 45775aff7f55b..fc675fa316ec0 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.pixometer/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.pixometer/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.pixometer/${project.version} + diff --git a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/handler/AccountHandler.java b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/handler/AccountHandler.java index 9b93a7ea038ee..32daa03aecce2 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/handler/AccountHandler.java +++ b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/handler/AccountHandler.java @@ -167,5 +167,4 @@ public long getTokenExpiryDate() { private void setTokenExpiryDate(long expiresIn) { this.tokenExpiryDate = System.nanoTime() + expiresIn; } - } diff --git a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/Annotation.java b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/Annotation.java index dc36553ece5d2..3d3cf47726931 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/Annotation.java +++ b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/Annotation.java @@ -69,5 +69,4 @@ public Integer getImage() { public void setImage(Integer image) { this.image = image; } - } diff --git a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/ImageMeta.java b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/ImageMeta.java index 1128bb1579875..56444eb523e54 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/ImageMeta.java +++ b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/ImageMeta.java @@ -143,5 +143,4 @@ public String getPixolusVersion() { public void setPixolusVersion(String pixolusVersion) { this.pixolusVersion = pixolusVersion; } - } diff --git a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/PixometerAccountConfiguration.java b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/PixometerAccountConfiguration.java index cb2d05699d4d6..e16b95a3a8915 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/PixometerAccountConfiguration.java +++ b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/PixometerAccountConfiguration.java @@ -36,5 +36,4 @@ public class PixometerAccountConfiguration { * Configured refresh rate */ public int refresh; - } diff --git a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/PixometerMeterConfiguration.java b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/PixometerMeterConfiguration.java index 285702af9a9c2..bdb48e9585b87 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/PixometerMeterConfiguration.java +++ b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/PixometerMeterConfiguration.java @@ -26,5 +26,4 @@ public class PixometerMeterConfiguration { * The resourceId of the current meter */ public @NonNullByDefault({}) String resourceId; - } diff --git a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/ReadingInstance.java b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/ReadingInstance.java index 3137f009e7f81..82c6442c84dca 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/ReadingInstance.java +++ b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/config/ReadingInstance.java @@ -89,5 +89,4 @@ public int getProvidedFractionDigitsSecondTariff() { public void setProvidedFractionDigitsSecondTariff(int provided_fraction_digits_second_tariff) { this.providedFractionDigitsSecondTariff = provided_fraction_digits_second_tariff; } - } diff --git a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/data/MeterState.java b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/data/MeterState.java index c772cb561635d..5d1382ea63be5 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/data/MeterState.java +++ b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/data/MeterState.java @@ -61,5 +61,4 @@ public DateTimeType getLastReadingDate() { public DateTimeType getLastRefreshTime() { return lastRefreshTime; } - } diff --git a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/serializer/CustomReadingInstanceDeserializer.java b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/serializer/CustomReadingInstanceDeserializer.java index 927ce674eb99a..30e92af5f8ef6 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/serializer/CustomReadingInstanceDeserializer.java +++ b/bundles/org.openhab.binding.pixometer/src/main/java/org/openhab/binding/pixometer/internal/serializer/CustomReadingInstanceDeserializer.java @@ -106,5 +106,4 @@ private String getStringFromJson(JsonObject data, String key) { private boolean checkStringForNullValues(String s) { return (s == null || s.isEmpty() || s.equals("null")); } - } diff --git a/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/channels.xml index 2f98ccc5a544b..11f955418d163 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/channels.xml @@ -7,12 +7,12 @@ DateTime The last time that the current meter has been read. - + DateTime The last time that the thing has been refreshed. - + diff --git a/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/energymeter.xml b/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/energymeter.xml index cc858a83471b5..94010c5d432da 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/energymeter.xml +++ b/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/energymeter.xml @@ -6,19 +6,20 @@ - + A specific energy meter. - - - + + + - The ID which represents the current meter. You can find it in the pixometer browser app while editing a specific meter. It should look like this: "https://pixometer.io/portal/#/meters/XXXXX/edit" + The ID which represents the current meter. You can find it in the pixometer browser app while editing a + specific meter. It should look like this: "https://pixometer.io/portal/#/meters/XXXXX/edit" @@ -26,6 +27,6 @@ Number:Energy The last value that has been read for this meter. - + diff --git a/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/gasmeter.xml b/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/gasmeter.xml index 9c8347ee73c26..9fdfca158a3f6 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/gasmeter.xml +++ b/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/gasmeter.xml @@ -6,19 +6,20 @@ - + A specific gas meter. - - - + + + - The ID which represents the current meter. You can find it in the pixometer browser app while editing a specific meter. It should look like this: "https://pixometer.io/portal/#/meters/XXXXX/edit" + The ID which represents the current meter. You can find it in the pixometer browser app while editing a + specific meter. It should look like this: "https://pixometer.io/portal/#/meters/XXXXX/edit" @@ -26,6 +27,6 @@ Number:Volume The last value that has been read for this meter. - + diff --git a/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/watermeter.xml b/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/watermeter.xml index b26c4d728b43c..d48e517b3938b 100644 --- a/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/watermeter.xml +++ b/bundles/org.openhab.binding.pixometer/src/main/resources/ESH-INF/thing/watermeter.xml @@ -6,19 +6,20 @@ - + A specific water meter. - - - + + + - The ID which represents the current meter. You can find it in the pixometer browser app while editing a specific meter. It should look like this: "https://pixometer.io/portal/#/meters/XXXXX/edit" + The ID which represents the current meter. You can find it in the pixometer browser app while editing a + specific meter. It should look like this: "https://pixometer.io/portal/#/meters/XXXXX/edit" @@ -26,6 +27,6 @@ Number:Volume The last value that has been read for this meter. - + diff --git a/bundles/org.openhab.binding.pjlinkdevice/pom.xml b/bundles/org.openhab.binding.pjlinkdevice/pom.xml index 9ad8a9b55b6dc..17b87df05f91d 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/pom.xml +++ b/bundles/org.openhab.binding.pjlinkdevice/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.pjlinkdevice diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/PJLinkDevice.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/PJLinkDevice.java index e7da5cfe1f30a..7a8c945f210fa 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/PJLinkDevice.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/PJLinkDevice.java @@ -22,6 +22,7 @@ import java.net.Socket; import java.net.SocketAddress; import java.net.SocketTimeoutException; +import java.text.MessageFormat; import java.time.Duration; import java.time.Instant; import java.util.Arrays; @@ -206,6 +207,11 @@ public void addPrefixToNextCommand(String cmd) throws IOException, Authenticatio this.prefixForNextCommand = cmd; } + public static String preprocessResponse(String response) { + // some devices send leading zero bytes, see https://github.com/openhab/openhab-addons/issues/6725 + return response.replaceAll("^\0*|\0*$", ""); + } + public synchronized String execute(String command) throws IOException, AuthenticationException, ResponseException { String fullCommand = this.prefixForNextCommand + command; this.prefixForNextCommand = ""; @@ -227,18 +233,20 @@ public synchronized String execute(String command) throws IOException, Authentic } String response = null; - while ((response = getReader().readLine()) != null && response.isEmpty()) { + while ((response = getReader().readLine()) != null && preprocessResponse(response).isEmpty()) { logger.debug("Got empty string response for request '{}' from {}, waiting for another line", response, fullCommand.replaceAll("\r", "\\\\r")); } if (response == null) { - throw new ResponseException("Response to request '" + fullCommand.replaceAll("\r", "\\\\r") + "' was null"); + throw new ResponseException(MessageFormat.format("Response to request ''{0}'' was null", + fullCommand.replaceAll("\r", "\\\\r"))); } + if (logger.isDebugEnabled()) { logger.debug("Got response '{}' ({}) for request '{}' from {}", response, Arrays.toString(response.getBytes()), fullCommand.replaceAll("\r", "\\\\r"), ipAddress); } - return response; + return preprocessResponse(response); } public void checkAvailability() throws IOException, AuthenticationException, ResponseException { @@ -350,7 +358,6 @@ public String getOtherInformation() throws ResponseException, IOException, Authe public Set getAvailableInputs() throws ResponseException, IOException, AuthenticationException { return new InputListQueryCommand(this).execute().getResult(); - } public void dispose() { diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/AcknowledgeResponseValue.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/AcknowledgeResponseValue.java index dedfcd35fdc5d..31e72358d846c 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/AcknowledgeResponseValue.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/AcknowledgeResponseValue.java @@ -44,5 +44,4 @@ public static AcknowledgeResponseValue getValueForCode(String code) throws Respo throw new ResponseException("Cannot understand acknowledgement status: " + code); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/CacheException.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/CacheException.java index 82be7c085d324..3d18d48d530a6 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/CacheException.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/CacheException.java @@ -26,5 +26,4 @@ public class CacheException extends RuntimeException { public CacheException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/CachedCommand.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/CachedCommand.java index 4f8a12aaeec4a..2509d0c6360f1 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/CachedCommand.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/CachedCommand.java @@ -71,5 +71,4 @@ public ResponseType execute() throws ResponseException, IOException, Authenticat throw e; } } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/ResponseException.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/ResponseException.java index e6855865e62b1..578a472df41fd 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/ResponseException.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/ResponseException.java @@ -38,5 +38,4 @@ public ResponseException(String message) { public ResponseException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/authentication/AuthenticationCommand.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/authentication/AuthenticationCommand.java index 69998cad1b980..365f5bf650ccb 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/authentication/AuthenticationCommand.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/authentication/AuthenticationCommand.java @@ -61,5 +61,4 @@ public String getChallenge() { public PJLinkDevice getDevice() { return this.device; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/authentication/AuthenticationRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/authentication/AuthenticationRequest.java index df9fcfe0724fd..861950014ee06 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/authentication/AuthenticationRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/authentication/AuthenticationRequest.java @@ -47,5 +47,4 @@ public String getRequestString() throws AuthenticationException { throw new AuthenticationException(e); } } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/errorstatus/ErrorStatusQueryRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/errorstatus/ErrorStatusQueryRequest.java index 01f68577a71dd..f3670bad345af 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/errorstatus/ErrorStatusQueryRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/errorstatus/ErrorStatusQueryRequest.java @@ -27,5 +27,4 @@ public class ErrorStatusQueryRequest implements Request { public String getRequestString() { return "%1ERST ?"; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/errorstatus/ErrorStatusQueryResponse.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/errorstatus/ErrorStatusQueryResponse.java index f71f8ea40c30b..7e44db6aad21f 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/errorstatus/ErrorStatusQueryResponse.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/errorstatus/ErrorStatusQueryResponse.java @@ -113,5 +113,4 @@ protected Map parseRespons } return result; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationCommand.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationCommand.java index 9ff1e815cf1b9..71b68a7e15448 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationCommand.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationCommand.java @@ -71,5 +71,4 @@ protected IdentificationRequest createRequest() { protected IdentificationResponse parseResponse(String response) throws ResponseException { return new IdentificationResponse(this, response); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationRequest.java index b076690bd1599..813602f15530c 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationRequest.java @@ -33,5 +33,4 @@ public IdentificationRequest(IdentificationCommand command) { public String getRequestString() { return "%1" + this.command.getIdentificationProperty().getPJLinkCommandPrefix() + " ?"; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationResponse.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationResponse.java index 038e489ceef4f..3e1ffcf063246 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationResponse.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/identification/IdentificationResponse.java @@ -31,5 +31,4 @@ public IdentificationResponse(IdentificationCommand command, String response) th protected String parseResponseWithoutPrefix(String responseWithoutPrefix) throws ResponseException { return responseWithoutPrefix; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputInstructionRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputInstructionRequest.java index 0cca08acb3c95..2c90af5a4ba97 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputInstructionRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputInstructionRequest.java @@ -33,5 +33,4 @@ public InputInstructionRequest(InputInstructionCommand command) { public String getRequestString() { return "%1INPT " + this.command.getTarget().getPJLinkRepresentation(); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputInstructionResponse.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputInstructionResponse.java index a75f9a5a9eb91..f74178b060d14 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputInstructionResponse.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputInstructionResponse.java @@ -40,5 +40,4 @@ protected AcknowledgeResponseValue parseResponseWithoutPrefix(String responseWit throws ResponseException { return AcknowledgeResponseValue.getValueForCode(responseWithoutPrefix); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputListQueryRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputListQueryRequest.java index 9f26a622b88a4..2a6cfe09324fc 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputListQueryRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputListQueryRequest.java @@ -27,5 +27,4 @@ public class InputListQueryRequest implements Request { public String getRequestString() { return "%1INST ?"; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputListQueryResponse.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputListQueryResponse.java index 37d9a1f90bd4b..6215c3d9285bf 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputListQueryResponse.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputListQueryResponse.java @@ -45,5 +45,4 @@ protected Set parseResponseWithoutPrefix(String responseWithoutPrefix) th } return result; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputQueryRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputQueryRequest.java index 5222176300592..bd5f689b0a0a6 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputQueryRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/input/InputQueryRequest.java @@ -27,5 +27,4 @@ public class InputQueryRequest implements Request { public String getRequestString() { return "%1INPT ?"; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/lampstatus/LampStatesCommand.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/lampstatus/LampStatesCommand.java index 2986776667c67..51a26907ed336 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/lampstatus/LampStatesCommand.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/lampstatus/LampStatesCommand.java @@ -39,5 +39,4 @@ protected LampStatesRequest createRequest() { protected LampStatesResponse parseResponse(String response) throws ResponseException { return new LampStatesResponse(response); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/lampstatus/LampStatesResponse.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/lampstatus/LampStatesResponse.java index ef0244af99f39..d031f6e7783d2 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/lampstatus/LampStatesResponse.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/lampstatus/LampStatesResponse.java @@ -74,5 +74,4 @@ protected List parseResponseWithoutPrefix(String r } return result; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/mute/MuteInstructionRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/mute/MuteInstructionRequest.java index 220b426a5da54..eaac1ab077be7 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/mute/MuteInstructionRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/mute/MuteInstructionRequest.java @@ -34,5 +34,4 @@ public String getRequestString() { return "%1AVMT " + this.command.getTargetChannel().getPJLinkRepresentation() + this.command.getTargetState().getPJLinkRepresentation(); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/mute/MuteQueryRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/mute/MuteQueryRequest.java index 9a7e619e1a4b1..7a2b9a10cd24f 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/mute/MuteQueryRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/mute/MuteQueryRequest.java @@ -27,5 +27,4 @@ public class MuteQueryRequest implements Request { public String getRequestString() { return "%1AVMT ?"; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerInstructionRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerInstructionRequest.java index c008dae0a6a43..e1247d8ecc6ec 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerInstructionRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerInstructionRequest.java @@ -33,5 +33,4 @@ public PowerInstructionRequest(PowerInstructionCommand command) { public String getRequestString() { return "%1POWR " + this.command.getTarget().getPJLinkRepresentation(); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerInstructionResponse.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerInstructionResponse.java index df58494e2f7f2..c93792aecb279 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerInstructionResponse.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerInstructionResponse.java @@ -33,5 +33,4 @@ protected AcknowledgeResponseValue parseResponseWithoutPrefix(String responseWit throws ResponseException { return AcknowledgeResponseValue.getValueForCode(responseWithoutPrefix); } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerQueryRequest.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerQueryRequest.java index e3038fbb43367..d6ca6743878e2 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerQueryRequest.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerQueryRequest.java @@ -27,5 +27,4 @@ public class PowerQueryRequest implements Request { public String getRequestString() { return "%1POWR ?"; } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerQueryResponse.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerQueryResponse.java index 289bf11644948..d09afea123830 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerQueryResponse.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/device/command/power/PowerQueryResponse.java @@ -50,7 +50,6 @@ public static PowerQueryResponseValue parseString(String code) throws ResponseEx throw new ResponseException("Cannot understand power status: " + code); } - } public PowerQueryResponse(String response) throws ResponseException { diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/discovery/AbstractDiscoveryParticipant.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/discovery/AbstractDiscoveryParticipant.java index 0d505f321f95c..a1fddcb63fa9c 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/discovery/AbstractDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/discovery/AbstractDiscoveryParticipant.java @@ -128,5 +128,4 @@ private Set generateAddressesToScan() { } protected abstract void collectAddressesToScan(Set addressesToScan, InterfaceAddress i); - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/discovery/DiscoveryParticipantClass1.java b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/discovery/DiscoveryParticipantClass1.java index ea368d0c6f988..ecdfc8f2b0e79 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/discovery/DiscoveryParticipantClass1.java +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/java/org/openhab/binding/pjlinkdevice/internal/discovery/DiscoveryParticipantClass1.java @@ -100,5 +100,4 @@ protected void checkAddress(InetAddress ip, int tcpPort, int timeout) { // no device here } } - } diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.pjlinkdevice/src/main/resources/ESH-INF/binding/binding.xml index 8aae7ce11db21..1ffc4fbf70d54 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/resources/ESH-INF/binding/binding.xml @@ -6,7 +6,8 @@ PJLinkDevice Binding This binding can control PJLink compatible devices. - The PJLink protocol was mainly standardized for digital projectors, but some other types of devices also use it, in + The PJLink protocol was mainly standardized for digital + projectors, but some other types of devices also use it, in particular TV screens. Nils Schnabel diff --git a/bundles/org.openhab.binding.pjlinkdevice/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.pjlinkdevice/src/main/resources/ESH-INF/thing/thing-types.xml index 3b90083840c8c..b70918c9a9925 100644 --- a/bundles/org.openhab.binding.pjlinkdevice/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.pjlinkdevice/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,60 +9,68 @@ A PJLink compatible device, e.g. a digital projector - - - - - - + + + + + + - + + basic + + + + + Use these settings to configure how the status of the PJLink device will be refreshed + + network-address The address of the PJLink device to control. - + + 4352 + + The TCP port of the PJLink device to control. + + password The password of the PJLink device. - - 4352 - - The TCP port of the PJLink device to control. + + + Seconds between connection retries when connection to the PJLink device has been lost, 0 means never + retry, minimum 30s + 60 - + 5 How often to poll the device state (in seconds). A value of zero will disable polling. - + false Enable polling for the power state. Only considered if the refreshInterval interval is greater than zero. - + false Enable polling for the mute state. Only considered if the refreshInterval interval is greater than zero. - + false Enable polling for the selected input channel. Only considered if the refreshInterval interval is greater than zero. - - - Seconds between connection retries when connection to the PJLink device has been lost, 0 means never - retry, minimum 30s - 60 - - + false Enable polling for the lamp state. Only considered if the refresh interval is greater than zero. @@ -99,7 +107,7 @@ Number How long the lamp has been in use (in hours) - + @@ -113,7 +121,7 @@ Switch Is the lamp in use? - + diff --git a/bundles/org.openhab.binding.plclogo/lib/bit_io.patch b/bundles/org.openhab.binding.plclogo/lib/bit_io.patch index 3ec43f303d0f2..8b1a218da2a25 100644 --- a/bundles/org.openhab.binding.plclogo/lib/bit_io.patch +++ b/bundles/org.openhab.binding.plclogo/lib/bit_io.patch @@ -1,3792 +1,3792 @@ -diff U3 IntByRef.java IntByRef.java ---- IntByRef.java Thu Mar 23 15:34:52 2017 -+++ IntByRef.java Tue Aug 08 18:53:37 2017 -@@ -1,40 +1,40 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ -- --package Moka7; -- --/** -- * Quick class to pass an integer by reference -- * @author Davide -- */ -- --public class IntByRef { -- -- public IntByRef(int Val) -- { -- this.Value=Val; -- } -- public IntByRef() -- { -- this.Value=0; -- } -- public int Value; --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+ -+package Moka7; -+ -+/** -+ * Quick class to pass an integer by reference -+ * @author Davide Nardella -+ */ -+ -+public class IntByRef { -+ -+ public IntByRef(int Val) -+ { -+ this.Value=Val; -+ } -+ public IntByRef() -+ { -+ this.Value=0; -+ } -+ public int Value; -+} -diff U3 S7.java S7.java ---- S7.java Thu Mar 23 15:34:52 2017 -+++ S7.java Tue Aug 08 18:53:37 2017 -@@ -1,287 +1,287 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ --package Moka7; -- --import java.io.UnsupportedEncodingException; --import java.util.Date; --import java.util.Calendar; -- --/** -- * -- * @author Davide -- */ -- -- --// Step 7 Constants and Conversion helper class --public class S7 { -- // S7 ID Area (Area that we want to read/write) -- public static final int S7AreaPE = 0x81; -- public static final int S7AreaPA = 0x82; -- public static final int S7AreaMK = 0x83; -- public static final int S7AreaDB = 0x84; -- public static final int S7AreaCT = 0x1C; -- public static final int S7AreaTM = 0x1D; -- // Connection types -- public static final byte PG = 0x01; -- public static final byte OP = 0x02; -- public static final byte S7_BASIC = 0x03; -- // Block type -- public static final int Block_OB = 0x38; -- public static final int Block_DB = 0x41; -- public static final int Block_SDB = 0x42; -- public static final int Block_FC = 0x43; -- public static final int Block_SFC = 0x44; -- public static final int Block_FB = 0x45; -- public static final int Block_SFB = 0x46; -- // Sub Block Type -- public static final int SubBlk_OB = 0x08; -- public static final int SubBlk_DB = 0x0A; -- public static final int SubBlk_SDB = 0x0B; -- public static final int SubBlk_FC = 0x0C; -- public static final int SubBlk_SFC = 0x0D; -- public static final int SubBlk_FB = 0x0E; -- public static final int SubBlk_SFB = 0x0F; -- // Block languages -- public static final int BlockLangAWL = 0x01; -- public static final int BlockLangKOP = 0x02; -- public static final int BlockLangFUP = 0x03; -- public static final int BlockLangSCL = 0x04; -- public static final int BlockLangDB = 0x05; -- public static final int BlockLangGRAPH = 0x06; -- // PLC Status -- public static final int S7CpuStatusUnknown = 0x00; -- public static final int S7CpuStatusRun = 0x08; -- public static final int S7CpuStatusStop = 0x04; -- // Type Var -- public static final int S7TypeBool = 1; -- public static final int S7TypeInt = 1; -- -- // Returns the bit at Pos.Bit -- public static boolean GetBitAt(byte[] Buffer, int Pos, int Bit) -- { -- int Value = Buffer[Pos] & 0x0FF; -- byte[] Mask = { -- (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08, -- (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80 -- }; -- if (Bit<0) Bit=0; -- if (Bit>7) Bit=7; -- -- return (Value & Mask[Bit])!=0; -- } -- /** -- * Returns a 16 bit unsigned value : from 0 to 65535 (2^16-1) -- * @param Buffer -- * @param Pos start position -- * @return -- */ -- public static int GetWordAt(byte[] Buffer, int Pos) -- { -- int hi = (Buffer[Pos] & 0x00FF); -- int lo = (Buffer[Pos+1] & 0x00FF); -- return (hi<<8)+lo; -- } -- -- // Returns a 16 bit signed value : from -32768 to 32767 -- public static int GetShortAt(byte[] Buffer, int Pos) -- { -- int hi = (Buffer[Pos]); -- int lo = (Buffer[Pos+1] & 0x00FF); -- return ((hi<<8)+lo); -- } -- -- // Returns a 32 bit unsigned value : from 0 to 4294967295 (2^32-1) -- public static long GetDWordAt(byte[] Buffer, int Pos) -- { -- long Result; -- Result=(long)(Buffer[Pos] & 0x0FF); -- Result<<=8; -- Result+=(long)(Buffer[Pos+1] & 0x0FF); -- Result<<=8; -- Result+=(long)(Buffer[Pos+2] & 0x0FF); -- Result<<=8; -- Result+=(long)(Buffer[Pos+3] & 0x0FF); -- return Result; -- } -- -- // Returns a 32 bit signed value : from 0 to 4294967295 (2^32-1) -- public static int GetDIntAt(byte[] Buffer, int Pos) -- { -- int Result; -- Result= Buffer[Pos]; -- Result<<=8; -- Result+=(Buffer[Pos+1] & 0x0FF); -- Result<<=8; -- Result+=(Buffer[Pos+2] & 0x0FF); -- Result<<=8; -- Result+=(Buffer[Pos+3] & 0x0FF); -- return Result; -- } -- -- // Returns a 32 bit floating point -- public static float GetFloatAt(byte[] Buffer, int Pos) -- { -- int IntFloat = GetDIntAt(Buffer, Pos); -- return Float.intBitsToFloat(IntFloat); -- } -- -- // Returns an ASCII string -- public static String GetStringAt(byte[] Buffer, int Pos, int MaxLen) -- { -- byte[] StrBuffer = new byte[MaxLen]; -- System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen); -- String S; -- try { -- S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8 -- } catch (UnsupportedEncodingException ex) { -- S = ""; -- } -- return S; -- } -- -- public static String GetPrintableStringAt(byte[] Buffer, int Pos, int MaxLen) -- { -- byte[] StrBuffer = new byte[MaxLen]; -- System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen); -- for (int c = 0; c < MaxLen; c++) -- { -- if ((StrBuffer[c]<31) || (StrBuffer[c]>126)) -- StrBuffer[c]=46; // '.' -- } -- String S; -- try { -- S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8 -- } catch (UnsupportedEncodingException ex) { -- S = ""; -- } -- return S; -- } -- -- public static Date GetDateAt(byte[] Buffer, int Pos) -- { -- int Year, Month, Day, Hour, Min, Sec; -- Calendar S7Date = Calendar.getInstance(); -- -- Year = S7.BCDtoByte(Buffer[Pos]); -- if (Year<90) -- Year+=2000; -- else -- Year+=1900; -- -- Month=S7.BCDtoByte(Buffer[Pos+1])-1; -- Day =S7.BCDtoByte(Buffer[Pos+2]); -- Hour =S7.BCDtoByte(Buffer[Pos+3]); -- Min =S7.BCDtoByte(Buffer[Pos+4]); -- Sec =S7.BCDtoByte(Buffer[Pos+5]); -- -- S7Date.set(Year, Month, Day, Hour, Min, Sec); -- -- return S7Date.getTime(); -- } -- -- public static void SetBitAt(byte[] Buffer, int Pos, int Bit, boolean Value) -- { -- byte[] Mask = { -- (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08, -- (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80 -- }; -- if (Bit<0) Bit=0; -- if (Bit>7) Bit=7; -- -- if (Value) -- Buffer[Pos]= (byte) (Buffer[Pos] | Mask[Bit]); -- else -- Buffer[Pos]= (byte) (Buffer[Pos] & ~Mask[Bit]); -- } -- -- public static void SetWordAt(byte[] Buffer, int Pos, int Value) -- { -- int Word = Value & 0x0FFFF; -- Buffer[Pos] = (byte) (Word >> 8); -- Buffer[Pos+1] = (byte) (Word & 0x00FF); -- } -- -- public static void SetShortAt(byte[] Buffer, int Pos, int Value) -- { -- Buffer[Pos] = (byte) (Value >> 8); -- Buffer[Pos+1] = (byte) (Value & 0x00FF); -- } -- public static void SetDWordAt(byte[] Buffer, int Pos, long Value) -- { -- long DWord = Value &0x0FFFFFFFF; -- Buffer[Pos+3] = (byte) (DWord &0xFF); -- Buffer[Pos+2] = (byte) ((DWord >> 8) &0xFF); -- Buffer[Pos+1] = (byte) ((DWord >> 16) &0xFF); -- Buffer[Pos] = (byte) ((DWord >> 24) &0xFF); -- } -- -- public static void SetDIntAt(byte[] Buffer, int Pos, int Value) -- { -- Buffer[Pos+3] = (byte) (Value &0xFF); -- Buffer[Pos+2] = (byte) ((Value >> 8) &0xFF); -- Buffer[Pos+1] = (byte) ((Value >> 16) &0xFF); -- Buffer[Pos] = (byte) ((Value >> 24) &0xFF); -- } -- -- public static void SetFloatAt(byte[] Buffer, int Pos, float Value) -- { -- int DInt = Float.floatToIntBits(Value); -- SetDIntAt(Buffer, Pos, DInt); -- } -- -- public static void SetDateAt(byte[] Buffer, int Pos, Date DateTime) -- { -- int Year, Month, Day, Hour, Min, Sec, Dow; -- Calendar S7Date = Calendar.getInstance(); -- S7Date.setTime(DateTime); -- -- Year = S7Date.get(Calendar.YEAR); -- Month = S7Date.get(Calendar.MONTH)+1; -- Day = S7Date.get(Calendar.DAY_OF_MONTH); -- Hour = S7Date.get(Calendar.HOUR_OF_DAY); -- Min = S7Date.get(Calendar.MINUTE); -- Sec = S7Date.get(Calendar.SECOND); -- Dow = S7Date.get(Calendar.DAY_OF_WEEK); -- -- if (Year>1999) -- Year-=2000; -- -- Buffer[Pos] =ByteToBCD(Year); -- Buffer[Pos+1]=ByteToBCD(Month); -- Buffer[Pos+2]=ByteToBCD(Day); -- Buffer[Pos+3]=ByteToBCD(Hour); -- Buffer[Pos+4]=ByteToBCD(Min); -- Buffer[Pos+5]=ByteToBCD(Sec); -- Buffer[Pos+6]=0; -- Buffer[Pos+7]=ByteToBCD(Dow); -- } -- -- public static int BCDtoByte(byte B) -- { -- return ((B >> 4) * 10) + (B & 0x0F); -- } -- -- public static byte ByteToBCD(int Value) -- { -- return (byte) (((Value / 10) << 4) | (Value % 10)); -- } -- --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+package Moka7; -+ -+import java.io.UnsupportedEncodingException; -+import java.util.Date; -+import java.util.Calendar; -+ -+/** -+ * -+ * @author Davide Nardella -+ */ -+ -+ -+// Step 7 Constants and Conversion helper class -+public class S7 { -+ // S7 ID Area (Area that we want to read/write) -+ public static final int S7AreaPE = 0x81; -+ public static final int S7AreaPA = 0x82; -+ public static final int S7AreaMK = 0x83; -+ public static final int S7AreaDB = 0x84; -+ public static final int S7AreaCT = 0x1C; -+ public static final int S7AreaTM = 0x1D; -+ // Connection types -+ public static final byte PG = 0x01; -+ public static final byte OP = 0x02; -+ public static final byte S7_BASIC = 0x03; -+ // Block type -+ public static final int Block_OB = 0x38; -+ public static final int Block_DB = 0x41; -+ public static final int Block_SDB = 0x42; -+ public static final int Block_FC = 0x43; -+ public static final int Block_SFC = 0x44; -+ public static final int Block_FB = 0x45; -+ public static final int Block_SFB = 0x46; -+ // Sub Block Type -+ public static final int SubBlk_OB = 0x08; -+ public static final int SubBlk_DB = 0x0A; -+ public static final int SubBlk_SDB = 0x0B; -+ public static final int SubBlk_FC = 0x0C; -+ public static final int SubBlk_SFC = 0x0D; -+ public static final int SubBlk_FB = 0x0E; -+ public static final int SubBlk_SFB = 0x0F; -+ // Block languages -+ public static final int BlockLangAWL = 0x01; -+ public static final int BlockLangKOP = 0x02; -+ public static final int BlockLangFUP = 0x03; -+ public static final int BlockLangSCL = 0x04; -+ public static final int BlockLangDB = 0x05; -+ public static final int BlockLangGRAPH = 0x06; -+ // PLC Status -+ public static final int S7CpuStatusUnknown = 0x00; -+ public static final int S7CpuStatusRun = 0x08; -+ public static final int S7CpuStatusStop = 0x04; -+ // Type Var -+ public static final int S7TypeBool = 1; -+ public static final int S7TypeInt = 1; -+ -+ // Returns the bit at Pos.Bit -+ public static boolean GetBitAt(byte[] Buffer, int Pos, int Bit) -+ { -+ int Value = Buffer[Pos] & 0x0FF; -+ byte[] Mask = { -+ (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08, -+ (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80 -+ }; -+ if (Bit<0) Bit=0; -+ if (Bit>7) Bit=7; -+ -+ return (Value & Mask[Bit])!=0; -+ } -+ /** -+ * Returns a 16 bit unsigned value : from 0 to 65535 (2^16-1) -+ * @param Buffer -+ * @param Pos start position -+ * @return -+ */ -+ public static int GetWordAt(byte[] Buffer, int Pos) -+ { -+ int hi = (Buffer[Pos] & 0x00FF); -+ int lo = (Buffer[Pos+1] & 0x00FF); -+ return (hi<<8)+lo; -+ } -+ -+ // Returns a 16 bit signed value : from -32768 to 32767 -+ public static int GetShortAt(byte[] Buffer, int Pos) -+ { -+ int hi = (Buffer[Pos]); -+ int lo = (Buffer[Pos+1] & 0x00FF); -+ return ((hi<<8)+lo); -+ } -+ -+ // Returns a 32 bit unsigned value : from 0 to 4294967295 (2^32-1) -+ public static long GetDWordAt(byte[] Buffer, int Pos) -+ { -+ long Result; -+ Result=(long)(Buffer[Pos] & 0x0FF); -+ Result<<=8; -+ Result+=(long)(Buffer[Pos+1] & 0x0FF); -+ Result<<=8; -+ Result+=(long)(Buffer[Pos+2] & 0x0FF); -+ Result<<=8; -+ Result+=(long)(Buffer[Pos+3] & 0x0FF); -+ return Result; -+ } -+ -+ // Returns a 32 bit signed value : from 0 to 4294967295 (2^32-1) -+ public static int GetDIntAt(byte[] Buffer, int Pos) -+ { -+ int Result; -+ Result= Buffer[Pos]; -+ Result<<=8; -+ Result+=(Buffer[Pos+1] & 0x0FF); -+ Result<<=8; -+ Result+=(Buffer[Pos+2] & 0x0FF); -+ Result<<=8; -+ Result+=(Buffer[Pos+3] & 0x0FF); -+ return Result; -+ } -+ -+ // Returns a 32 bit floating point -+ public static float GetFloatAt(byte[] Buffer, int Pos) -+ { -+ int IntFloat = GetDIntAt(Buffer, Pos); -+ return Float.intBitsToFloat(IntFloat); -+ } -+ -+ // Returns an ASCII string -+ public static String GetStringAt(byte[] Buffer, int Pos, int MaxLen) -+ { -+ byte[] StrBuffer = new byte[MaxLen]; -+ System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen); -+ String S; -+ try { -+ S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8 -+ } catch (UnsupportedEncodingException ex) { -+ S = ""; -+ } -+ return S; -+ } -+ -+ public static String GetPrintableStringAt(byte[] Buffer, int Pos, int MaxLen) -+ { -+ byte[] StrBuffer = new byte[MaxLen]; -+ System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen); -+ for (int c = 0; c < MaxLen; c++) -+ { -+ if ((StrBuffer[c]<31) || (StrBuffer[c]>126)) -+ StrBuffer[c]=46; // '.' -+ } -+ String S; -+ try { -+ S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8 -+ } catch (UnsupportedEncodingException ex) { -+ S = ""; -+ } -+ return S; -+ } -+ -+ public static Date GetDateAt(byte[] Buffer, int Pos) -+ { -+ int Year, Month, Day, Hour, Min, Sec; -+ Calendar S7Date = Calendar.getInstance(); -+ -+ Year = S7.BCDtoByte(Buffer[Pos]); -+ if (Year<90) -+ Year+=2000; -+ else -+ Year+=1900; -+ -+ Month=S7.BCDtoByte(Buffer[Pos+1])-1; -+ Day =S7.BCDtoByte(Buffer[Pos+2]); -+ Hour =S7.BCDtoByte(Buffer[Pos+3]); -+ Min =S7.BCDtoByte(Buffer[Pos+4]); -+ Sec =S7.BCDtoByte(Buffer[Pos+5]); -+ -+ S7Date.set(Year, Month, Day, Hour, Min, Sec); -+ -+ return S7Date.getTime(); -+ } -+ -+ public static void SetBitAt(byte[] Buffer, int Pos, int Bit, boolean Value) -+ { -+ byte[] Mask = { -+ (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08, -+ (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80 -+ }; -+ if (Bit<0) Bit=0; -+ if (Bit>7) Bit=7; -+ -+ if (Value) -+ Buffer[Pos]= (byte) (Buffer[Pos] | Mask[Bit]); -+ else -+ Buffer[Pos]= (byte) (Buffer[Pos] & ~Mask[Bit]); -+ } -+ -+ public static void SetWordAt(byte[] Buffer, int Pos, int Value) -+ { -+ int Word = Value & 0x0FFFF; -+ Buffer[Pos] = (byte) (Word >> 8); -+ Buffer[Pos+1] = (byte) (Word & 0x00FF); -+ } -+ -+ public static void SetShortAt(byte[] Buffer, int Pos, int Value) -+ { -+ Buffer[Pos] = (byte) (Value >> 8); -+ Buffer[Pos+1] = (byte) (Value & 0x00FF); -+ } -+ public static void SetDWordAt(byte[] Buffer, int Pos, long Value) -+ { -+ long DWord = Value &0x0FFFFFFFF; -+ Buffer[Pos+3] = (byte) (DWord &0xFF); -+ Buffer[Pos+2] = (byte) ((DWord >> 8) &0xFF); -+ Buffer[Pos+1] = (byte) ((DWord >> 16) &0xFF); -+ Buffer[Pos] = (byte) ((DWord >> 24) &0xFF); -+ } -+ -+ public static void SetDIntAt(byte[] Buffer, int Pos, int Value) -+ { -+ Buffer[Pos+3] = (byte) (Value &0xFF); -+ Buffer[Pos+2] = (byte) ((Value >> 8) &0xFF); -+ Buffer[Pos+1] = (byte) ((Value >> 16) &0xFF); -+ Buffer[Pos] = (byte) ((Value >> 24) &0xFF); -+ } -+ -+ public static void SetFloatAt(byte[] Buffer, int Pos, float Value) -+ { -+ int DInt = Float.floatToIntBits(Value); -+ SetDIntAt(Buffer, Pos, DInt); -+ } -+ -+ public static void SetDateAt(byte[] Buffer, int Pos, Date DateTime) -+ { -+ int Year, Month, Day, Hour, Min, Sec, Dow; -+ Calendar S7Date = Calendar.getInstance(); -+ S7Date.setTime(DateTime); -+ -+ Year = S7Date.get(Calendar.YEAR); -+ Month = S7Date.get(Calendar.MONTH)+1; -+ Day = S7Date.get(Calendar.DAY_OF_MONTH); -+ Hour = S7Date.get(Calendar.HOUR_OF_DAY); -+ Min = S7Date.get(Calendar.MINUTE); -+ Sec = S7Date.get(Calendar.SECOND); -+ Dow = S7Date.get(Calendar.DAY_OF_WEEK); -+ -+ if (Year>1999) -+ Year-=2000; -+ -+ Buffer[Pos] =ByteToBCD(Year); -+ Buffer[Pos+1]=ByteToBCD(Month); -+ Buffer[Pos+2]=ByteToBCD(Day); -+ Buffer[Pos+3]=ByteToBCD(Hour); -+ Buffer[Pos+4]=ByteToBCD(Min); -+ Buffer[Pos+5]=ByteToBCD(Sec); -+ Buffer[Pos+6]=0; -+ Buffer[Pos+7]=ByteToBCD(Dow); -+ } -+ -+ public static int BCDtoByte(byte B) -+ { -+ return ((B >> 4) * 10) + (B & 0x0F); -+ } -+ -+ public static byte ByteToBCD(int Value) -+ { -+ return (byte) (((Value / 10) << 4) | (Value % 10)); -+ } -+ -+} -diff U3 S7BlockInfo.java S7BlockInfo.java ---- S7BlockInfo.java Thu Mar 23 15:34:52 2017 -+++ S7BlockInfo.java Tue Aug 08 18:53:37 2017 -@@ -1,101 +1,101 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ --package Moka7; --import java.util.Date; --/** -- * -- * @author Davide -- */ --public class S7BlockInfo { -- -- private final int BufSize = 96; -- // MilliSeconds between 1970/1/1 (Java time base) and 1984/1/1 (Siemens base) -- private final long DeltaMilliSecs = 441763200000L; -- protected byte[] Buffer = new byte[BufSize]; -- -- protected void Update(byte[] Src, int Pos) -- { -- System.arraycopy(Src, Pos, Buffer, 0, BufSize); -- } -- public int BlkType() -- { -- return Buffer[2]; -- } -- public int BlkNumber() -- { -- return S7.GetWordAt(Buffer, 3); -- } -- public int BlkLang() -- { -- return Buffer[1]; -- } -- public int BlkFlags() -- { -- return Buffer[0]; -- } -- public int MC7Size() // The real size in bytes -- { -- return S7.GetWordAt(Buffer, 31); -- } -- public int LoadSize() -- { -- return S7.GetDIntAt(Buffer, 5); -- } -- public int LocalData() -- { -- return S7.GetWordAt(Buffer, 29); -- } -- public int SBBLength() -- { -- return S7.GetWordAt(Buffer, 25); -- } -- public int Checksum() -- { -- return S7.GetWordAt(Buffer, 59); -- } -- public int Version() -- { -- return Buffer[57]; -- } -- public Date CodeDate() -- { -- long BlockDate = ((long)S7.GetWordAt(Buffer, 17))*86400000L+DeltaMilliSecs; -- return new Date(BlockDate); -- } -- public Date IntfDate() -- { -- long BlockDate = ((long)S7.GetWordAt(Buffer, 23))*86400000L+DeltaMilliSecs; -- return new Date(BlockDate); -- } -- public String Author() -- { -- return S7.GetStringAt(Buffer,33,8); -- } -- public String Family() -- { -- return S7.GetStringAt(Buffer,41,8); -- } -- public String Header() -- { -- return S7.GetStringAt(Buffer,49,8); -- } -- --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+package Moka7; -+import java.util.Date; -+/** -+ * -+ * @author Davide Nardella -+ */ -+public class S7BlockInfo { -+ -+ private final int BufSize = 96; -+ // MilliSeconds between 1970/1/1 (Java time base) and 1984/1/1 (Siemens base) -+ private final long DeltaMilliSecs = 441763200000L; -+ protected byte[] Buffer = new byte[BufSize]; -+ -+ protected void Update(byte[] Src, int Pos) -+ { -+ System.arraycopy(Src, Pos, Buffer, 0, BufSize); -+ } -+ public int BlkType() -+ { -+ return Buffer[2]; -+ } -+ public int BlkNumber() -+ { -+ return S7.GetWordAt(Buffer, 3); -+ } -+ public int BlkLang() -+ { -+ return Buffer[1]; -+ } -+ public int BlkFlags() -+ { -+ return Buffer[0]; -+ } -+ public int MC7Size() // The real size in bytes -+ { -+ return S7.GetWordAt(Buffer, 31); -+ } -+ public int LoadSize() -+ { -+ return S7.GetDIntAt(Buffer, 5); -+ } -+ public int LocalData() -+ { -+ return S7.GetWordAt(Buffer, 29); -+ } -+ public int SBBLength() -+ { -+ return S7.GetWordAt(Buffer, 25); -+ } -+ public int Checksum() -+ { -+ return S7.GetWordAt(Buffer, 59); -+ } -+ public int Version() -+ { -+ return Buffer[57]; -+ } -+ public Date CodeDate() -+ { -+ long BlockDate = ((long)S7.GetWordAt(Buffer, 17))*86400000L+DeltaMilliSecs; -+ return new Date(BlockDate); -+ } -+ public Date IntfDate() -+ { -+ long BlockDate = ((long)S7.GetWordAt(Buffer, 23))*86400000L+DeltaMilliSecs; -+ return new Date(BlockDate); -+ } -+ public String Author() -+ { -+ return S7.GetStringAt(Buffer,33,8); -+ } -+ public String Family() -+ { -+ return S7.GetStringAt(Buffer,41,8); -+ } -+ public String Header() -+ { -+ return S7.GetStringAt(Buffer,49,8); -+ } -+ -+} -diff U3 S7Client.java S7Client.java ---- S7Client.java Thu Mar 23 15:34:52 2017 -+++ S7Client.java Tue Aug 08 18:53:37 2017 -@@ -1,1214 +1,1233 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ --package Moka7; -- --import java.io.DataInputStream; --import java.io.DataOutputStream; --import java.io.IOException; --import java.io.UnsupportedEncodingException; --import java.net.InetSocketAddress; --import java.net.Socket; --import java.net.SocketAddress; --import java.util.Date; -- -- --/** -- * -- * @author Dave Nardella -- */ --public class S7Client --{ -- // WordLength -- private static final byte S7WLByte =0x02; -- private static final byte S7WLCounter =0x1C; -- private static final byte S7WLTimer =0x1D; -- // Error Codes -- public static final int errTCPConnectionFailed = 0x0001; -- public static final int errTCPDataSend = 0x0002; -- public static final int errTCPDataRecv = 0x0003; -- public static final int errTCPDataRecvTout = 0x0004; -- public static final int errTCPConnectionReset = 0x0005; -- public static final int errISOInvalidPDU = 0x0006; -- public static final int errISOConnectionFailed = 0x0007; -- public static final int errISONegotiatingPDU = 0x0008; -- public static final int errS7InvalidPDU = 0x0009; -- public static final int errS7DataRead = 0x000A; -- public static final int errS7DataWrite = 0x000B; -- public static final int errS7BufferTooSmall = 0x000C; -- public static final int errS7FunctionError = 0x000D; -- public static final int errS7InvalidParams = 0x000E; -- -- // Public fields -- public boolean Connected = false; -- public int LastError = 0; -- public int RecvTimeout = 2000; -- -- // Privates -- private static final int ISOTCP = 102; // ISOTCP Port -- private static final int MinPduSize = 16; -- private static final int DefaultPduSizeRequested = 480; -- private static final int IsoHSize = 7; // TPKT+COTP Header Size -- private static final int MaxPduSize = DefaultPduSizeRequested+IsoHSize; -- -- -- private Socket TCPSocket; -- private final byte[] PDU = new byte[2048]; -- -- private DataInputStream InStream = null; -- private DataOutputStream OutStream = null; -- -- private String IPAddress; -- -- private byte LocalTSAP_HI; -- private byte LocalTSAP_LO; -- private byte RemoteTSAP_HI; -- private byte RemoteTSAP_LO; -- private byte LastPDUType; -- -- private short ConnType = S7.PG; -- private int _PDULength = 0; -- -- // Telegrams -- // ISO Connection Request telegram (contains also ISO Header and COTP Header) -- private static final byte ISO_CR[] = { -- // TPKT (RFC1006 Header) -- (byte)0x03, // RFC 1006 ID (3) -- (byte)0x00, // Reserved, always 0 -- (byte)0x00, // High part of packet lenght (entire frame, payload and TPDU included) -- (byte)0x16, // Low part of packet lenght (entire frame, payload and TPDU included) -- // COTP (ISO 8073 Header) -- (byte)0x11, // PDU Size Length -- (byte)0xE0, // CR - Connection Request ID -- (byte)0x00, // Dst Reference HI -- (byte)0x00, // Dst Reference LO -- (byte)0x00, // Src Reference HI -- (byte)0x01, // Src Reference LO -- (byte)0x00, // Class + Options Flags -- (byte)0xC0, // PDU Max Length ID -- (byte)0x01, // PDU Max Length HI -- (byte)0x0A, // PDU Max Length LO -- (byte)0xC1, // Src TSAP Identifier -- (byte)0x02, // Src TSAP Length (2 bytes) -- (byte)0x01, // Src TSAP HI (will be overwritten) -- (byte)0x00, // Src TSAP LO (will be overwritten) -- (byte)0xC2, // Dst TSAP Identifier -- (byte)0x02, // Dst TSAP Length (2 bytes) -- (byte)0x01, // Dst TSAP HI (will be overwritten) -- (byte)0x02 // Dst TSAP LO (will be overwritten) -- }; -- -- // S7 PDU Negotiation Telegram (contains also ISO Header and COTP Header) -- private static final byte S7_PN[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x19, -- (byte)0x02, (byte)0xf0, (byte)0x80, // TPKT + COTP (see above for info) -- (byte)0x32, (byte)0x01, (byte)0x00, (byte)0x00, -- (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x08, -- (byte)0x00, (byte)0x00, (byte)0xf0, (byte)0x00, -- (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01, -- (byte)0x00, (byte)0x1e // PDU Length Requested = HI-LO 480 bytes -- }; -- -- // S7 Read/Write Request Header (contains also ISO Header and COTP Header) -- private static final byte S7_RW[] = { // 31-35 bytes -- (byte)0x03,(byte)0x00, -- (byte)0x00,(byte)0x1f, // Telegram Length (Data Size + 31 or 35) -- (byte)0x02,(byte)0xf0, (byte)0x80, // COTP (see above for info) -- (byte)0x32, // S7 Protocol ID -- (byte)0x01, // Job Type -- (byte)0x00,(byte)0x00, // Redundancy identification -- (byte)0x05,(byte)0x00, // PDU Reference -- (byte)0x00,(byte)0x0e, // Parameters Length -- (byte)0x00,(byte)0x00, // Data Length = Size(bytes) + 4 -- (byte)0x04, // Function 4 Read Var, 5 Write Var -- (byte)0x01, // Items count -- (byte)0x12, // Var spec. -- (byte)0x0a, // Length of remaining bytes -- (byte)0x10, // Syntax ID -- S7WLByte, // Transport Size -- (byte)0x00,(byte)0x00, // Num Elements -- (byte)0x00,(byte)0x00, // DB Number (if any, else 0) -- (byte)0x84, // Area Type -- (byte)0x00,(byte)0x00,(byte)0x00, // Area Offset -- // WR area -- (byte)0x00, // Reserved -- (byte)0x04, // Transport size -- (byte)0x00,(byte)0x00, // Data Length * 8 (if not timer or counter) -- }; -- private static final int Size_RD = 31; -- private static final int Size_WR = 35; -- -- // S7 Get Block Info Request Header (contains also ISO Header and COTP Header) -- private static final byte S7_BI[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x05, -- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -- (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12, -- (byte)0x04, (byte)0x11, (byte)0x43, (byte)0x03, -- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -- (byte)0x08, (byte)0x30, -- (byte)0x41, // Block Type -- (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, // ASCII Block Number -- (byte)0x41 -- }; -- -- // SZL First telegram request -- private static final byte S7_SZL_FIRST[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x07, (byte)0x00, (byte)0x00, -- (byte)0x05, (byte)0x00, // Sequence out -- (byte)0x00, (byte)0x08, (byte)0x00, -- (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12, -- (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01, -- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -- (byte)0x04, -- (byte)0x00, (byte)0x00, // ID (29) -- (byte)0x00, (byte)0x00 // Index (31) -- }; -- -- // SZL Next telegram request -- private static final byte S7_SZL_NEXT[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x06, -- (byte)0x00, (byte)0x00, (byte)0x0c, (byte)0x00, -- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, -- (byte)0x08, (byte)0x12, (byte)0x44, (byte)0x01, -- (byte)0x01, // Sequence -- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, -- (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00 -- }; -- -- // Get Date/Time request -- private static final byte S7_GET_DT[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x38, -- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, -- (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x01, -- (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, -- (byte)0x00 -- }; -- -- // Set Date/Time command -- private static final byte S7_SET_DT[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x89, -- (byte)0x03, (byte)0x00, (byte)0x08, (byte)0x00, -- (byte)0x0e, (byte)0x00, (byte)0x01, (byte)0x12, -- (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x02, -- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -- (byte)0x0a, (byte)0x00, (byte)0x19, // Hi part of Year -- (byte)0x13, // Lo part of Year -- (byte)0x12, // Month -- (byte)0x06, // Day -- (byte)0x17, // Hour -- (byte)0x37, // Min -- (byte)0x13, // Sec -- (byte)0x00, (byte)0x01 // ms + Day of week -- }; -- -- // S7 STOP request -- private static final byte S7_STOP[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0e, -- (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00, -- (byte)0x00, (byte)0x29, (byte)0x00, (byte)0x00, -- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, -- (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52, -- (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41, -- (byte)0x4d -- }; -- -- // S7 HOT Start request -- private static final byte S7_HOT_START[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0c, -- (byte)0x00, (byte)0x00, (byte)0x14, (byte)0x00, -- (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00, -- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, -- (byte)0xfd, (byte)0x00, (byte)0x00, (byte)0x09, -- (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52, -- (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41, -- (byte)0x4d -- }; -- -- // S7 COLD Start request -- private static final byte S7_COLD_START[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0f, -- (byte)0x00, (byte)0x00, (byte)0x16, (byte)0x00, -- (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00, -- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, -- (byte)0xfd, (byte)0x00, (byte)0x02, (byte)0x43, -- (byte)0x20, (byte)0x09, (byte)0x50, (byte)0x5f, -- (byte)0x50, (byte)0x52, (byte)0x4f, (byte)0x47, -- (byte)0x52, (byte)0x41, (byte)0x4d -- }; -- -- // S7 Get PLC Status -- private static final byte S7_GET_STAT[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x2c, -- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -- (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12, -- (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01, -- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -- (byte)0x04, (byte)0x04, (byte)0x24, (byte)0x00, -- (byte)0x00 -- }; -- -- // S7 Set Session Password -- private static final byte S7_SET_PWD[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x27, -- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -- (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12, -- (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x01, -- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -- (byte)0x08, -- // 8 Char Encoded Password -- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, -- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 -- }; -- -- // S7 Clear Session Password -- private static final byte S7_CLR_PWD[] = { -- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d, -- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x29, -- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, -- (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x02, -- (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, -- (byte)0x00 -- }; -- -- public S7Client() -- { -- // Placeholder for future implementations -- } -- -- public static String ErrorText(int Error) -- { -- switch (Error) -- { -- case errTCPConnectionFailed : -- return "TCP Connection failed."; -- case errTCPDataSend : -- return "TCP Sending error."; -- case errTCPDataRecv : -- return "TCP Receiving error."; -- case errTCPDataRecvTout : -- return "Data Receiving timeout."; -- case errTCPConnectionReset : -- return "Connection reset by the peer."; -- case errISOInvalidPDU : -- return "Invalid ISO PDU received."; -- case errISOConnectionFailed : -- return "ISO connection refused by the CPU."; -- case errISONegotiatingPDU : -- return "ISO error negotiating the PDU length."; -- case errS7InvalidPDU : -- return "Invalid S7 PDU received."; -- case errS7DataRead : -- return "S7 Error reading data from the CPU."; -- case errS7DataWrite : -- return "S7 Error writing data to the CPU."; -- case errS7BufferTooSmall : -- return "The Buffer supplied to the function is too small."; -- case errS7FunctionError : -- return "S7 function refused by the CPU."; -- case errS7InvalidParams : -- return "Invalid parameters supplied to the function."; -- default : -- return "Unknown error : 0x"+Integer.toHexString(Error); -- } -- } -- -- private int TCPConnect() -- { -- SocketAddress sockaddr = new InetSocketAddress(IPAddress, ISOTCP); -- LastError=0; -- try { -- TCPSocket = new Socket(); -- TCPSocket.connect(sockaddr ,5000); -- TCPSocket.setTcpNoDelay(true); -- InStream = new DataInputStream(TCPSocket.getInputStream()); -- OutStream = new DataOutputStream(TCPSocket.getOutputStream()); -- } -- catch (IOException e) { -- LastError=errTCPConnectionFailed; -- } -- return LastError; -- } -- -- private int WaitForData(int Size, int Timeout) -- { -- int cnt = 0; -- LastError=0; -- int SizeAvail; -- boolean Expired = false; -- try -- { -- SizeAvail=InStream.available(); -- while ((SizeAvailTimeout; -- // If timeout we clean the buffer -- if (Expired && (SizeAvail>0) && (LastError==0)) -- InStream.read(PDU, 0, SizeAvail); -- } -- } -- catch (IOException ex) -- { -- LastError=errTCPDataRecvTout; -- } -- if (cnt>=Timeout) -- { -- LastError=errTCPDataRecvTout; -- } -- return LastError; -- } -- -- private int RecvPacket(byte[] Buffer, int Start, int Size) -- { -- int BytesRead=0; -- LastError=WaitForData(Size,RecvTimeout); -- if (LastError==0) -- { -- try { -- BytesRead = InStream.read(Buffer, Start, Size); -- } catch (IOException ex) { -- LastError=errTCPDataRecv; -- } -- if (BytesRead==0) -- LastError=errTCPConnectionReset; -- } -- return LastError; -- } -- -- private void SendPacket(byte[] Buffer, int Len) -- { -- LastError = 0; -- try { -- OutStream.write(Buffer,0,Len); -- OutStream.flush(); -- } catch (IOException ex) { -- LastError = errTCPDataSend; -- } -- } -- private void SendPacket(byte[] Buffer) -- { -- SendPacket(Buffer,Buffer.length); -- } -- -- private int RecvIsoPacket() -- { -- Boolean Done = false; -- int Size = 0; -- while ((LastError==0) && !Done) -- { -- // Get TPKT (4 bytes) -- RecvPacket(PDU, 0, 4); -- if (LastError==0) -- { -- Size=S7.GetWordAt(PDU,2); -- // Check 0 bytes Data Packet (only TPKT+COTP = 7 bytes) -- if (Size==IsoHSize) -- RecvPacket(PDU,4, 3); // Skip remaining 3 bytes and Done is still false -- else -- { -- if ((Size>MaxPduSize) || (Size16 && <247 -- } -- } -- } -- if (LastError==0) -- { -- RecvPacket(PDU,4, 3); // Skip remaining 3 COTP bytes -- LastPDUType=PDU[5]; // Stores PDU Type, we need it -- // Receives the S7 Payload -- RecvPacket(PDU, 7, Size-IsoHSize); -- } -- if (LastError==0) -- return Size; -- else -- return 0; -- } -- -- private int ISOConnect() -- { -- int Size; -- ISO_CR[16]=LocalTSAP_HI; -- ISO_CR[17]=LocalTSAP_LO; -- ISO_CR[20]=RemoteTSAP_HI; -- ISO_CR[21]=RemoteTSAP_LO; -- -- // Sends the connection request telegram -- SendPacket(ISO_CR); -- if (LastError==0) -- { -- // Gets the reply (if any) -- Size=RecvIsoPacket(); -- if (LastError==0) -- { -- if (Size==22) -- { -- if (LastPDUType!=(byte)0xD0) // 0xD0 = CC Connection confirm -- LastError=errISOConnectionFailed; -- } -- else -- LastError=errISOInvalidPDU; -- } -- } -- return LastError; -- } -- -- private int NegotiatePduLength() -- { -- int Length; -- // Set PDU Size Requested -- S7.SetWordAt(S7_PN,23,DefaultPduSizeRequested); -- // Sends the connection request telegram -- SendPacket(S7_PN); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (LastError==0) -- { -- // check S7 Error -- if ((Length==27) && (PDU[17]==0) && (PDU[18]==0)) // 20 = size of Negotiate Answer -- { -- // Get PDU Size Negotiated -- _PDULength = S7.GetWordAt(PDU,25); -- if (_PDULength>0) -- return 0; -- else -- LastError=errISONegotiatingPDU; -- } -- else -- LastError=errISONegotiatingPDU; -- } -- } -- return LastError; -- } -- -- public void SetConnectionType(short ConnectionType) -- { -- ConnType=ConnectionType; -- } -- -- public int Connect() -- { -- LastError=0; -- if (!Connected) -- { -- TCPConnect(); -- if (LastError==0) // First stage : TCP Connection -- { -- ISOConnect(); -- if (LastError==0) // Second stage : ISOTCP (ISO 8073) Connection -- { -- LastError=NegotiatePduLength(); // Third stage : S7 PDU negotiation -- } -- } -- } -- Connected=LastError==0; -- -- // In case the connection is not completely established (TCP connection + ISO connection + PDU negotiation) -- // we close the socket and its IO streams to revert the object back to pre-Connect() state -- if (!Connected) -- { -- if (TCPSocket != null) { -- try { -- TCPSocket.close(); -- } catch (IOException ex) { -- } -- } -- if (InStream != null) { -- try { -- InStream.close(); -- } catch (IOException ex) { -- } -- } -- if (OutStream != null) { -- try { -- OutStream.close(); -- } catch (IOException ex) { -- } -- } -- _PDULength = 0; -- } -- -- return LastError; -- } -- -- public void Disconnect() -- { -- if (Connected) -- { -- try { -- OutStream.close(); -- InStream.close(); -- TCPSocket.close(); -- _PDULength=0; -- } catch (IOException ex) { -- } -- Connected=false; -- } -- } -- -- public int ConnectTo(String Address, int Rack, int Slot) -- { -- int RemoteTSAP=(ConnType<<8)+ (Rack * 0x20) + Slot; -- SetConnectionParams(Address, 0x0100, RemoteTSAP); -- return Connect(); -- } -- -- public int PDULength() -- { -- return _PDULength; -- } -- -- public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP) -- { -- int LocTSAP = LocalTSAP & 0x0000FFFF; -- int RemTSAP = RemoteTSAP & 0x0000FFFF; -- IPAddress = Address; -- LocalTSAP_HI = (byte) (LocTSAP>>8); -- LocalTSAP_LO = (byte) (LocTSAP & 0x00FF); -- RemoteTSAP_HI= (byte) (RemTSAP>>8); -- RemoteTSAP_LO= (byte) (RemTSAP & 0x00FF); -- } -- -- public int ReadArea(int Area, int DBNumber, int Start, int Amount, byte[] Data) -- { -- int Address; -- int NumElements; -- int MaxElements; -- int TotElements; -- int SizeRequested; -- int Length; -- int Offset = 0; -- int WordSize = 1; -- -- LastError=0; -- -- // If we are addressing Timers or counters the element size is 2 -- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) -- WordSize = 2; -- -- MaxElements=(_PDULength-18) / WordSize; // 18 = Reply telegram header -- TotElements=Amount; -- -- while ((TotElements>0) && (LastError==0)) -- { -- NumElements=TotElements; -- if (NumElements>MaxElements) -- NumElements=MaxElements; -- -- SizeRequested = NumElements * WordSize; -- -- // Setup the telegram -- System.arraycopy(S7_RW, 0, PDU, 0, Size_RD); -- // Set DB Number -- PDU[27] = (byte) Area; -- // Set Area -- if (Area==S7.S7AreaDB) -- S7.SetWordAt(PDU,25,DBNumber); -- -- // Adjusts Start and word length -- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) -- { -- Address = Start; -- if (Area==S7.S7AreaCT) -- PDU[22]=S7WLCounter; -- else -- PDU[22]=S7WLTimer; -- } -- else -- Address = Start<<3; -- -- // Num elements -- S7.SetWordAt(PDU,23,NumElements); -- -- // Address into the PLC (only 3 bytes) -- PDU[30] = (byte) (Address & 0x0FF); -- Address = Address >> 8; -- PDU[29] = (byte) (Address & 0x0FF); -- Address = Address >> 8; -- PDU[28] = (byte) (Address & 0x0FF); -- -- SendPacket(PDU, Size_RD); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (LastError==0) -- { -- if (Length>=25) -- { -- if ((Length-25==SizeRequested) && (PDU[21]==(byte)0xFF)) -- { -- System.arraycopy(PDU, 25, Data, Offset, SizeRequested); -- Offset+=SizeRequested; -- } -- else -- LastError = errS7DataRead; -- } -- else -- LastError = errS7InvalidPDU; -- } -- } -- -- TotElements -= NumElements; -- Start += NumElements*WordSize; -- } -- return LastError; -- } -- -- public int WriteArea(int Area, int DBNumber, int Start, int Amount, byte[] Data) -- { -- int Address; -- int NumElements; -- int MaxElements; -- int TotElements; -- int DataSize; -- int IsoSize; -- int Length; -- int Offset = 0; -- int WordSize = 1; -- -- LastError=0; -- -- // If we are addressing Timers or counters the element size is 2 -- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) -- WordSize = 2; -- -- MaxElements=(_PDULength-35) / WordSize; // 18 = Reply telegram header -- TotElements=Amount; -- -- while ((TotElements>0) && (LastError==0)) -- { -- NumElements=TotElements; -- if (NumElements>MaxElements) -- NumElements=MaxElements; -- -- DataSize = NumElements * WordSize; -- IsoSize = Size_WR + DataSize; -- -- // Setup the telegram -- System.arraycopy(S7_RW, 0, PDU, 0, Size_WR); -- // Whole telegram Size -- S7.SetWordAt(PDU,2,IsoSize); -- // Data Length -- Length=DataSize+4; -- S7.SetWordAt(PDU,15,Length); -- // Function -- PDU[17]= (byte) 0x05; -- // Set DB Number -- PDU[27] = (byte) Area; -- if (Area==S7.S7AreaDB) -- S7.SetWordAt(PDU,25,DBNumber); -- -- // Adjusts Start and word length -- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) -- { -- Address = Start; -- Length = DataSize; -- if (Area==S7.S7AreaCT) -- PDU[22]=S7WLCounter; -- else -- PDU[22]=S7WLTimer; -- } -- else -- { -- Address = Start<<3; -- Length = DataSize<<3; -- } -- // Num elements -- S7.SetWordAt(PDU,23,NumElements); -- // Address into the PLC -- PDU[30] = (byte) (Address & 0x0FF); -- Address = Address >> 8; -- PDU[29] = (byte) (Address & 0x0FF); -- Address = Address >> 8; -- PDU[28] = (byte) (Address & 0x0FF); -- // Length -- S7.SetWordAt(PDU,33,Length); -- -- // Copies the Data -- System.arraycopy(Data, Offset, PDU, 35, DataSize); -- -- SendPacket(PDU, IsoSize); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (LastError==0) -- { -- if (Length==22) -- { -- if ((S7.GetWordAt(PDU,17)!=0) || (PDU[21]!=(byte)0xFF)) -- LastError = errS7DataWrite; -- } -- else -- LastError = errS7InvalidPDU; -- } -- } -- -- Offset+=DataSize; -- TotElements -= NumElements; -- Start += NumElements*WordSize; -- } -- return LastError; -- } -- -- public int GetAgBlockInfo(int BlockType, int BlockNumber, S7BlockInfo Block) -- { -- int Length; -- LastError=0; -- // Block Type -- S7_BI[30] = (byte) BlockType; -- // Block Number -- S7_BI[31]=(byte) ((BlockNumber / 10000)+0x30); -- BlockNumber=BlockNumber % 10000; -- S7_BI[32]=(byte) ((BlockNumber / 1000)+0x30); -- BlockNumber=BlockNumber % 1000; -- S7_BI[33]=(byte) ((BlockNumber / 100)+0x30); -- BlockNumber=BlockNumber % 100; -- S7_BI[34]=(byte) ((BlockNumber / 10)+0x30); -- BlockNumber=BlockNumber % 10; -- S7_BI[35]=(byte) ((BlockNumber / 1)+0x30); -- -- SendPacket(S7_BI); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 32) // the minimum expected -- { -- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) -- { -- Block.Update(PDU, 42); -- } -- else -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- -- return LastError; -- } -- /** -- * -- * @param DBNumber DB Number -- * @param Buffer Destination buffer -- * @param SizeRead How many bytes were read -- * @return -- */ -- public int DBGet(int DBNumber, byte[] Buffer, IntByRef SizeRead) -- { -- S7BlockInfo Block = new S7BlockInfo(); -- // Query the DB Length -- LastError = GetAgBlockInfo(S7.Block_DB, DBNumber, Block); -- if (LastError==0) -- { -- int SizeToRead = Block.MC7Size(); -- // Checks the room -- if (SizeToRead<=Buffer.length) -- { -- LastError=ReadArea(S7.S7AreaDB, DBNumber, 0, SizeToRead, Buffer); -- if (LastError==0) -- SizeRead.Value=SizeToRead; -- } -- else -- LastError=errS7BufferTooSmall; -- } -- return LastError; -- } -- -- public int ReadSZL(int ID, int Index, S7Szl SZL) -- { -- int Length; -- int DataSZL; -- int Offset = 0; -- boolean Done = false; -- boolean First = true; -- byte Seq_in =0x00; -- int Seq_out =0x0000; -- -- LastError=0; -- SZL.DataSize=0; -- do -- { -- if (First) -- { -- S7.SetWordAt(S7_SZL_FIRST, 11, ++Seq_out); -- S7.SetWordAt(S7_SZL_FIRST, 29, ID); -- S7.SetWordAt(S7_SZL_FIRST, 31, Index); -- SendPacket(S7_SZL_FIRST); -- } -- else -- { -- S7.SetWordAt(S7_SZL_NEXT, 11, ++Seq_out); -- PDU[24] = (byte)Seq_in; -- SendPacket(S7_SZL_NEXT); -- } -- if (LastError!=0) -- return LastError; -- -- Length=RecvIsoPacket(); -- if (LastError==0) -- { -- if (First) -- { -- if (Length > 32) // the minimum expected -- { -- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) -- { -- // Gets Amount of this slice -- DataSZL=S7.GetWordAt(PDU,31)-8; // Skips extra params (ID, Index ...) -- Done=PDU[26]==0x00; -- Seq_in=(byte)PDU[24]; // Slice sequence -- -- SZL.LENTHDR=S7.GetWordAt(PDU, 37); -- SZL.N_DR=S7.GetWordAt(PDU, 39); -- SZL.Copy(PDU, 41, Offset, DataSZL); -- Offset+=DataSZL; -- SZL.DataSize+=DataSZL; -- } -- else -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- else -- { -- if (Length > 32) // the minimum expected -- { -- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) -- { -- // Gets Amount of this slice -- DataSZL=S7.GetWordAt(PDU,31); -- Done=PDU[26]==0x00; -- Seq_in=(byte)PDU[24]; // Slice sequence -- SZL.Copy(PDU, 37, Offset, DataSZL); -- Offset+=DataSZL; -- SZL.DataSize+=DataSZL; -- } -- else -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- } -- First=false; -- } -- while(!Done && (LastError==0)); -- -- return LastError; -- } -- -- -- public int GetCpuInfo(S7CpuInfo Info) -- { -- S7Szl SZL = new S7Szl(1024); -- -- LastError = ReadSZL(0x001C, 0x0000, SZL); -- if (LastError==0) -- { -- Info.Update(SZL.Data, 0); -- } -- return LastError; -- } -- -- public int GetCpInfo(S7CpInfo Info) -- { -- S7Szl SZL = new S7Szl(1024); -- -- LastError = ReadSZL(0x0131, 0x0001, SZL); -- if (LastError==0) -- { -- Info.Update(SZL.Data, 0); -- } -- return LastError; -- } -- -- public int GetOrderCode(S7OrderCode Code) -- { -- S7Szl SZL = new S7Szl(1024); -- -- LastError = ReadSZL(0x0011, 0x0000, SZL); -- if (LastError==0) -- { -- Code.Update(SZL.Data, 0, SZL.DataSize); -- } -- return LastError; -- } -- -- public int GetPlcDateTime(Date DateTime) -- { -- int Length; -- -- LastError = 0; -- SendPacket(S7_GET_DT); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 30) // the minimum expected -- { -- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) -- { -- DateTime=S7.GetDateAt(PDU, 34); -- } -- else -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- -- return LastError; -- } -- -- public int SetPlcDateTime(Date DateTime) -- { -- int Length; -- -- LastError = 0; -- S7.SetDateAt(S7_SET_DT, 31, DateTime); -- -- SendPacket(S7_SET_DT); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 30) // the minimum expected -- { -- if (S7.GetWordAt(PDU,27)!=0) -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- -- return LastError; -- } -- -- public int SetPlcSystemDateTime() -- { -- return SetPlcDateTime(new Date()); -- } -- -- public int PlcStop() -- { -- int Length; -- -- LastError = 0; -- SendPacket(S7_STOP); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 18) // 18 is the minimum expected -- { -- if (S7.GetWordAt(PDU,17)!=0) -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- return LastError; -- } -- -- public int PlcHotStart() -- { -- int Length; -- -- LastError = 0; -- SendPacket(S7_HOT_START); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 18) // the minimum expected -- { -- if (S7.GetWordAt(PDU,17)!=0) -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- return LastError; -- } -- -- public int PlcColdStart() -- { -- int Length; -- -- LastError = 0; -- SendPacket(S7_COLD_START); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 18) // the minimum expected -- { -- if (S7.GetWordAt(PDU,17)!=0) -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- return LastError; -- } -- -- public int GetPlcStatus(IntByRef Status) -- { -- int Length; -- -- LastError = 0; -- SendPacket(S7_GET_STAT); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 30) // the minimum expected -- { -- if (S7.GetWordAt(PDU,27)==0) -- { -- switch (PDU[44]) -- { -- case S7.S7CpuStatusUnknown : -- case S7.S7CpuStatusRun : -- case S7.S7CpuStatusStop : Status.Value=PDU[44]; -- break; -- default : -- // Since RUN status is always 0x08 for all CPUs and CPs, STOP status -- // sometime can be coded as 0x03 (especially for old cpu...) -- Status.Value=S7.S7CpuStatusStop; -- } -- } -- else -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- return LastError; -- } -- -- public int SetSessionPassword(String Password) -- { -- byte[] pwd = {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; -- int Length; -- -- LastError = 0; -- // Adjusts the Password length to 8 -- if (Password.length()>8) -- Password=Password.substring(0, 8); -- else -- { -- while (Password.length()<8) -- Password=Password+" "; -- } -- -- try { -- pwd = Password.getBytes("UTF-8"); -- } catch (UnsupportedEncodingException ex) { -- LastError = errS7InvalidParams; -- } -- if (LastError==0) -- { -- // Encodes the password -- pwd[0]=(byte) (pwd[0] ^ 0x55); -- pwd[1]=(byte) (pwd[1] ^ 0x55); -- for (int c = 2; c < 8; c++) -- { -- pwd[c]=(byte) (pwd[c] ^ 0x55 ^ pwd[c-2]); -- } -- System.arraycopy(pwd, 0, S7_SET_PWD, 29, 8); -- // Sends the telegrem -- SendPacket(S7_SET_PWD); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 32) // the minimum expected -- { -- if (S7.GetWordAt(PDU,27)!=0) -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- } -- return LastError; -- } -- -- public int ClearSessionPassword() -- { -- int Length; -- -- LastError = 0; -- SendPacket(S7_CLR_PWD); -- if (LastError==0) -- { -- Length=RecvIsoPacket(); -- if (Length > 30) // the minimum expected -- { -- if (S7.GetWordAt(PDU,27)!=0) -- LastError = errS7FunctionError; -- } -- else -- LastError = errS7InvalidPDU; -- } -- return LastError; -- } -- -- public int GetProtection(S7Protection Protection) -- { -- S7Szl SZL = new S7Szl(256); -- -- LastError = ReadSZL(0x0232, 0x0004, SZL); -- if (LastError==0) -- { -- Protection.Update(SZL.Data); -- } -- return LastError; -- } -- --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+package Moka7; -+ -+import java.io.DataInputStream; -+import java.io.DataOutputStream; -+import java.io.IOException; -+import java.io.UnsupportedEncodingException; -+import java.net.InetSocketAddress; -+import java.net.Socket; -+import java.net.SocketAddress; -+import java.util.Date; -+ -+ -+/** -+ * -+ * @author Davide Nardella -+ */ -+public class S7Client -+{ -+ // WordLength -+ public static final int S7WLBit = 0x01; -+ public static final int S7WLByte = 0x02; -+ public static final int S7WLCounter = 0x1C; -+ public static final int S7WLTimer = 0x1D; -+ -+ // Error Codes -+ public static final int errTCPConnectionFailed = 0x0001; -+ public static final int errTCPDataSend = 0x0002; -+ public static final int errTCPDataRecv = 0x0003; -+ public static final int errTCPDataRecvTout = 0x0004; -+ public static final int errTCPConnectionReset = 0x0005; -+ public static final int errISOInvalidPDU = 0x0006; -+ public static final int errISOConnectionFailed = 0x0007; -+ public static final int errISONegotiatingPDU = 0x0008; -+ public static final int errS7InvalidPDU = 0x0009; -+ public static final int errS7DataRead = 0x000A; -+ public static final int errS7DataWrite = 0x000B; -+ public static final int errS7BufferTooSmall = 0x000C; -+ public static final int errS7FunctionError = 0x000D; -+ public static final int errS7InvalidParams = 0x000E; -+ -+ // Public fields -+ public boolean Connected = false; -+ public int LastError = 0; -+ public int RecvTimeout = 2000; -+ -+ // Privates -+ private static final int ISOTCP = 102; // ISOTCP Port -+ private static final int MinPduSize = 16; -+ private static final int DefaultPduSizeRequested = 480; -+ private static final int IsoHSize = 7; // TPKT+COTP Header Size -+ private static final int MaxPduSize = DefaultPduSizeRequested+IsoHSize; -+ -+ private Socket TCPSocket; -+ private final byte[] PDU = new byte[2048]; -+ -+ private DataInputStream InStream = null; -+ private DataOutputStream OutStream = null; -+ -+ private String IPAddress; -+ -+ private byte LocalTSAP_HI; -+ private byte LocalTSAP_LO; -+ private byte RemoteTSAP_HI; -+ private byte RemoteTSAP_LO; -+ private byte LastPDUType; -+ -+ private short ConnType = S7.PG; -+ private int _PDULength = 0; -+ -+ // Telegrams -+ // ISO Connection Request telegram (contains also ISO Header and COTP Header) -+ private static final byte ISO_CR[] = { -+ // TPKT (RFC1006 Header) -+ (byte)0x03, // RFC 1006 ID (3) -+ (byte)0x00, // Reserved, always 0 -+ (byte)0x00, // High part of packet lenght (entire frame, payload and TPDU included) -+ (byte)0x16, // Low part of packet lenght (entire frame, payload and TPDU included) -+ // COTP (ISO 8073 Header) -+ (byte)0x11, // PDU Size Length -+ (byte)0xE0, // CR - Connection Request ID -+ (byte)0x00, // Dst Reference HI -+ (byte)0x00, // Dst Reference LO -+ (byte)0x00, // Src Reference HI -+ (byte)0x01, // Src Reference LO -+ (byte)0x00, // Class + Options Flags -+ (byte)0xC0, // PDU Max Length ID -+ (byte)0x01, // PDU Max Length HI -+ (byte)0x0A, // PDU Max Length LO -+ (byte)0xC1, // Src TSAP Identifier -+ (byte)0x02, // Src TSAP Length (2 bytes) -+ (byte)0x01, // Src TSAP HI (will be overwritten) -+ (byte)0x00, // Src TSAP LO (will be overwritten) -+ (byte)0xC2, // Dst TSAP Identifier -+ (byte)0x02, // Dst TSAP Length (2 bytes) -+ (byte)0x01, // Dst TSAP HI (will be overwritten) -+ (byte)0x02 // Dst TSAP LO (will be overwritten) -+ }; -+ -+ // S7 PDU Negotiation Telegram (contains also ISO Header and COTP Header) -+ private static final byte S7_PN[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x19, -+ (byte)0x02, (byte)0xf0, (byte)0x80, // TPKT + COTP (see above for info) -+ (byte)0x32, (byte)0x01, (byte)0x00, (byte)0x00, -+ (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x08, -+ (byte)0x00, (byte)0x00, (byte)0xf0, (byte)0x00, -+ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01, -+ (byte)0x00, (byte)0x1e // PDU Length Requested = HI-LO 480 bytes -+ }; -+ -+ // S7 Read/Write Request Header (contains also ISO Header and COTP Header) -+ private static final byte S7_RW[] = { // 31-35 bytes -+ (byte)0x03,(byte)0x00, -+ (byte)0x00,(byte)0x1f, // Telegram Length (Data Size + 31 or 35) -+ (byte)0x02,(byte)0xf0, (byte)0x80, // COTP (see above for info) -+ (byte)0x32, // S7 Protocol ID -+ (byte)0x01, // Job Type -+ (byte)0x00,(byte)0x00, // Redundancy identification -+ (byte)0x05,(byte)0x00, // PDU Reference -+ (byte)0x00,(byte)0x0e, // Parameters Length -+ (byte)0x00,(byte)0x00, // Data Length = Size(bytes) + 4 -+ (byte)0x04, // Function 4 Read Var, 5 Write Var -+ (byte)0x01, // Items count -+ (byte)0x12, // Var spec. -+ (byte)0x0a, // Length of remaining bytes -+ (byte)0x10, // Syntax ID -+ S7WLByte, // Transport Size -+ (byte)0x00,(byte)0x00, // Num Elements -+ (byte)0x00,(byte)0x00, // DB Number (if any, else 0) -+ (byte)0x84, // Area Type -+ (byte)0x00,(byte)0x00,(byte)0x00, // Area Offset -+ // WR area -+ (byte)0x00, // Reserved -+ (byte)0x04, // Transport size -+ (byte)0x00,(byte)0x00, // Data Length * 8 (if not timer or counter) -+ }; -+ private static final int Size_RD = 31; -+ private static final int Size_WR = 35; -+ -+ // S7 Get Block Info Request Header (contains also ISO Header and COTP Header) -+ private static final byte S7_BI[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x05, -+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -+ (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12, -+ (byte)0x04, (byte)0x11, (byte)0x43, (byte)0x03, -+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -+ (byte)0x08, (byte)0x30, -+ (byte)0x41, // Block Type -+ (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, // ASCII Block Number -+ (byte)0x41 -+ }; -+ -+ // SZL First telegram request -+ private static final byte S7_SZL_FIRST[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x07, (byte)0x00, (byte)0x00, -+ (byte)0x05, (byte)0x00, // Sequence out -+ (byte)0x00, (byte)0x08, (byte)0x00, -+ (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12, -+ (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01, -+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -+ (byte)0x04, -+ (byte)0x00, (byte)0x00, // ID (29) -+ (byte)0x00, (byte)0x00 // Index (31) -+ }; -+ -+ // SZL Next telegram request -+ private static final byte S7_SZL_NEXT[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x06, -+ (byte)0x00, (byte)0x00, (byte)0x0c, (byte)0x00, -+ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, -+ (byte)0x08, (byte)0x12, (byte)0x44, (byte)0x01, -+ (byte)0x01, // Sequence -+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, -+ (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00 -+ }; -+ -+ // Get Date/Time request -+ private static final byte S7_GET_DT[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x38, -+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -+ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, -+ (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x01, -+ (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, -+ (byte)0x00 -+ }; -+ -+ // Set Date/Time command -+ private static final byte S7_SET_DT[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x89, -+ (byte)0x03, (byte)0x00, (byte)0x08, (byte)0x00, -+ (byte)0x0e, (byte)0x00, (byte)0x01, (byte)0x12, -+ (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x02, -+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -+ (byte)0x0a, (byte)0x00, (byte)0x19, // Hi part of Year -+ (byte)0x13, // Lo part of Year -+ (byte)0x12, // Month -+ (byte)0x06, // Day -+ (byte)0x17, // Hour -+ (byte)0x37, // Min -+ (byte)0x13, // Sec -+ (byte)0x00, (byte)0x01 // ms + Day of week -+ }; -+ -+ // S7 STOP request -+ private static final byte S7_STOP[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0e, -+ (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00, -+ (byte)0x00, (byte)0x29, (byte)0x00, (byte)0x00, -+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, -+ (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52, -+ (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41, -+ (byte)0x4d -+ }; -+ -+ // S7 HOT Start request -+ private static final byte S7_HOT_START[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0c, -+ (byte)0x00, (byte)0x00, (byte)0x14, (byte)0x00, -+ (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00, -+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, -+ (byte)0xfd, (byte)0x00, (byte)0x00, (byte)0x09, -+ (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52, -+ (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41, -+ (byte)0x4d -+ }; -+ -+ // S7 COLD Start request -+ private static final byte S7_COLD_START[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0f, -+ (byte)0x00, (byte)0x00, (byte)0x16, (byte)0x00, -+ (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00, -+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, -+ (byte)0xfd, (byte)0x00, (byte)0x02, (byte)0x43, -+ (byte)0x20, (byte)0x09, (byte)0x50, (byte)0x5f, -+ (byte)0x50, (byte)0x52, (byte)0x4f, (byte)0x47, -+ (byte)0x52, (byte)0x41, (byte)0x4d -+ }; -+ -+ // S7 Get PLC Status -+ private static final byte S7_GET_STAT[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x2c, -+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -+ (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12, -+ (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01, -+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -+ (byte)0x04, (byte)0x04, (byte)0x24, (byte)0x00, -+ (byte)0x00 -+ }; -+ -+ // S7 Set Session Password -+ private static final byte S7_SET_PWD[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x27, -+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -+ (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12, -+ (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x01, -+ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, -+ (byte)0x08, -+ // 8 Char Encoded Password -+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, -+ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 -+ }; -+ -+ // S7 Clear Session Password -+ private static final byte S7_CLR_PWD[] = { -+ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d, -+ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, -+ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x29, -+ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, -+ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, -+ (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x02, -+ (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, -+ (byte)0x00 -+ }; -+ -+ public S7Client() -+ { -+ // Placeholder for future implementations -+ } -+ -+ public static String ErrorText(int Error) -+ { -+ switch (Error) -+ { -+ case errTCPConnectionFailed : -+ return "TCP Connection failed."; -+ case errTCPDataSend : -+ return "TCP Sending error."; -+ case errTCPDataRecv : -+ return "TCP Receiving error."; -+ case errTCPDataRecvTout : -+ return "Data Receiving timeout."; -+ case errTCPConnectionReset : -+ return "Connection reset by the peer."; -+ case errISOInvalidPDU : -+ return "Invalid ISO PDU received."; -+ case errISOConnectionFailed : -+ return "ISO connection refused by the CPU."; -+ case errISONegotiatingPDU : -+ return "ISO error negotiating the PDU length."; -+ case errS7InvalidPDU : -+ return "Invalid S7 PDU received."; -+ case errS7DataRead : -+ return "S7 Error reading data from the CPU."; -+ case errS7DataWrite : -+ return "S7 Error writing data to the CPU."; -+ case errS7BufferTooSmall : -+ return "The Buffer supplied to the function is too small."; -+ case errS7FunctionError : -+ return "S7 function refused by the CPU."; -+ case errS7InvalidParams : -+ return "Invalid parameters supplied to the function."; -+ default : -+ return "Unknown error : 0x"+Integer.toHexString(Error); -+ } -+ } -+ -+ private int TCPConnect() -+ { -+ SocketAddress sockaddr = new InetSocketAddress(IPAddress, ISOTCP); -+ LastError=0; -+ try { -+ TCPSocket = new Socket(); -+ TCPSocket.connect(sockaddr ,5000); -+ TCPSocket.setTcpNoDelay(true); -+ InStream = new DataInputStream(TCPSocket.getInputStream()); -+ OutStream = new DataOutputStream(TCPSocket.getOutputStream()); -+ } -+ catch (IOException e) { -+ LastError=errTCPConnectionFailed; -+ } -+ return LastError; -+ } -+ -+ private int WaitForData(int Size, int Timeout) -+ { -+ int cnt = 0; -+ LastError=0; -+ int SizeAvail; -+ boolean Expired = false; -+ try -+ { -+ SizeAvail=InStream.available(); -+ while ((SizeAvailTimeout; -+ // If timeout we clean the buffer -+ if (Expired && (SizeAvail>0) && (LastError==0)) -+ InStream.read(PDU, 0, SizeAvail); -+ } -+ } -+ catch (IOException ex) -+ { -+ LastError=errTCPDataRecvTout; -+ } -+ if (cnt>=Timeout) -+ { -+ LastError=errTCPDataRecvTout; -+ } -+ return LastError; -+ } -+ -+ private int RecvPacket(byte[] Buffer, int Start, int Size) -+ { -+ int BytesRead=0; -+ LastError=WaitForData(Size,RecvTimeout); -+ if (LastError==0) -+ { -+ try { -+ BytesRead = InStream.read(Buffer, Start, Size); -+ } catch (IOException ex) { -+ LastError=errTCPDataRecv; -+ } -+ if (BytesRead==0) -+ LastError=errTCPConnectionReset; -+ } -+ return LastError; -+ } -+ -+ private void SendPacket(byte[] Buffer, int Len) -+ { -+ LastError = 0; -+ try { -+ OutStream.write(Buffer,0,Len); -+ OutStream.flush(); -+ } catch (IOException ex) { -+ LastError = errTCPDataSend; -+ } -+ } -+ private void SendPacket(byte[] Buffer) -+ { -+ SendPacket(Buffer,Buffer.length); -+ } -+ -+ private int RecvIsoPacket() -+ { -+ Boolean Done = false; -+ int Size = 0; -+ while ((LastError==0) && !Done) -+ { -+ // Get TPKT (4 bytes) -+ RecvPacket(PDU, 0, 4); -+ if (LastError==0) -+ { -+ Size=S7.GetWordAt(PDU,2); -+ // Check 0 bytes Data Packet (only TPKT+COTP = 7 bytes) -+ if (Size==IsoHSize) -+ RecvPacket(PDU,4, 3); // Skip remaining 3 bytes and Done is still false -+ else -+ { -+ if ((Size>MaxPduSize) || (Size16 && <247 -+ } -+ } -+ } -+ if (LastError==0) -+ { -+ RecvPacket(PDU,4, 3); // Skip remaining 3 COTP bytes -+ LastPDUType=PDU[5]; // Stores PDU Type, we need it -+ // Receives the S7 Payload -+ RecvPacket(PDU, 7, Size-IsoHSize); -+ } -+ if (LastError==0) -+ return Size; -+ else -+ return 0; -+ } -+ -+ private int ISOConnect() -+ { -+ int Size; -+ ISO_CR[16]=LocalTSAP_HI; -+ ISO_CR[17]=LocalTSAP_LO; -+ ISO_CR[20]=RemoteTSAP_HI; -+ ISO_CR[21]=RemoteTSAP_LO; -+ -+ // Sends the connection request telegram -+ SendPacket(ISO_CR); -+ if (LastError==0) -+ { -+ // Gets the reply (if any) -+ Size=RecvIsoPacket(); -+ if (LastError==0) -+ { -+ if (Size==22) -+ { -+ if (LastPDUType!=(byte)0xD0) // 0xD0 = CC Connection confirm -+ LastError=errISOConnectionFailed; -+ } -+ else -+ LastError=errISOInvalidPDU; -+ } -+ } -+ return LastError; -+ } -+ -+ private int NegotiatePduLength() -+ { -+ int Length; -+ // Set PDU Size Requested -+ S7.SetWordAt(S7_PN,23,DefaultPduSizeRequested); -+ // Sends the connection request telegram -+ SendPacket(S7_PN); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (LastError==0) -+ { -+ // check S7 Error -+ if ((Length==27) && (PDU[17]==0) && (PDU[18]==0)) // 20 = size of Negotiate Answer -+ { -+ // Get PDU Size Negotiated -+ _PDULength = S7.GetWordAt(PDU,25); -+ if (_PDULength>0) -+ return 0; -+ else -+ LastError=errISONegotiatingPDU; -+ } -+ else -+ LastError=errISONegotiatingPDU; -+ } -+ } -+ return LastError; -+ } -+ -+ public void SetConnectionType(short ConnectionType) -+ { -+ ConnType=ConnectionType; -+ } -+ -+ public int Connect() -+ { -+ LastError=0; -+ if (!Connected) -+ { -+ TCPConnect(); -+ if (LastError==0) // First stage : TCP Connection -+ { -+ ISOConnect(); -+ if (LastError==0) // Second stage : ISOTCP (ISO 8073) Connection -+ { -+ LastError=NegotiatePduLength(); // Third stage : S7 PDU negotiation -+ } -+ } -+ } -+ Connected=LastError==0; -+ -+ // In case the connection is not completely established (TCP connection + ISO connection + PDU negotiation) -+ // we close the socket and its IO streams to revert the object back to pre-Connect() state -+ if (!Connected) -+ { -+ if (TCPSocket != null) { -+ try { -+ TCPSocket.close(); -+ } catch (IOException ex) { -+ } -+ } -+ if (InStream != null) { -+ try { -+ InStream.close(); -+ } catch (IOException ex) { -+ } -+ } -+ if (OutStream != null) { -+ try { -+ OutStream.close(); -+ } catch (IOException ex) { -+ } -+ } -+ _PDULength = 0; -+ } -+ -+ return LastError; -+ } -+ -+ public void Disconnect() -+ { -+ if (Connected) -+ { -+ try { -+ OutStream.close(); -+ InStream.close(); -+ TCPSocket.close(); -+ _PDULength=0; -+ } catch (IOException ex) { -+ } -+ Connected=false; -+ } -+ } -+ -+ public int ConnectTo(String Address, int Rack, int Slot) -+ { -+ int RemoteTSAP=(ConnType<<8)+ (Rack * 0x20) + Slot; -+ SetConnectionParams(Address, 0x0100, RemoteTSAP); -+ return Connect(); -+ } -+ -+ public int PDULength() -+ { -+ return _PDULength; -+ } -+ -+ public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP) -+ { -+ int LocTSAP = LocalTSAP & 0x0000FFFF; -+ int RemTSAP = RemoteTSAP & 0x0000FFFF; -+ IPAddress = Address; -+ LocalTSAP_HI = (byte) (LocTSAP>>8); -+ LocalTSAP_LO = (byte) (LocTSAP & 0x00FF); -+ RemoteTSAP_HI= (byte) (RemTSAP>>8); -+ RemoteTSAP_LO= (byte) (RemTSAP & 0x00FF); -+ } -+ -+ public int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) -+ { -+ int Address; -+ int NumElements; -+ int MaxElements; -+ int TotElements; -+ int SizeRequested; -+ int Length; -+ int Offset = 0; -+ byte WordSize = 1; -+ -+ LastError=0; -+ -+ // If we are addressing Timers or counters the element size is 2 -+ if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) -+ WordSize = 2; -+ -+ MaxElements=(_PDULength-18) / WordSize; // 18 = Reply telegram header -+ TotElements=Amount; -+ -+ while ((TotElements>0) && (LastError==0)) -+ { -+ NumElements=TotElements; -+ if (NumElements>MaxElements) -+ NumElements=MaxElements; -+ -+ SizeRequested = NumElements * WordSize; -+ -+ // Setup the telegram -+ System.arraycopy(S7_RW, 0, PDU, 0, Size_RD); -+ // Set DB Number -+ PDU[27] = (byte) Area; -+ // Set Area -+ if (Area==S7.S7AreaDB) -+ S7.SetWordAt(PDU,25,DBNumber); -+ -+ PDU[22] = (byte) WordLength; -+ // Adjusts Start and word length -+ if ((WordLength==S7WLBit) || (WordLength==S7WLTimer) || (WordLength==S7WLCounter)) -+ { -+ Address = Start; -+ } -+ else -+ { -+ Address = Start<<3; -+ } -+ -+ // Num elements -+ S7.SetWordAt(PDU,23,NumElements); -+ -+ // Address into the PLC (only 3 bytes) -+ PDU[30] = (byte) (Address & 0x0FF); -+ Address = Address >> 8; -+ PDU[29] = (byte) (Address & 0x0FF); -+ Address = Address >> 8; -+ PDU[28] = (byte) (Address & 0x0FF); -+ -+ // Transport Size -+ PDU[32] = 0x04; -+ if (WordLength==S7WLBit) -+ { -+ PDU[32] = 0x03; -+ } -+ else if ((WordLength==S7WLTimer) || (WordLength==S7WLCounter)) -+ { -+ PDU[32] = 0x09; -+ } -+ -+ SendPacket(PDU, Size_RD); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (LastError==0) -+ { -+ if (Length>=25) -+ { -+ if ((Length-25==SizeRequested) && (PDU[21]==(byte)0xFF)) -+ { -+ System.arraycopy(PDU, 25, Data, Offset, SizeRequested); -+ Offset+=SizeRequested; -+ } -+ else -+ LastError = errS7DataRead; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ } -+ -+ TotElements -= NumElements; -+ Start += NumElements*WordSize; -+ } -+ return LastError; -+ } -+ -+ public int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) -+ { -+ int Address; -+ int NumElements; -+ int MaxElements; -+ int TotElements; -+ int DataSize; -+ int IsoSize; -+ int Length; -+ int Offset = 0; -+ byte WordSize = 1; -+ -+ LastError=0; -+ -+ // If we are addressing Timers or counters the element size is 2 -+ if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) -+ WordSize = 2; -+ -+ MaxElements=(_PDULength-35) / WordSize; // 35 = Reply telegram header -+ TotElements=Amount; -+ -+ while ((TotElements>0) && (LastError==0)) -+ { -+ NumElements=TotElements; -+ if (NumElements>MaxElements) -+ NumElements=MaxElements; -+ -+ DataSize = NumElements * WordSize; -+ IsoSize = Size_WR + DataSize; -+ -+ // Setup the telegram -+ System.arraycopy(S7_RW, 0, PDU, 0, Size_WR); -+ // Whole telegram Size -+ S7.SetWordAt(PDU,2,IsoSize); -+ // Data Length -+ Length=DataSize+4; -+ S7.SetWordAt(PDU,15,Length); -+ // Function -+ PDU[17]= (byte) 0x05; -+ // Set DB Number -+ PDU[27] = (byte) Area; -+ if (Area==S7.S7AreaDB) -+ S7.SetWordAt(PDU,25,DBNumber); -+ -+ PDU[22] = (byte) WordLength; -+ // Adjusts Start and word length -+ if ((WordLength==S7WLBit) || (WordLength==S7WLTimer) || (WordLength==S7WLCounter)) -+ { -+ Address = Start; -+ Length = DataSize; -+ } -+ else -+ { -+ Address = Start<<3; -+ Length = DataSize<<3; -+ } -+ -+ // Num elements -+ S7.SetWordAt(PDU,23,NumElements); -+ // Address into the PLC -+ PDU[30] = (byte) (Address & 0x0FF); -+ Address = Address >> 8; -+ PDU[29] = (byte) (Address & 0x0FF); -+ Address = Address >> 8; -+ PDU[28] = (byte) (Address & 0x0FF); -+ -+ // Transport Size -+ PDU[32] = 0x04; -+ if (WordLength==S7WLBit) -+ { -+ PDU[32] = 0x03; -+ } -+ else if ((WordLength==S7WLTimer) || (WordLength==S7WLCounter)) -+ { -+ PDU[32] = 0x09; -+ } -+ -+ // Length -+ S7.SetWordAt(PDU,33,Length); -+ -+ // Copies the Data -+ System.arraycopy(Data, Offset, PDU, 35, DataSize); -+ -+ SendPacket(PDU, IsoSize); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (LastError==0) -+ { -+ if (Length==22) -+ { -+ if ((S7.GetWordAt(PDU,17)!=0) || (PDU[21]!=(byte)0xFF)) -+ LastError = errS7DataWrite; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ } -+ -+ Offset+=DataSize; -+ TotElements -= NumElements; -+ Start += NumElements*WordSize; -+ } -+ return LastError; -+ } -+ -+ public int GetAgBlockInfo(int BlockType, int BlockNumber, S7BlockInfo Block) -+ { -+ int Length; -+ LastError=0; -+ // Block Type -+ S7_BI[30] = (byte) BlockType; -+ // Block Number -+ S7_BI[31]=(byte) ((BlockNumber / 10000)+0x30); -+ BlockNumber=BlockNumber % 10000; -+ S7_BI[32]=(byte) ((BlockNumber / 1000)+0x30); -+ BlockNumber=BlockNumber % 1000; -+ S7_BI[33]=(byte) ((BlockNumber / 100)+0x30); -+ BlockNumber=BlockNumber % 100; -+ S7_BI[34]=(byte) ((BlockNumber / 10)+0x30); -+ BlockNumber=BlockNumber % 10; -+ S7_BI[35]=(byte) ((BlockNumber / 1)+0x30); -+ -+ SendPacket(S7_BI); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 32) // the minimum expected -+ { -+ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) -+ { -+ Block.Update(PDU, 42); -+ } -+ else -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ -+ return LastError; -+ } -+ /** -+ * -+ * @param DBNumber DB Number -+ * @param Buffer Destination buffer -+ * @param SizeRead How many bytes were read -+ * @return -+ */ -+ public int DBGet(int DBNumber, byte[] Buffer, IntByRef SizeRead) -+ { -+ S7BlockInfo Block = new S7BlockInfo(); -+ // Query the DB Length -+ LastError = GetAgBlockInfo(S7.Block_DB, DBNumber, Block); -+ if (LastError==0) -+ { -+ int SizeToRead = Block.MC7Size(); -+ // Checks the room -+ if (SizeToRead<=Buffer.length) -+ { -+ LastError=ReadArea(S7.S7AreaDB, DBNumber, 0, SizeToRead, S7WLByte, Buffer); -+ if (LastError==0) -+ SizeRead.Value=SizeToRead; -+ } -+ else -+ LastError=errS7BufferTooSmall; -+ } -+ return LastError; -+ } -+ -+ public int ReadSZL(int ID, int Index, S7Szl SZL) -+ { -+ int Length; -+ int DataSZL; -+ int Offset = 0; -+ boolean Done = false; -+ boolean First = true; -+ byte Seq_in =0x00; -+ int Seq_out =0x0000; -+ -+ LastError=0; -+ SZL.DataSize=0; -+ do -+ { -+ if (First) -+ { -+ S7.SetWordAt(S7_SZL_FIRST, 11, ++Seq_out); -+ S7.SetWordAt(S7_SZL_FIRST, 29, ID); -+ S7.SetWordAt(S7_SZL_FIRST, 31, Index); -+ SendPacket(S7_SZL_FIRST); -+ } -+ else -+ { -+ S7.SetWordAt(S7_SZL_NEXT, 11, ++Seq_out); -+ PDU[24] = (byte)Seq_in; -+ SendPacket(S7_SZL_NEXT); -+ } -+ if (LastError!=0) -+ return LastError; -+ -+ Length=RecvIsoPacket(); -+ if (LastError==0) -+ { -+ if (First) -+ { -+ if (Length > 32) // the minimum expected -+ { -+ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) -+ { -+ // Gets Amount of this slice -+ DataSZL=S7.GetWordAt(PDU,31)-8; // Skips extra params (ID, Index ...) -+ Done=PDU[26]==0x00; -+ Seq_in=(byte)PDU[24]; // Slice sequence -+ -+ SZL.LENTHDR=S7.GetWordAt(PDU, 37); -+ SZL.N_DR=S7.GetWordAt(PDU, 39); -+ SZL.Copy(PDU, 41, Offset, DataSZL); -+ Offset+=DataSZL; -+ SZL.DataSize+=DataSZL; -+ } -+ else -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ else -+ { -+ if (Length > 32) // the minimum expected -+ { -+ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) -+ { -+ // Gets Amount of this slice -+ DataSZL=S7.GetWordAt(PDU,31); -+ Done=PDU[26]==0x00; -+ Seq_in=(byte)PDU[24]; // Slice sequence -+ SZL.Copy(PDU, 37, Offset, DataSZL); -+ Offset+=DataSZL; -+ SZL.DataSize+=DataSZL; -+ } -+ else -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ } -+ First=false; -+ } -+ while(!Done && (LastError==0)); -+ -+ return LastError; -+ } -+ -+ public int GetCpuInfo(S7CpuInfo Info) -+ { -+ S7Szl SZL = new S7Szl(1024); -+ -+ LastError = ReadSZL(0x001C, 0x0000, SZL); -+ if (LastError==0) -+ { -+ Info.Update(SZL.Data, 0); -+ } -+ return LastError; -+ } -+ -+ public int GetCpInfo(S7CpInfo Info) -+ { -+ S7Szl SZL = new S7Szl(1024); -+ -+ LastError = ReadSZL(0x0131, 0x0001, SZL); -+ if (LastError==0) -+ { -+ Info.Update(SZL.Data, 0); -+ } -+ return LastError; -+ } -+ -+ public int GetOrderCode(S7OrderCode Code) -+ { -+ S7Szl SZL = new S7Szl(1024); -+ -+ LastError = ReadSZL(0x0011, 0x0000, SZL); -+ if (LastError==0) -+ { -+ Code.Update(SZL.Data, 0, SZL.DataSize); -+ } -+ return LastError; -+ } -+ -+ public int GetPlcDateTime(Date DateTime) -+ { -+ int Length; -+ -+ LastError = 0; -+ SendPacket(S7_GET_DT); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 30) // the minimum expected -+ { -+ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) -+ { -+ DateTime=S7.GetDateAt(PDU, 34); -+ } -+ else -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ -+ return LastError; -+ } -+ -+ public int SetPlcDateTime(Date DateTime) -+ { -+ int Length; -+ -+ LastError = 0; -+ S7.SetDateAt(S7_SET_DT, 31, DateTime); -+ -+ SendPacket(S7_SET_DT); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 30) // the minimum expected -+ { -+ if (S7.GetWordAt(PDU,27)!=0) -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ -+ return LastError; -+ } -+ -+ public int SetPlcSystemDateTime() -+ { -+ return SetPlcDateTime(new Date()); -+ } -+ -+ public int PlcStop() -+ { -+ int Length; -+ -+ LastError = 0; -+ SendPacket(S7_STOP); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 18) // 18 is the minimum expected -+ { -+ if (S7.GetWordAt(PDU,17)!=0) -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ return LastError; -+ } -+ -+ public int PlcHotStart() -+ { -+ int Length; -+ -+ LastError = 0; -+ SendPacket(S7_HOT_START); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 18) // the minimum expected -+ { -+ if (S7.GetWordAt(PDU,17)!=0) -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ return LastError; -+ } -+ -+ public int PlcColdStart() -+ { -+ int Length; -+ -+ LastError = 0; -+ SendPacket(S7_COLD_START); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 18) // the minimum expected -+ { -+ if (S7.GetWordAt(PDU,17)!=0) -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ return LastError; -+ } -+ -+ public int GetPlcStatus(IntByRef Status) -+ { -+ int Length; -+ -+ LastError = 0; -+ SendPacket(S7_GET_STAT); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 30) // the minimum expected -+ { -+ if (S7.GetWordAt(PDU,27)==0) -+ { -+ switch (PDU[44]) -+ { -+ case S7.S7CpuStatusUnknown : -+ case S7.S7CpuStatusRun : -+ case S7.S7CpuStatusStop : Status.Value=PDU[44]; -+ break; -+ default : -+ // Since RUN status is always 0x08 for all CPUs and CPs, STOP status -+ // sometime can be coded as 0x03 (especially for old cpu...) -+ Status.Value=S7.S7CpuStatusStop; -+ } -+ } -+ else -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ return LastError; -+ } -+ -+ public int SetSessionPassword(String Password) -+ { -+ byte[] pwd = {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; -+ int Length; -+ -+ LastError = 0; -+ // Adjusts the Password length to 8 -+ if (Password.length()>8) -+ Password=Password.substring(0, 8); -+ else -+ { -+ while (Password.length()<8) -+ Password=Password+" "; -+ } -+ -+ try { -+ pwd = Password.getBytes("UTF-8"); -+ } catch (UnsupportedEncodingException ex) { -+ LastError = errS7InvalidParams; -+ } -+ if (LastError==0) -+ { -+ // Encodes the password -+ pwd[0]=(byte) (pwd[0] ^ 0x55); -+ pwd[1]=(byte) (pwd[1] ^ 0x55); -+ for (int c = 2; c < 8; c++) -+ { -+ pwd[c]=(byte) (pwd[c] ^ 0x55 ^ pwd[c-2]); -+ } -+ System.arraycopy(pwd, 0, S7_SET_PWD, 29, 8); -+ // Sends the telegrem -+ SendPacket(S7_SET_PWD); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 32) // the minimum expected -+ { -+ if (S7.GetWordAt(PDU,27)!=0) -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ } -+ return LastError; -+ } -+ -+ public int ClearSessionPassword() -+ { -+ int Length; -+ -+ LastError = 0; -+ SendPacket(S7_CLR_PWD); -+ if (LastError==0) -+ { -+ Length=RecvIsoPacket(); -+ if (Length > 30) // the minimum expected -+ { -+ if (S7.GetWordAt(PDU,27)!=0) -+ LastError = errS7FunctionError; -+ } -+ else -+ LastError = errS7InvalidPDU; -+ } -+ return LastError; -+ } -+ -+ public int GetProtection(S7Protection Protection) -+ { -+ S7Szl SZL = new S7Szl(256); -+ -+ LastError = ReadSZL(0x0232, 0x0004, SZL); -+ if (LastError==0) -+ { -+ Protection.Update(SZL.Data); -+ } -+ return LastError; -+ } -+ -+} -diff U3 S7CpInfo.java S7CpInfo.java ---- S7CpInfo.java Thu Mar 23 15:34:52 2017 -+++ S7CpInfo.java Tue Aug 08 18:53:37 2017 -@@ -1,41 +1,41 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ --package Moka7; -- --/** -- * -- * @author Davide -- */ --public class S7CpInfo { -- -- public int MaxPduLength; -- public int MaxConnections; -- public int MaxMpiRate; -- public int MaxBusRate; -- -- protected void Update(byte[] Src, int Pos) -- { -- MaxPduLength = S7.GetShortAt(Src, 2); -- MaxConnections = S7.GetShortAt(Src, 4); -- MaxMpiRate = S7.GetDIntAt(Src, 6); -- MaxBusRate = S7.GetDIntAt(Src, 10); -- } --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+package Moka7; -+ -+/** -+ * -+ * @author Davide Nardella -+ */ -+public class S7CpInfo { -+ -+ public int MaxPduLength; -+ public int MaxConnections; -+ public int MaxMpiRate; -+ public int MaxBusRate; -+ -+ protected void Update(byte[] Src, int Pos) -+ { -+ MaxPduLength = S7.GetShortAt(Src, 2); -+ MaxConnections = S7.GetShortAt(Src, 4); -+ MaxMpiRate = S7.GetDIntAt(Src, 6); -+ MaxBusRate = S7.GetDIntAt(Src, 10); -+ } -+} -diff U3 S7CpuInfo.java S7CpuInfo.java ---- S7CpuInfo.java Thu Mar 23 15:34:52 2017 -+++ S7CpuInfo.java Tue Aug 08 18:53:37 2017 -@@ -1,57 +1,57 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ --package Moka7; -- --/** -- * -- * @author Davide -- */ --public class S7CpuInfo { -- -- private final int BufSize = 256; -- protected byte[] Buffer = new byte[BufSize]; -- -- protected void Update(byte[] Src, int Pos) -- { -- System.arraycopy(Src, Pos, Buffer, 0, BufSize); -- } -- -- public String ModuleTypeName() -- { -- return S7.GetStringAt(Buffer,172,32); -- } -- public String SerialNumber() -- { -- return S7.GetStringAt(Buffer,138,24); -- } -- public String ASName() -- { -- return S7.GetStringAt(Buffer,2,24); -- } -- public String Copyright() -- { -- return S7.GetStringAt(Buffer,104,26); -- } -- public String ModuleName() -- { -- return S7.GetStringAt(Buffer,36,24); -- } --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+package Moka7; -+ -+/** -+ * -+ * @author Davide Nardella -+ */ -+public class S7CpuInfo { -+ -+ private final int BufSize = 256; -+ protected byte[] Buffer = new byte[BufSize]; -+ -+ protected void Update(byte[] Src, int Pos) -+ { -+ System.arraycopy(Src, Pos, Buffer, 0, BufSize); -+ } -+ -+ public String ModuleTypeName() -+ { -+ return S7.GetStringAt(Buffer,172,32); -+ } -+ public String SerialNumber() -+ { -+ return S7.GetStringAt(Buffer,138,24); -+ } -+ public String ASName() -+ { -+ return S7.GetStringAt(Buffer,2,24); -+ } -+ public String Copyright() -+ { -+ return S7.GetStringAt(Buffer,104,26); -+ } -+ public String ModuleName() -+ { -+ return S7.GetStringAt(Buffer,36,24); -+ } -+} -diff U3 S7OrderCode.java S7OrderCode.java ---- S7OrderCode.java Thu Mar 23 15:34:52 2017 -+++ S7OrderCode.java Tue Aug 08 18:53:37 2017 -@@ -1,46 +1,46 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ --package Moka7; -- --/** -- * -- * @author Davide -- */ --public class S7OrderCode { -- -- public int V1; -- public int V2; -- public int V3; -- protected byte[] Buffer = new byte[1024]; -- -- protected void Update(byte[] Src, int Pos, int Size) -- { -- System.arraycopy(Src, Pos, Buffer, 0, Size); -- V1 = (byte) Src[Size-3]; -- V2 = (byte) Src[Size-2]; -- V3 = (byte) Src[Size-1]; -- } -- -- public String Code() -- { -- return S7.GetStringAt(Buffer, 2, 20); -- } --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+package Moka7; -+ -+/** -+ * -+ * @author Davide Nardella -+ */ -+public class S7OrderCode { -+ -+ public int V1; -+ public int V2; -+ public int V3; -+ protected byte[] Buffer = new byte[1024]; -+ -+ protected void Update(byte[] Src, int Pos, int Size) -+ { -+ System.arraycopy(Src, Pos, Buffer, 0, Size); -+ V1 = (byte) Src[Size-3]; -+ V2 = (byte) Src[Size-2]; -+ V3 = (byte) Src[Size-1]; -+ } -+ -+ public String Code() -+ { -+ return S7.GetStringAt(Buffer, 2, 20); -+ } -+} -diff U3 S7Protection.java S7Protection.java ---- S7Protection.java Thu Mar 23 15:34:52 2017 -+++ S7Protection.java Tue Aug 08 18:53:37 2017 -@@ -1,38 +1,43 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ --package Moka7; -- --// See §33.19 of "System Software for S7-300/400 System and Standard Functions" --public class S7Protection { -- public int sch_schal; -- public int sch_par; -- public int sch_rel; -- public int bart_sch; -- public int anl_sch; -- protected void Update(byte[] Src) -- { -- sch_schal = S7.GetWordAt(Src,2); -- sch_par = S7.GetWordAt(Src,4); -- sch_rel = S7.GetWordAt(Src,6); -- bart_sch = S7.GetWordAt(Src,8); -- anl_sch = S7.GetWordAt(Src,10); -- } --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+package Moka7; -+ -+/** -+ * -+ * @author Davide Nardella -+ */ -+ -+// See §33.19 of "System Software for S7-300/400 System and Standard Functions" -+public class S7Protection { -+ public int sch_schal; -+ public int sch_par; -+ public int sch_rel; -+ public int bart_sch; -+ public int anl_sch; -+ protected void Update(byte[] Src) -+ { -+ sch_schal = S7.GetWordAt(Src,2); -+ sch_par = S7.GetWordAt(Src,4); -+ sch_rel = S7.GetWordAt(Src,6); -+ bart_sch = S7.GetWordAt(Src,8); -+ anl_sch = S7.GetWordAt(Src,10); -+ } -+} -diff U3 S7Szl.java S7Szl.java ---- S7Szl.java Thu Mar 23 15:34:52 2017 -+++ S7Szl.java Tue Aug 08 18:53:37 2017 -@@ -1,42 +1,42 @@ --/*=============================================================================| --| PROJECT Moka7 1.0.2 | --|==============================================================================| --| Copyright (C) 2013, 2016 Davide Nardella | --| All rights reserved. | --|==============================================================================| --| SNAP7 is free software: you can redistribute it and/or modify | --| it under the terms of the Lesser GNU General Public License as published by | --| the Free Software Foundation, either version 3 of the License, or under | --| EPL Eclipse Public License 1.0. | --| | --| This means that you have to chose in advance which take before you import | --| the library into your project. | --| | --| SNAP7 is distributed in the hope that it will be useful, | --| but WITHOUT ANY WARRANTY; without even the implied warranty of | --| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | --| decide to adopt. | --| | --|=============================================================================*/ --package Moka7; -- --/** -- * -- * @author Davide -- */ --public class S7Szl { -- -- public int LENTHDR; -- public int N_DR; -- public int DataSize; -- public byte Data[]; -- -- public S7Szl(int BufferSize) -- { -- Data = new byte[BufferSize]; -- } -- protected void Copy(byte[] Src, int SrcPos, int DestPos, int Size) -- { -- System.arraycopy(Src, SrcPos, Data, DestPos, Size); -- } --} -+/*=============================================================================| -+| PROJECT Moka7 1.0.2 | -+|==============================================================================| -+| Copyright (C) 2013, 2016 Davide Nardella | -+| All rights reserved. | -+|==============================================================================| -+| SNAP7 is free software: you can redistribute it and/or modify | -+| it under the terms of the Lesser GNU General Public License as published by | -+| the Free Software Foundation, either version 3 of the License, or under | -+| EPL Eclipse Public License 1.0. | -+| | -+| This means that you have to chose in advance which take before you import | -+| the library into your project. | -+| | -+| SNAP7 is distributed in the hope that it will be useful, | -+| but WITHOUT ANY WARRANTY; without even the implied warranty of | -+| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | -+| decide to adopt. | -+| | -+|=============================================================================*/ -+package Moka7; -+ -+/** -+ * -+ * @author Davide Nardella -+ */ -+public class S7Szl { -+ -+ public int LENTHDR; -+ public int N_DR; -+ public int DataSize; -+ public byte Data[]; -+ -+ public S7Szl(int BufferSize) -+ { -+ Data = new byte[BufferSize]; -+ } -+ protected void Copy(byte[] Src, int SrcPos, int DestPos, int Size) -+ { -+ System.arraycopy(Src, SrcPos, Data, DestPos, Size); -+ } -+} +diff U3 IntByRef.java IntByRef.java +--- IntByRef.java Thu Mar 23 15:34:52 2017 ++++ IntByRef.java Tue Aug 08 18:53:37 2017 +@@ -1,40 +1,40 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +- +-package Moka7; +- +-/** +- * Quick class to pass an integer by reference +- * @author Davide +- */ +- +-public class IntByRef { +- +- public IntByRef(int Val) +- { +- this.Value=Val; +- } +- public IntByRef() +- { +- this.Value=0; +- } +- public int Value; +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++ ++package Moka7; ++ ++/** ++ * Quick class to pass an integer by reference ++ * @author Davide Nardella ++ */ ++ ++public class IntByRef { ++ ++ public IntByRef(int Val) ++ { ++ this.Value=Val; ++ } ++ public IntByRef() ++ { ++ this.Value=0; ++ } ++ public int Value; ++} +diff U3 S7.java S7.java +--- S7.java Thu Mar 23 15:34:52 2017 ++++ S7.java Tue Aug 08 18:53:37 2017 +@@ -1,287 +1,287 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +-package Moka7; +- +-import java.io.UnsupportedEncodingException; +-import java.util.Date; +-import java.util.Calendar; +- +-/** +- * +- * @author Davide +- */ +- +- +-// Step 7 Constants and Conversion helper class +-public class S7 { +- // S7 ID Area (Area that we want to read/write) +- public static final int S7AreaPE = 0x81; +- public static final int S7AreaPA = 0x82; +- public static final int S7AreaMK = 0x83; +- public static final int S7AreaDB = 0x84; +- public static final int S7AreaCT = 0x1C; +- public static final int S7AreaTM = 0x1D; +- // Connection types +- public static final byte PG = 0x01; +- public static final byte OP = 0x02; +- public static final byte S7_BASIC = 0x03; +- // Block type +- public static final int Block_OB = 0x38; +- public static final int Block_DB = 0x41; +- public static final int Block_SDB = 0x42; +- public static final int Block_FC = 0x43; +- public static final int Block_SFC = 0x44; +- public static final int Block_FB = 0x45; +- public static final int Block_SFB = 0x46; +- // Sub Block Type +- public static final int SubBlk_OB = 0x08; +- public static final int SubBlk_DB = 0x0A; +- public static final int SubBlk_SDB = 0x0B; +- public static final int SubBlk_FC = 0x0C; +- public static final int SubBlk_SFC = 0x0D; +- public static final int SubBlk_FB = 0x0E; +- public static final int SubBlk_SFB = 0x0F; +- // Block languages +- public static final int BlockLangAWL = 0x01; +- public static final int BlockLangKOP = 0x02; +- public static final int BlockLangFUP = 0x03; +- public static final int BlockLangSCL = 0x04; +- public static final int BlockLangDB = 0x05; +- public static final int BlockLangGRAPH = 0x06; +- // PLC Status +- public static final int S7CpuStatusUnknown = 0x00; +- public static final int S7CpuStatusRun = 0x08; +- public static final int S7CpuStatusStop = 0x04; +- // Type Var +- public static final int S7TypeBool = 1; +- public static final int S7TypeInt = 1; +- +- // Returns the bit at Pos.Bit +- public static boolean GetBitAt(byte[] Buffer, int Pos, int Bit) +- { +- int Value = Buffer[Pos] & 0x0FF; +- byte[] Mask = { +- (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08, +- (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80 +- }; +- if (Bit<0) Bit=0; +- if (Bit>7) Bit=7; +- +- return (Value & Mask[Bit])!=0; +- } +- /** +- * Returns a 16 bit unsigned value : from 0 to 65535 (2^16-1) +- * @param Buffer +- * @param Pos start position +- * @return +- */ +- public static int GetWordAt(byte[] Buffer, int Pos) +- { +- int hi = (Buffer[Pos] & 0x00FF); +- int lo = (Buffer[Pos+1] & 0x00FF); +- return (hi<<8)+lo; +- } +- +- // Returns a 16 bit signed value : from -32768 to 32767 +- public static int GetShortAt(byte[] Buffer, int Pos) +- { +- int hi = (Buffer[Pos]); +- int lo = (Buffer[Pos+1] & 0x00FF); +- return ((hi<<8)+lo); +- } +- +- // Returns a 32 bit unsigned value : from 0 to 4294967295 (2^32-1) +- public static long GetDWordAt(byte[] Buffer, int Pos) +- { +- long Result; +- Result=(long)(Buffer[Pos] & 0x0FF); +- Result<<=8; +- Result+=(long)(Buffer[Pos+1] & 0x0FF); +- Result<<=8; +- Result+=(long)(Buffer[Pos+2] & 0x0FF); +- Result<<=8; +- Result+=(long)(Buffer[Pos+3] & 0x0FF); +- return Result; +- } +- +- // Returns a 32 bit signed value : from 0 to 4294967295 (2^32-1) +- public static int GetDIntAt(byte[] Buffer, int Pos) +- { +- int Result; +- Result= Buffer[Pos]; +- Result<<=8; +- Result+=(Buffer[Pos+1] & 0x0FF); +- Result<<=8; +- Result+=(Buffer[Pos+2] & 0x0FF); +- Result<<=8; +- Result+=(Buffer[Pos+3] & 0x0FF); +- return Result; +- } +- +- // Returns a 32 bit floating point +- public static float GetFloatAt(byte[] Buffer, int Pos) +- { +- int IntFloat = GetDIntAt(Buffer, Pos); +- return Float.intBitsToFloat(IntFloat); +- } +- +- // Returns an ASCII string +- public static String GetStringAt(byte[] Buffer, int Pos, int MaxLen) +- { +- byte[] StrBuffer = new byte[MaxLen]; +- System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen); +- String S; +- try { +- S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8 +- } catch (UnsupportedEncodingException ex) { +- S = ""; +- } +- return S; +- } +- +- public static String GetPrintableStringAt(byte[] Buffer, int Pos, int MaxLen) +- { +- byte[] StrBuffer = new byte[MaxLen]; +- System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen); +- for (int c = 0; c < MaxLen; c++) +- { +- if ((StrBuffer[c]<31) || (StrBuffer[c]>126)) +- StrBuffer[c]=46; // '.' +- } +- String S; +- try { +- S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8 +- } catch (UnsupportedEncodingException ex) { +- S = ""; +- } +- return S; +- } +- +- public static Date GetDateAt(byte[] Buffer, int Pos) +- { +- int Year, Month, Day, Hour, Min, Sec; +- Calendar S7Date = Calendar.getInstance(); +- +- Year = S7.BCDtoByte(Buffer[Pos]); +- if (Year<90) +- Year+=2000; +- else +- Year+=1900; +- +- Month=S7.BCDtoByte(Buffer[Pos+1])-1; +- Day =S7.BCDtoByte(Buffer[Pos+2]); +- Hour =S7.BCDtoByte(Buffer[Pos+3]); +- Min =S7.BCDtoByte(Buffer[Pos+4]); +- Sec =S7.BCDtoByte(Buffer[Pos+5]); +- +- S7Date.set(Year, Month, Day, Hour, Min, Sec); +- +- return S7Date.getTime(); +- } +- +- public static void SetBitAt(byte[] Buffer, int Pos, int Bit, boolean Value) +- { +- byte[] Mask = { +- (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08, +- (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80 +- }; +- if (Bit<0) Bit=0; +- if (Bit>7) Bit=7; +- +- if (Value) +- Buffer[Pos]= (byte) (Buffer[Pos] | Mask[Bit]); +- else +- Buffer[Pos]= (byte) (Buffer[Pos] & ~Mask[Bit]); +- } +- +- public static void SetWordAt(byte[] Buffer, int Pos, int Value) +- { +- int Word = Value & 0x0FFFF; +- Buffer[Pos] = (byte) (Word >> 8); +- Buffer[Pos+1] = (byte) (Word & 0x00FF); +- } +- +- public static void SetShortAt(byte[] Buffer, int Pos, int Value) +- { +- Buffer[Pos] = (byte) (Value >> 8); +- Buffer[Pos+1] = (byte) (Value & 0x00FF); +- } +- public static void SetDWordAt(byte[] Buffer, int Pos, long Value) +- { +- long DWord = Value &0x0FFFFFFFF; +- Buffer[Pos+3] = (byte) (DWord &0xFF); +- Buffer[Pos+2] = (byte) ((DWord >> 8) &0xFF); +- Buffer[Pos+1] = (byte) ((DWord >> 16) &0xFF); +- Buffer[Pos] = (byte) ((DWord >> 24) &0xFF); +- } +- +- public static void SetDIntAt(byte[] Buffer, int Pos, int Value) +- { +- Buffer[Pos+3] = (byte) (Value &0xFF); +- Buffer[Pos+2] = (byte) ((Value >> 8) &0xFF); +- Buffer[Pos+1] = (byte) ((Value >> 16) &0xFF); +- Buffer[Pos] = (byte) ((Value >> 24) &0xFF); +- } +- +- public static void SetFloatAt(byte[] Buffer, int Pos, float Value) +- { +- int DInt = Float.floatToIntBits(Value); +- SetDIntAt(Buffer, Pos, DInt); +- } +- +- public static void SetDateAt(byte[] Buffer, int Pos, Date DateTime) +- { +- int Year, Month, Day, Hour, Min, Sec, Dow; +- Calendar S7Date = Calendar.getInstance(); +- S7Date.setTime(DateTime); +- +- Year = S7Date.get(Calendar.YEAR); +- Month = S7Date.get(Calendar.MONTH)+1; +- Day = S7Date.get(Calendar.DAY_OF_MONTH); +- Hour = S7Date.get(Calendar.HOUR_OF_DAY); +- Min = S7Date.get(Calendar.MINUTE); +- Sec = S7Date.get(Calendar.SECOND); +- Dow = S7Date.get(Calendar.DAY_OF_WEEK); +- +- if (Year>1999) +- Year-=2000; +- +- Buffer[Pos] =ByteToBCD(Year); +- Buffer[Pos+1]=ByteToBCD(Month); +- Buffer[Pos+2]=ByteToBCD(Day); +- Buffer[Pos+3]=ByteToBCD(Hour); +- Buffer[Pos+4]=ByteToBCD(Min); +- Buffer[Pos+5]=ByteToBCD(Sec); +- Buffer[Pos+6]=0; +- Buffer[Pos+7]=ByteToBCD(Dow); +- } +- +- public static int BCDtoByte(byte B) +- { +- return ((B >> 4) * 10) + (B & 0x0F); +- } +- +- public static byte ByteToBCD(int Value) +- { +- return (byte) (((Value / 10) << 4) | (Value % 10)); +- } +- +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++package Moka7; ++ ++import java.io.UnsupportedEncodingException; ++import java.util.Date; ++import java.util.Calendar; ++ ++/** ++ * ++ * @author Davide Nardella ++ */ ++ ++ ++// Step 7 Constants and Conversion helper class ++public class S7 { ++ // S7 ID Area (Area that we want to read/write) ++ public static final int S7AreaPE = 0x81; ++ public static final int S7AreaPA = 0x82; ++ public static final int S7AreaMK = 0x83; ++ public static final int S7AreaDB = 0x84; ++ public static final int S7AreaCT = 0x1C; ++ public static final int S7AreaTM = 0x1D; ++ // Connection types ++ public static final byte PG = 0x01; ++ public static final byte OP = 0x02; ++ public static final byte S7_BASIC = 0x03; ++ // Block type ++ public static final int Block_OB = 0x38; ++ public static final int Block_DB = 0x41; ++ public static final int Block_SDB = 0x42; ++ public static final int Block_FC = 0x43; ++ public static final int Block_SFC = 0x44; ++ public static final int Block_FB = 0x45; ++ public static final int Block_SFB = 0x46; ++ // Sub Block Type ++ public static final int SubBlk_OB = 0x08; ++ public static final int SubBlk_DB = 0x0A; ++ public static final int SubBlk_SDB = 0x0B; ++ public static final int SubBlk_FC = 0x0C; ++ public static final int SubBlk_SFC = 0x0D; ++ public static final int SubBlk_FB = 0x0E; ++ public static final int SubBlk_SFB = 0x0F; ++ // Block languages ++ public static final int BlockLangAWL = 0x01; ++ public static final int BlockLangKOP = 0x02; ++ public static final int BlockLangFUP = 0x03; ++ public static final int BlockLangSCL = 0x04; ++ public static final int BlockLangDB = 0x05; ++ public static final int BlockLangGRAPH = 0x06; ++ // PLC Status ++ public static final int S7CpuStatusUnknown = 0x00; ++ public static final int S7CpuStatusRun = 0x08; ++ public static final int S7CpuStatusStop = 0x04; ++ // Type Var ++ public static final int S7TypeBool = 1; ++ public static final int S7TypeInt = 1; ++ ++ // Returns the bit at Pos.Bit ++ public static boolean GetBitAt(byte[] Buffer, int Pos, int Bit) ++ { ++ int Value = Buffer[Pos] & 0x0FF; ++ byte[] Mask = { ++ (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08, ++ (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80 ++ }; ++ if (Bit<0) Bit=0; ++ if (Bit>7) Bit=7; ++ ++ return (Value & Mask[Bit])!=0; ++ } ++ /** ++ * Returns a 16 bit unsigned value : from 0 to 65535 (2^16-1) ++ * @param Buffer ++ * @param Pos start position ++ * @return ++ */ ++ public static int GetWordAt(byte[] Buffer, int Pos) ++ { ++ int hi = (Buffer[Pos] & 0x00FF); ++ int lo = (Buffer[Pos+1] & 0x00FF); ++ return (hi<<8)+lo; ++ } ++ ++ // Returns a 16 bit signed value : from -32768 to 32767 ++ public static int GetShortAt(byte[] Buffer, int Pos) ++ { ++ int hi = (Buffer[Pos]); ++ int lo = (Buffer[Pos+1] & 0x00FF); ++ return ((hi<<8)+lo); ++ } ++ ++ // Returns a 32 bit unsigned value : from 0 to 4294967295 (2^32-1) ++ public static long GetDWordAt(byte[] Buffer, int Pos) ++ { ++ long Result; ++ Result=(long)(Buffer[Pos] & 0x0FF); ++ Result<<=8; ++ Result+=(long)(Buffer[Pos+1] & 0x0FF); ++ Result<<=8; ++ Result+=(long)(Buffer[Pos+2] & 0x0FF); ++ Result<<=8; ++ Result+=(long)(Buffer[Pos+3] & 0x0FF); ++ return Result; ++ } ++ ++ // Returns a 32 bit signed value : from 0 to 4294967295 (2^32-1) ++ public static int GetDIntAt(byte[] Buffer, int Pos) ++ { ++ int Result; ++ Result= Buffer[Pos]; ++ Result<<=8; ++ Result+=(Buffer[Pos+1] & 0x0FF); ++ Result<<=8; ++ Result+=(Buffer[Pos+2] & 0x0FF); ++ Result<<=8; ++ Result+=(Buffer[Pos+3] & 0x0FF); ++ return Result; ++ } ++ ++ // Returns a 32 bit floating point ++ public static float GetFloatAt(byte[] Buffer, int Pos) ++ { ++ int IntFloat = GetDIntAt(Buffer, Pos); ++ return Float.intBitsToFloat(IntFloat); ++ } ++ ++ // Returns an ASCII string ++ public static String GetStringAt(byte[] Buffer, int Pos, int MaxLen) ++ { ++ byte[] StrBuffer = new byte[MaxLen]; ++ System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen); ++ String S; ++ try { ++ S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8 ++ } catch (UnsupportedEncodingException ex) { ++ S = ""; ++ } ++ return S; ++ } ++ ++ public static String GetPrintableStringAt(byte[] Buffer, int Pos, int MaxLen) ++ { ++ byte[] StrBuffer = new byte[MaxLen]; ++ System.arraycopy(Buffer, Pos, StrBuffer, 0, MaxLen); ++ for (int c = 0; c < MaxLen; c++) ++ { ++ if ((StrBuffer[c]<31) || (StrBuffer[c]>126)) ++ StrBuffer[c]=46; // '.' ++ } ++ String S; ++ try { ++ S = new String(StrBuffer, "UTF-8"); // the charset is UTF-8 ++ } catch (UnsupportedEncodingException ex) { ++ S = ""; ++ } ++ return S; ++ } ++ ++ public static Date GetDateAt(byte[] Buffer, int Pos) ++ { ++ int Year, Month, Day, Hour, Min, Sec; ++ Calendar S7Date = Calendar.getInstance(); ++ ++ Year = S7.BCDtoByte(Buffer[Pos]); ++ if (Year<90) ++ Year+=2000; ++ else ++ Year+=1900; ++ ++ Month=S7.BCDtoByte(Buffer[Pos+1])-1; ++ Day =S7.BCDtoByte(Buffer[Pos+2]); ++ Hour =S7.BCDtoByte(Buffer[Pos+3]); ++ Min =S7.BCDtoByte(Buffer[Pos+4]); ++ Sec =S7.BCDtoByte(Buffer[Pos+5]); ++ ++ S7Date.set(Year, Month, Day, Hour, Min, Sec); ++ ++ return S7Date.getTime(); ++ } ++ ++ public static void SetBitAt(byte[] Buffer, int Pos, int Bit, boolean Value) ++ { ++ byte[] Mask = { ++ (byte)0x01,(byte)0x02,(byte)0x04,(byte)0x08, ++ (byte)0x10,(byte)0x20,(byte)0x40,(byte)0x80 ++ }; ++ if (Bit<0) Bit=0; ++ if (Bit>7) Bit=7; ++ ++ if (Value) ++ Buffer[Pos]= (byte) (Buffer[Pos] | Mask[Bit]); ++ else ++ Buffer[Pos]= (byte) (Buffer[Pos] & ~Mask[Bit]); ++ } ++ ++ public static void SetWordAt(byte[] Buffer, int Pos, int Value) ++ { ++ int Word = Value & 0x0FFFF; ++ Buffer[Pos] = (byte) (Word >> 8); ++ Buffer[Pos+1] = (byte) (Word & 0x00FF); ++ } ++ ++ public static void SetShortAt(byte[] Buffer, int Pos, int Value) ++ { ++ Buffer[Pos] = (byte) (Value >> 8); ++ Buffer[Pos+1] = (byte) (Value & 0x00FF); ++ } ++ public static void SetDWordAt(byte[] Buffer, int Pos, long Value) ++ { ++ long DWord = Value &0x0FFFFFFFF; ++ Buffer[Pos+3] = (byte) (DWord &0xFF); ++ Buffer[Pos+2] = (byte) ((DWord >> 8) &0xFF); ++ Buffer[Pos+1] = (byte) ((DWord >> 16) &0xFF); ++ Buffer[Pos] = (byte) ((DWord >> 24) &0xFF); ++ } ++ ++ public static void SetDIntAt(byte[] Buffer, int Pos, int Value) ++ { ++ Buffer[Pos+3] = (byte) (Value &0xFF); ++ Buffer[Pos+2] = (byte) ((Value >> 8) &0xFF); ++ Buffer[Pos+1] = (byte) ((Value >> 16) &0xFF); ++ Buffer[Pos] = (byte) ((Value >> 24) &0xFF); ++ } ++ ++ public static void SetFloatAt(byte[] Buffer, int Pos, float Value) ++ { ++ int DInt = Float.floatToIntBits(Value); ++ SetDIntAt(Buffer, Pos, DInt); ++ } ++ ++ public static void SetDateAt(byte[] Buffer, int Pos, Date DateTime) ++ { ++ int Year, Month, Day, Hour, Min, Sec, Dow; ++ Calendar S7Date = Calendar.getInstance(); ++ S7Date.setTime(DateTime); ++ ++ Year = S7Date.get(Calendar.YEAR); ++ Month = S7Date.get(Calendar.MONTH)+1; ++ Day = S7Date.get(Calendar.DAY_OF_MONTH); ++ Hour = S7Date.get(Calendar.HOUR_OF_DAY); ++ Min = S7Date.get(Calendar.MINUTE); ++ Sec = S7Date.get(Calendar.SECOND); ++ Dow = S7Date.get(Calendar.DAY_OF_WEEK); ++ ++ if (Year>1999) ++ Year-=2000; ++ ++ Buffer[Pos] =ByteToBCD(Year); ++ Buffer[Pos+1]=ByteToBCD(Month); ++ Buffer[Pos+2]=ByteToBCD(Day); ++ Buffer[Pos+3]=ByteToBCD(Hour); ++ Buffer[Pos+4]=ByteToBCD(Min); ++ Buffer[Pos+5]=ByteToBCD(Sec); ++ Buffer[Pos+6]=0; ++ Buffer[Pos+7]=ByteToBCD(Dow); ++ } ++ ++ public static int BCDtoByte(byte B) ++ { ++ return ((B >> 4) * 10) + (B & 0x0F); ++ } ++ ++ public static byte ByteToBCD(int Value) ++ { ++ return (byte) (((Value / 10) << 4) | (Value % 10)); ++ } ++ ++} +diff U3 S7BlockInfo.java S7BlockInfo.java +--- S7BlockInfo.java Thu Mar 23 15:34:52 2017 ++++ S7BlockInfo.java Tue Aug 08 18:53:37 2017 +@@ -1,101 +1,101 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +-package Moka7; +-import java.util.Date; +-/** +- * +- * @author Davide +- */ +-public class S7BlockInfo { +- +- private final int BufSize = 96; +- // MilliSeconds between 1970/1/1 (Java time base) and 1984/1/1 (Siemens base) +- private final long DeltaMilliSecs = 441763200000L; +- protected byte[] Buffer = new byte[BufSize]; +- +- protected void Update(byte[] Src, int Pos) +- { +- System.arraycopy(Src, Pos, Buffer, 0, BufSize); +- } +- public int BlkType() +- { +- return Buffer[2]; +- } +- public int BlkNumber() +- { +- return S7.GetWordAt(Buffer, 3); +- } +- public int BlkLang() +- { +- return Buffer[1]; +- } +- public int BlkFlags() +- { +- return Buffer[0]; +- } +- public int MC7Size() // The real size in bytes +- { +- return S7.GetWordAt(Buffer, 31); +- } +- public int LoadSize() +- { +- return S7.GetDIntAt(Buffer, 5); +- } +- public int LocalData() +- { +- return S7.GetWordAt(Buffer, 29); +- } +- public int SBBLength() +- { +- return S7.GetWordAt(Buffer, 25); +- } +- public int Checksum() +- { +- return S7.GetWordAt(Buffer, 59); +- } +- public int Version() +- { +- return Buffer[57]; +- } +- public Date CodeDate() +- { +- long BlockDate = ((long)S7.GetWordAt(Buffer, 17))*86400000L+DeltaMilliSecs; +- return new Date(BlockDate); +- } +- public Date IntfDate() +- { +- long BlockDate = ((long)S7.GetWordAt(Buffer, 23))*86400000L+DeltaMilliSecs; +- return new Date(BlockDate); +- } +- public String Author() +- { +- return S7.GetStringAt(Buffer,33,8); +- } +- public String Family() +- { +- return S7.GetStringAt(Buffer,41,8); +- } +- public String Header() +- { +- return S7.GetStringAt(Buffer,49,8); +- } +- +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++package Moka7; ++import java.util.Date; ++/** ++ * ++ * @author Davide Nardella ++ */ ++public class S7BlockInfo { ++ ++ private final int BufSize = 96; ++ // MilliSeconds between 1970/1/1 (Java time base) and 1984/1/1 (Siemens base) ++ private final long DeltaMilliSecs = 441763200000L; ++ protected byte[] Buffer = new byte[BufSize]; ++ ++ protected void Update(byte[] Src, int Pos) ++ { ++ System.arraycopy(Src, Pos, Buffer, 0, BufSize); ++ } ++ public int BlkType() ++ { ++ return Buffer[2]; ++ } ++ public int BlkNumber() ++ { ++ return S7.GetWordAt(Buffer, 3); ++ } ++ public int BlkLang() ++ { ++ return Buffer[1]; ++ } ++ public int BlkFlags() ++ { ++ return Buffer[0]; ++ } ++ public int MC7Size() // The real size in bytes ++ { ++ return S7.GetWordAt(Buffer, 31); ++ } ++ public int LoadSize() ++ { ++ return S7.GetDIntAt(Buffer, 5); ++ } ++ public int LocalData() ++ { ++ return S7.GetWordAt(Buffer, 29); ++ } ++ public int SBBLength() ++ { ++ return S7.GetWordAt(Buffer, 25); ++ } ++ public int Checksum() ++ { ++ return S7.GetWordAt(Buffer, 59); ++ } ++ public int Version() ++ { ++ return Buffer[57]; ++ } ++ public Date CodeDate() ++ { ++ long BlockDate = ((long)S7.GetWordAt(Buffer, 17))*86400000L+DeltaMilliSecs; ++ return new Date(BlockDate); ++ } ++ public Date IntfDate() ++ { ++ long BlockDate = ((long)S7.GetWordAt(Buffer, 23))*86400000L+DeltaMilliSecs; ++ return new Date(BlockDate); ++ } ++ public String Author() ++ { ++ return S7.GetStringAt(Buffer,33,8); ++ } ++ public String Family() ++ { ++ return S7.GetStringAt(Buffer,41,8); ++ } ++ public String Header() ++ { ++ return S7.GetStringAt(Buffer,49,8); ++ } ++ ++} +diff U3 S7Client.java S7Client.java +--- S7Client.java Thu Mar 23 15:34:52 2017 ++++ S7Client.java Tue Aug 08 18:53:37 2017 +@@ -1,1214 +1,1233 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +-package Moka7; +- +-import java.io.DataInputStream; +-import java.io.DataOutputStream; +-import java.io.IOException; +-import java.io.UnsupportedEncodingException; +-import java.net.InetSocketAddress; +-import java.net.Socket; +-import java.net.SocketAddress; +-import java.util.Date; +- +- +-/** +- * +- * @author Dave Nardella +- */ +-public class S7Client +-{ +- // WordLength +- private static final byte S7WLByte =0x02; +- private static final byte S7WLCounter =0x1C; +- private static final byte S7WLTimer =0x1D; +- // Error Codes +- public static final int errTCPConnectionFailed = 0x0001; +- public static final int errTCPDataSend = 0x0002; +- public static final int errTCPDataRecv = 0x0003; +- public static final int errTCPDataRecvTout = 0x0004; +- public static final int errTCPConnectionReset = 0x0005; +- public static final int errISOInvalidPDU = 0x0006; +- public static final int errISOConnectionFailed = 0x0007; +- public static final int errISONegotiatingPDU = 0x0008; +- public static final int errS7InvalidPDU = 0x0009; +- public static final int errS7DataRead = 0x000A; +- public static final int errS7DataWrite = 0x000B; +- public static final int errS7BufferTooSmall = 0x000C; +- public static final int errS7FunctionError = 0x000D; +- public static final int errS7InvalidParams = 0x000E; +- +- // Public fields +- public boolean Connected = false; +- public int LastError = 0; +- public int RecvTimeout = 2000; +- +- // Privates +- private static final int ISOTCP = 102; // ISOTCP Port +- private static final int MinPduSize = 16; +- private static final int DefaultPduSizeRequested = 480; +- private static final int IsoHSize = 7; // TPKT+COTP Header Size +- private static final int MaxPduSize = DefaultPduSizeRequested+IsoHSize; +- +- +- private Socket TCPSocket; +- private final byte[] PDU = new byte[2048]; +- +- private DataInputStream InStream = null; +- private DataOutputStream OutStream = null; +- +- private String IPAddress; +- +- private byte LocalTSAP_HI; +- private byte LocalTSAP_LO; +- private byte RemoteTSAP_HI; +- private byte RemoteTSAP_LO; +- private byte LastPDUType; +- +- private short ConnType = S7.PG; +- private int _PDULength = 0; +- +- // Telegrams +- // ISO Connection Request telegram (contains also ISO Header and COTP Header) +- private static final byte ISO_CR[] = { +- // TPKT (RFC1006 Header) +- (byte)0x03, // RFC 1006 ID (3) +- (byte)0x00, // Reserved, always 0 +- (byte)0x00, // High part of packet lenght (entire frame, payload and TPDU included) +- (byte)0x16, // Low part of packet lenght (entire frame, payload and TPDU included) +- // COTP (ISO 8073 Header) +- (byte)0x11, // PDU Size Length +- (byte)0xE0, // CR - Connection Request ID +- (byte)0x00, // Dst Reference HI +- (byte)0x00, // Dst Reference LO +- (byte)0x00, // Src Reference HI +- (byte)0x01, // Src Reference LO +- (byte)0x00, // Class + Options Flags +- (byte)0xC0, // PDU Max Length ID +- (byte)0x01, // PDU Max Length HI +- (byte)0x0A, // PDU Max Length LO +- (byte)0xC1, // Src TSAP Identifier +- (byte)0x02, // Src TSAP Length (2 bytes) +- (byte)0x01, // Src TSAP HI (will be overwritten) +- (byte)0x00, // Src TSAP LO (will be overwritten) +- (byte)0xC2, // Dst TSAP Identifier +- (byte)0x02, // Dst TSAP Length (2 bytes) +- (byte)0x01, // Dst TSAP HI (will be overwritten) +- (byte)0x02 // Dst TSAP LO (will be overwritten) +- }; +- +- // S7 PDU Negotiation Telegram (contains also ISO Header and COTP Header) +- private static final byte S7_PN[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x19, +- (byte)0x02, (byte)0xf0, (byte)0x80, // TPKT + COTP (see above for info) +- (byte)0x32, (byte)0x01, (byte)0x00, (byte)0x00, +- (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x08, +- (byte)0x00, (byte)0x00, (byte)0xf0, (byte)0x00, +- (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01, +- (byte)0x00, (byte)0x1e // PDU Length Requested = HI-LO 480 bytes +- }; +- +- // S7 Read/Write Request Header (contains also ISO Header and COTP Header) +- private static final byte S7_RW[] = { // 31-35 bytes +- (byte)0x03,(byte)0x00, +- (byte)0x00,(byte)0x1f, // Telegram Length (Data Size + 31 or 35) +- (byte)0x02,(byte)0xf0, (byte)0x80, // COTP (see above for info) +- (byte)0x32, // S7 Protocol ID +- (byte)0x01, // Job Type +- (byte)0x00,(byte)0x00, // Redundancy identification +- (byte)0x05,(byte)0x00, // PDU Reference +- (byte)0x00,(byte)0x0e, // Parameters Length +- (byte)0x00,(byte)0x00, // Data Length = Size(bytes) + 4 +- (byte)0x04, // Function 4 Read Var, 5 Write Var +- (byte)0x01, // Items count +- (byte)0x12, // Var spec. +- (byte)0x0a, // Length of remaining bytes +- (byte)0x10, // Syntax ID +- S7WLByte, // Transport Size +- (byte)0x00,(byte)0x00, // Num Elements +- (byte)0x00,(byte)0x00, // DB Number (if any, else 0) +- (byte)0x84, // Area Type +- (byte)0x00,(byte)0x00,(byte)0x00, // Area Offset +- // WR area +- (byte)0x00, // Reserved +- (byte)0x04, // Transport size +- (byte)0x00,(byte)0x00, // Data Length * 8 (if not timer or counter) +- }; +- private static final int Size_RD = 31; +- private static final int Size_WR = 35; +- +- // S7 Get Block Info Request Header (contains also ISO Header and COTP Header) +- private static final byte S7_BI[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x05, +- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, +- (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12, +- (byte)0x04, (byte)0x11, (byte)0x43, (byte)0x03, +- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, +- (byte)0x08, (byte)0x30, +- (byte)0x41, // Block Type +- (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, // ASCII Block Number +- (byte)0x41 +- }; +- +- // SZL First telegram request +- private static final byte S7_SZL_FIRST[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x07, (byte)0x00, (byte)0x00, +- (byte)0x05, (byte)0x00, // Sequence out +- (byte)0x00, (byte)0x08, (byte)0x00, +- (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12, +- (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01, +- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, +- (byte)0x04, +- (byte)0x00, (byte)0x00, // ID (29) +- (byte)0x00, (byte)0x00 // Index (31) +- }; +- +- // SZL Next telegram request +- private static final byte S7_SZL_NEXT[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x06, +- (byte)0x00, (byte)0x00, (byte)0x0c, (byte)0x00, +- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, +- (byte)0x08, (byte)0x12, (byte)0x44, (byte)0x01, +- (byte)0x01, // Sequence +- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, +- (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00 +- }; +- +- // Get Date/Time request +- private static final byte S7_GET_DT[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x38, +- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, +- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, +- (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x01, +- (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, +- (byte)0x00 +- }; +- +- // Set Date/Time command +- private static final byte S7_SET_DT[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x89, +- (byte)0x03, (byte)0x00, (byte)0x08, (byte)0x00, +- (byte)0x0e, (byte)0x00, (byte)0x01, (byte)0x12, +- (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x02, +- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, +- (byte)0x0a, (byte)0x00, (byte)0x19, // Hi part of Year +- (byte)0x13, // Lo part of Year +- (byte)0x12, // Month +- (byte)0x06, // Day +- (byte)0x17, // Hour +- (byte)0x37, // Min +- (byte)0x13, // Sec +- (byte)0x00, (byte)0x01 // ms + Day of week +- }; +- +- // S7 STOP request +- private static final byte S7_STOP[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0e, +- (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00, +- (byte)0x00, (byte)0x29, (byte)0x00, (byte)0x00, +- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, +- (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52, +- (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41, +- (byte)0x4d +- }; +- +- // S7 HOT Start request +- private static final byte S7_HOT_START[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0c, +- (byte)0x00, (byte)0x00, (byte)0x14, (byte)0x00, +- (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00, +- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, +- (byte)0xfd, (byte)0x00, (byte)0x00, (byte)0x09, +- (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52, +- (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41, +- (byte)0x4d +- }; +- +- // S7 COLD Start request +- private static final byte S7_COLD_START[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0f, +- (byte)0x00, (byte)0x00, (byte)0x16, (byte)0x00, +- (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00, +- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, +- (byte)0xfd, (byte)0x00, (byte)0x02, (byte)0x43, +- (byte)0x20, (byte)0x09, (byte)0x50, (byte)0x5f, +- (byte)0x50, (byte)0x52, (byte)0x4f, (byte)0x47, +- (byte)0x52, (byte)0x41, (byte)0x4d +- }; +- +- // S7 Get PLC Status +- private static final byte S7_GET_STAT[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x2c, +- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, +- (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12, +- (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01, +- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, +- (byte)0x04, (byte)0x04, (byte)0x24, (byte)0x00, +- (byte)0x00 +- }; +- +- // S7 Set Session Password +- private static final byte S7_SET_PWD[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x27, +- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, +- (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12, +- (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x01, +- (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, +- (byte)0x08, +- // 8 Char Encoded Password +- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, +- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 +- }; +- +- // S7 Clear Session Password +- private static final byte S7_CLR_PWD[] = { +- (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d, +- (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, +- (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x29, +- (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, +- (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, +- (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x02, +- (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, +- (byte)0x00 +- }; +- +- public S7Client() +- { +- // Placeholder for future implementations +- } +- +- public static String ErrorText(int Error) +- { +- switch (Error) +- { +- case errTCPConnectionFailed : +- return "TCP Connection failed."; +- case errTCPDataSend : +- return "TCP Sending error."; +- case errTCPDataRecv : +- return "TCP Receiving error."; +- case errTCPDataRecvTout : +- return "Data Receiving timeout."; +- case errTCPConnectionReset : +- return "Connection reset by the peer."; +- case errISOInvalidPDU : +- return "Invalid ISO PDU received."; +- case errISOConnectionFailed : +- return "ISO connection refused by the CPU."; +- case errISONegotiatingPDU : +- return "ISO error negotiating the PDU length."; +- case errS7InvalidPDU : +- return "Invalid S7 PDU received."; +- case errS7DataRead : +- return "S7 Error reading data from the CPU."; +- case errS7DataWrite : +- return "S7 Error writing data to the CPU."; +- case errS7BufferTooSmall : +- return "The Buffer supplied to the function is too small."; +- case errS7FunctionError : +- return "S7 function refused by the CPU."; +- case errS7InvalidParams : +- return "Invalid parameters supplied to the function."; +- default : +- return "Unknown error : 0x"+Integer.toHexString(Error); +- } +- } +- +- private int TCPConnect() +- { +- SocketAddress sockaddr = new InetSocketAddress(IPAddress, ISOTCP); +- LastError=0; +- try { +- TCPSocket = new Socket(); +- TCPSocket.connect(sockaddr ,5000); +- TCPSocket.setTcpNoDelay(true); +- InStream = new DataInputStream(TCPSocket.getInputStream()); +- OutStream = new DataOutputStream(TCPSocket.getOutputStream()); +- } +- catch (IOException e) { +- LastError=errTCPConnectionFailed; +- } +- return LastError; +- } +- +- private int WaitForData(int Size, int Timeout) +- { +- int cnt = 0; +- LastError=0; +- int SizeAvail; +- boolean Expired = false; +- try +- { +- SizeAvail=InStream.available(); +- while ((SizeAvailTimeout; +- // If timeout we clean the buffer +- if (Expired && (SizeAvail>0) && (LastError==0)) +- InStream.read(PDU, 0, SizeAvail); +- } +- } +- catch (IOException ex) +- { +- LastError=errTCPDataRecvTout; +- } +- if (cnt>=Timeout) +- { +- LastError=errTCPDataRecvTout; +- } +- return LastError; +- } +- +- private int RecvPacket(byte[] Buffer, int Start, int Size) +- { +- int BytesRead=0; +- LastError=WaitForData(Size,RecvTimeout); +- if (LastError==0) +- { +- try { +- BytesRead = InStream.read(Buffer, Start, Size); +- } catch (IOException ex) { +- LastError=errTCPDataRecv; +- } +- if (BytesRead==0) +- LastError=errTCPConnectionReset; +- } +- return LastError; +- } +- +- private void SendPacket(byte[] Buffer, int Len) +- { +- LastError = 0; +- try { +- OutStream.write(Buffer,0,Len); +- OutStream.flush(); +- } catch (IOException ex) { +- LastError = errTCPDataSend; +- } +- } +- private void SendPacket(byte[] Buffer) +- { +- SendPacket(Buffer,Buffer.length); +- } +- +- private int RecvIsoPacket() +- { +- Boolean Done = false; +- int Size = 0; +- while ((LastError==0) && !Done) +- { +- // Get TPKT (4 bytes) +- RecvPacket(PDU, 0, 4); +- if (LastError==0) +- { +- Size=S7.GetWordAt(PDU,2); +- // Check 0 bytes Data Packet (only TPKT+COTP = 7 bytes) +- if (Size==IsoHSize) +- RecvPacket(PDU,4, 3); // Skip remaining 3 bytes and Done is still false +- else +- { +- if ((Size>MaxPduSize) || (Size16 && <247 +- } +- } +- } +- if (LastError==0) +- { +- RecvPacket(PDU,4, 3); // Skip remaining 3 COTP bytes +- LastPDUType=PDU[5]; // Stores PDU Type, we need it +- // Receives the S7 Payload +- RecvPacket(PDU, 7, Size-IsoHSize); +- } +- if (LastError==0) +- return Size; +- else +- return 0; +- } +- +- private int ISOConnect() +- { +- int Size; +- ISO_CR[16]=LocalTSAP_HI; +- ISO_CR[17]=LocalTSAP_LO; +- ISO_CR[20]=RemoteTSAP_HI; +- ISO_CR[21]=RemoteTSAP_LO; +- +- // Sends the connection request telegram +- SendPacket(ISO_CR); +- if (LastError==0) +- { +- // Gets the reply (if any) +- Size=RecvIsoPacket(); +- if (LastError==0) +- { +- if (Size==22) +- { +- if (LastPDUType!=(byte)0xD0) // 0xD0 = CC Connection confirm +- LastError=errISOConnectionFailed; +- } +- else +- LastError=errISOInvalidPDU; +- } +- } +- return LastError; +- } +- +- private int NegotiatePduLength() +- { +- int Length; +- // Set PDU Size Requested +- S7.SetWordAt(S7_PN,23,DefaultPduSizeRequested); +- // Sends the connection request telegram +- SendPacket(S7_PN); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (LastError==0) +- { +- // check S7 Error +- if ((Length==27) && (PDU[17]==0) && (PDU[18]==0)) // 20 = size of Negotiate Answer +- { +- // Get PDU Size Negotiated +- _PDULength = S7.GetWordAt(PDU,25); +- if (_PDULength>0) +- return 0; +- else +- LastError=errISONegotiatingPDU; +- } +- else +- LastError=errISONegotiatingPDU; +- } +- } +- return LastError; +- } +- +- public void SetConnectionType(short ConnectionType) +- { +- ConnType=ConnectionType; +- } +- +- public int Connect() +- { +- LastError=0; +- if (!Connected) +- { +- TCPConnect(); +- if (LastError==0) // First stage : TCP Connection +- { +- ISOConnect(); +- if (LastError==0) // Second stage : ISOTCP (ISO 8073) Connection +- { +- LastError=NegotiatePduLength(); // Third stage : S7 PDU negotiation +- } +- } +- } +- Connected=LastError==0; +- +- // In case the connection is not completely established (TCP connection + ISO connection + PDU negotiation) +- // we close the socket and its IO streams to revert the object back to pre-Connect() state +- if (!Connected) +- { +- if (TCPSocket != null) { +- try { +- TCPSocket.close(); +- } catch (IOException ex) { +- } +- } +- if (InStream != null) { +- try { +- InStream.close(); +- } catch (IOException ex) { +- } +- } +- if (OutStream != null) { +- try { +- OutStream.close(); +- } catch (IOException ex) { +- } +- } +- _PDULength = 0; +- } +- +- return LastError; +- } +- +- public void Disconnect() +- { +- if (Connected) +- { +- try { +- OutStream.close(); +- InStream.close(); +- TCPSocket.close(); +- _PDULength=0; +- } catch (IOException ex) { +- } +- Connected=false; +- } +- } +- +- public int ConnectTo(String Address, int Rack, int Slot) +- { +- int RemoteTSAP=(ConnType<<8)+ (Rack * 0x20) + Slot; +- SetConnectionParams(Address, 0x0100, RemoteTSAP); +- return Connect(); +- } +- +- public int PDULength() +- { +- return _PDULength; +- } +- +- public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP) +- { +- int LocTSAP = LocalTSAP & 0x0000FFFF; +- int RemTSAP = RemoteTSAP & 0x0000FFFF; +- IPAddress = Address; +- LocalTSAP_HI = (byte) (LocTSAP>>8); +- LocalTSAP_LO = (byte) (LocTSAP & 0x00FF); +- RemoteTSAP_HI= (byte) (RemTSAP>>8); +- RemoteTSAP_LO= (byte) (RemTSAP & 0x00FF); +- } +- +- public int ReadArea(int Area, int DBNumber, int Start, int Amount, byte[] Data) +- { +- int Address; +- int NumElements; +- int MaxElements; +- int TotElements; +- int SizeRequested; +- int Length; +- int Offset = 0; +- int WordSize = 1; +- +- LastError=0; +- +- // If we are addressing Timers or counters the element size is 2 +- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) +- WordSize = 2; +- +- MaxElements=(_PDULength-18) / WordSize; // 18 = Reply telegram header +- TotElements=Amount; +- +- while ((TotElements>0) && (LastError==0)) +- { +- NumElements=TotElements; +- if (NumElements>MaxElements) +- NumElements=MaxElements; +- +- SizeRequested = NumElements * WordSize; +- +- // Setup the telegram +- System.arraycopy(S7_RW, 0, PDU, 0, Size_RD); +- // Set DB Number +- PDU[27] = (byte) Area; +- // Set Area +- if (Area==S7.S7AreaDB) +- S7.SetWordAt(PDU,25,DBNumber); +- +- // Adjusts Start and word length +- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) +- { +- Address = Start; +- if (Area==S7.S7AreaCT) +- PDU[22]=S7WLCounter; +- else +- PDU[22]=S7WLTimer; +- } +- else +- Address = Start<<3; +- +- // Num elements +- S7.SetWordAt(PDU,23,NumElements); +- +- // Address into the PLC (only 3 bytes) +- PDU[30] = (byte) (Address & 0x0FF); +- Address = Address >> 8; +- PDU[29] = (byte) (Address & 0x0FF); +- Address = Address >> 8; +- PDU[28] = (byte) (Address & 0x0FF); +- +- SendPacket(PDU, Size_RD); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (LastError==0) +- { +- if (Length>=25) +- { +- if ((Length-25==SizeRequested) && (PDU[21]==(byte)0xFF)) +- { +- System.arraycopy(PDU, 25, Data, Offset, SizeRequested); +- Offset+=SizeRequested; +- } +- else +- LastError = errS7DataRead; +- } +- else +- LastError = errS7InvalidPDU; +- } +- } +- +- TotElements -= NumElements; +- Start += NumElements*WordSize; +- } +- return LastError; +- } +- +- public int WriteArea(int Area, int DBNumber, int Start, int Amount, byte[] Data) +- { +- int Address; +- int NumElements; +- int MaxElements; +- int TotElements; +- int DataSize; +- int IsoSize; +- int Length; +- int Offset = 0; +- int WordSize = 1; +- +- LastError=0; +- +- // If we are addressing Timers or counters the element size is 2 +- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) +- WordSize = 2; +- +- MaxElements=(_PDULength-35) / WordSize; // 18 = Reply telegram header +- TotElements=Amount; +- +- while ((TotElements>0) && (LastError==0)) +- { +- NumElements=TotElements; +- if (NumElements>MaxElements) +- NumElements=MaxElements; +- +- DataSize = NumElements * WordSize; +- IsoSize = Size_WR + DataSize; +- +- // Setup the telegram +- System.arraycopy(S7_RW, 0, PDU, 0, Size_WR); +- // Whole telegram Size +- S7.SetWordAt(PDU,2,IsoSize); +- // Data Length +- Length=DataSize+4; +- S7.SetWordAt(PDU,15,Length); +- // Function +- PDU[17]= (byte) 0x05; +- // Set DB Number +- PDU[27] = (byte) Area; +- if (Area==S7.S7AreaDB) +- S7.SetWordAt(PDU,25,DBNumber); +- +- // Adjusts Start and word length +- if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) +- { +- Address = Start; +- Length = DataSize; +- if (Area==S7.S7AreaCT) +- PDU[22]=S7WLCounter; +- else +- PDU[22]=S7WLTimer; +- } +- else +- { +- Address = Start<<3; +- Length = DataSize<<3; +- } +- // Num elements +- S7.SetWordAt(PDU,23,NumElements); +- // Address into the PLC +- PDU[30] = (byte) (Address & 0x0FF); +- Address = Address >> 8; +- PDU[29] = (byte) (Address & 0x0FF); +- Address = Address >> 8; +- PDU[28] = (byte) (Address & 0x0FF); +- // Length +- S7.SetWordAt(PDU,33,Length); +- +- // Copies the Data +- System.arraycopy(Data, Offset, PDU, 35, DataSize); +- +- SendPacket(PDU, IsoSize); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (LastError==0) +- { +- if (Length==22) +- { +- if ((S7.GetWordAt(PDU,17)!=0) || (PDU[21]!=(byte)0xFF)) +- LastError = errS7DataWrite; +- } +- else +- LastError = errS7InvalidPDU; +- } +- } +- +- Offset+=DataSize; +- TotElements -= NumElements; +- Start += NumElements*WordSize; +- } +- return LastError; +- } +- +- public int GetAgBlockInfo(int BlockType, int BlockNumber, S7BlockInfo Block) +- { +- int Length; +- LastError=0; +- // Block Type +- S7_BI[30] = (byte) BlockType; +- // Block Number +- S7_BI[31]=(byte) ((BlockNumber / 10000)+0x30); +- BlockNumber=BlockNumber % 10000; +- S7_BI[32]=(byte) ((BlockNumber / 1000)+0x30); +- BlockNumber=BlockNumber % 1000; +- S7_BI[33]=(byte) ((BlockNumber / 100)+0x30); +- BlockNumber=BlockNumber % 100; +- S7_BI[34]=(byte) ((BlockNumber / 10)+0x30); +- BlockNumber=BlockNumber % 10; +- S7_BI[35]=(byte) ((BlockNumber / 1)+0x30); +- +- SendPacket(S7_BI); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 32) // the minimum expected +- { +- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) +- { +- Block.Update(PDU, 42); +- } +- else +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- +- return LastError; +- } +- /** +- * +- * @param DBNumber DB Number +- * @param Buffer Destination buffer +- * @param SizeRead How many bytes were read +- * @return +- */ +- public int DBGet(int DBNumber, byte[] Buffer, IntByRef SizeRead) +- { +- S7BlockInfo Block = new S7BlockInfo(); +- // Query the DB Length +- LastError = GetAgBlockInfo(S7.Block_DB, DBNumber, Block); +- if (LastError==0) +- { +- int SizeToRead = Block.MC7Size(); +- // Checks the room +- if (SizeToRead<=Buffer.length) +- { +- LastError=ReadArea(S7.S7AreaDB, DBNumber, 0, SizeToRead, Buffer); +- if (LastError==0) +- SizeRead.Value=SizeToRead; +- } +- else +- LastError=errS7BufferTooSmall; +- } +- return LastError; +- } +- +- public int ReadSZL(int ID, int Index, S7Szl SZL) +- { +- int Length; +- int DataSZL; +- int Offset = 0; +- boolean Done = false; +- boolean First = true; +- byte Seq_in =0x00; +- int Seq_out =0x0000; +- +- LastError=0; +- SZL.DataSize=0; +- do +- { +- if (First) +- { +- S7.SetWordAt(S7_SZL_FIRST, 11, ++Seq_out); +- S7.SetWordAt(S7_SZL_FIRST, 29, ID); +- S7.SetWordAt(S7_SZL_FIRST, 31, Index); +- SendPacket(S7_SZL_FIRST); +- } +- else +- { +- S7.SetWordAt(S7_SZL_NEXT, 11, ++Seq_out); +- PDU[24] = (byte)Seq_in; +- SendPacket(S7_SZL_NEXT); +- } +- if (LastError!=0) +- return LastError; +- +- Length=RecvIsoPacket(); +- if (LastError==0) +- { +- if (First) +- { +- if (Length > 32) // the minimum expected +- { +- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) +- { +- // Gets Amount of this slice +- DataSZL=S7.GetWordAt(PDU,31)-8; // Skips extra params (ID, Index ...) +- Done=PDU[26]==0x00; +- Seq_in=(byte)PDU[24]; // Slice sequence +- +- SZL.LENTHDR=S7.GetWordAt(PDU, 37); +- SZL.N_DR=S7.GetWordAt(PDU, 39); +- SZL.Copy(PDU, 41, Offset, DataSZL); +- Offset+=DataSZL; +- SZL.DataSize+=DataSZL; +- } +- else +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- else +- { +- if (Length > 32) // the minimum expected +- { +- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) +- { +- // Gets Amount of this slice +- DataSZL=S7.GetWordAt(PDU,31); +- Done=PDU[26]==0x00; +- Seq_in=(byte)PDU[24]; // Slice sequence +- SZL.Copy(PDU, 37, Offset, DataSZL); +- Offset+=DataSZL; +- SZL.DataSize+=DataSZL; +- } +- else +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- } +- First=false; +- } +- while(!Done && (LastError==0)); +- +- return LastError; +- } +- +- +- public int GetCpuInfo(S7CpuInfo Info) +- { +- S7Szl SZL = new S7Szl(1024); +- +- LastError = ReadSZL(0x001C, 0x0000, SZL); +- if (LastError==0) +- { +- Info.Update(SZL.Data, 0); +- } +- return LastError; +- } +- +- public int GetCpInfo(S7CpInfo Info) +- { +- S7Szl SZL = new S7Szl(1024); +- +- LastError = ReadSZL(0x0131, 0x0001, SZL); +- if (LastError==0) +- { +- Info.Update(SZL.Data, 0); +- } +- return LastError; +- } +- +- public int GetOrderCode(S7OrderCode Code) +- { +- S7Szl SZL = new S7Szl(1024); +- +- LastError = ReadSZL(0x0011, 0x0000, SZL); +- if (LastError==0) +- { +- Code.Update(SZL.Data, 0, SZL.DataSize); +- } +- return LastError; +- } +- +- public int GetPlcDateTime(Date DateTime) +- { +- int Length; +- +- LastError = 0; +- SendPacket(S7_GET_DT); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 30) // the minimum expected +- { +- if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) +- { +- DateTime=S7.GetDateAt(PDU, 34); +- } +- else +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- +- return LastError; +- } +- +- public int SetPlcDateTime(Date DateTime) +- { +- int Length; +- +- LastError = 0; +- S7.SetDateAt(S7_SET_DT, 31, DateTime); +- +- SendPacket(S7_SET_DT); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 30) // the minimum expected +- { +- if (S7.GetWordAt(PDU,27)!=0) +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- +- return LastError; +- } +- +- public int SetPlcSystemDateTime() +- { +- return SetPlcDateTime(new Date()); +- } +- +- public int PlcStop() +- { +- int Length; +- +- LastError = 0; +- SendPacket(S7_STOP); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 18) // 18 is the minimum expected +- { +- if (S7.GetWordAt(PDU,17)!=0) +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- return LastError; +- } +- +- public int PlcHotStart() +- { +- int Length; +- +- LastError = 0; +- SendPacket(S7_HOT_START); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 18) // the minimum expected +- { +- if (S7.GetWordAt(PDU,17)!=0) +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- return LastError; +- } +- +- public int PlcColdStart() +- { +- int Length; +- +- LastError = 0; +- SendPacket(S7_COLD_START); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 18) // the minimum expected +- { +- if (S7.GetWordAt(PDU,17)!=0) +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- return LastError; +- } +- +- public int GetPlcStatus(IntByRef Status) +- { +- int Length; +- +- LastError = 0; +- SendPacket(S7_GET_STAT); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 30) // the minimum expected +- { +- if (S7.GetWordAt(PDU,27)==0) +- { +- switch (PDU[44]) +- { +- case S7.S7CpuStatusUnknown : +- case S7.S7CpuStatusRun : +- case S7.S7CpuStatusStop : Status.Value=PDU[44]; +- break; +- default : +- // Since RUN status is always 0x08 for all CPUs and CPs, STOP status +- // sometime can be coded as 0x03 (especially for old cpu...) +- Status.Value=S7.S7CpuStatusStop; +- } +- } +- else +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- return LastError; +- } +- +- public int SetSessionPassword(String Password) +- { +- byte[] pwd = {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; +- int Length; +- +- LastError = 0; +- // Adjusts the Password length to 8 +- if (Password.length()>8) +- Password=Password.substring(0, 8); +- else +- { +- while (Password.length()<8) +- Password=Password+" "; +- } +- +- try { +- pwd = Password.getBytes("UTF-8"); +- } catch (UnsupportedEncodingException ex) { +- LastError = errS7InvalidParams; +- } +- if (LastError==0) +- { +- // Encodes the password +- pwd[0]=(byte) (pwd[0] ^ 0x55); +- pwd[1]=(byte) (pwd[1] ^ 0x55); +- for (int c = 2; c < 8; c++) +- { +- pwd[c]=(byte) (pwd[c] ^ 0x55 ^ pwd[c-2]); +- } +- System.arraycopy(pwd, 0, S7_SET_PWD, 29, 8); +- // Sends the telegrem +- SendPacket(S7_SET_PWD); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 32) // the minimum expected +- { +- if (S7.GetWordAt(PDU,27)!=0) +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- } +- return LastError; +- } +- +- public int ClearSessionPassword() +- { +- int Length; +- +- LastError = 0; +- SendPacket(S7_CLR_PWD); +- if (LastError==0) +- { +- Length=RecvIsoPacket(); +- if (Length > 30) // the minimum expected +- { +- if (S7.GetWordAt(PDU,27)!=0) +- LastError = errS7FunctionError; +- } +- else +- LastError = errS7InvalidPDU; +- } +- return LastError; +- } +- +- public int GetProtection(S7Protection Protection) +- { +- S7Szl SZL = new S7Szl(256); +- +- LastError = ReadSZL(0x0232, 0x0004, SZL); +- if (LastError==0) +- { +- Protection.Update(SZL.Data); +- } +- return LastError; +- } +- +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++package Moka7; ++ ++import java.io.DataInputStream; ++import java.io.DataOutputStream; ++import java.io.IOException; ++import java.io.UnsupportedEncodingException; ++import java.net.InetSocketAddress; ++import java.net.Socket; ++import java.net.SocketAddress; ++import java.util.Date; ++ ++ ++/** ++ * ++ * @author Davide Nardella ++ */ ++public class S7Client ++{ ++ // WordLength ++ public static final int S7WLBit = 0x01; ++ public static final int S7WLByte = 0x02; ++ public static final int S7WLCounter = 0x1C; ++ public static final int S7WLTimer = 0x1D; ++ ++ // Error Codes ++ public static final int errTCPConnectionFailed = 0x0001; ++ public static final int errTCPDataSend = 0x0002; ++ public static final int errTCPDataRecv = 0x0003; ++ public static final int errTCPDataRecvTout = 0x0004; ++ public static final int errTCPConnectionReset = 0x0005; ++ public static final int errISOInvalidPDU = 0x0006; ++ public static final int errISOConnectionFailed = 0x0007; ++ public static final int errISONegotiatingPDU = 0x0008; ++ public static final int errS7InvalidPDU = 0x0009; ++ public static final int errS7DataRead = 0x000A; ++ public static final int errS7DataWrite = 0x000B; ++ public static final int errS7BufferTooSmall = 0x000C; ++ public static final int errS7FunctionError = 0x000D; ++ public static final int errS7InvalidParams = 0x000E; ++ ++ // Public fields ++ public boolean Connected = false; ++ public int LastError = 0; ++ public int RecvTimeout = 2000; ++ ++ // Privates ++ private static final int ISOTCP = 102; // ISOTCP Port ++ private static final int MinPduSize = 16; ++ private static final int DefaultPduSizeRequested = 480; ++ private static final int IsoHSize = 7; // TPKT+COTP Header Size ++ private static final int MaxPduSize = DefaultPduSizeRequested+IsoHSize; ++ ++ private Socket TCPSocket; ++ private final byte[] PDU = new byte[2048]; ++ ++ private DataInputStream InStream = null; ++ private DataOutputStream OutStream = null; ++ ++ private String IPAddress; ++ ++ private byte LocalTSAP_HI; ++ private byte LocalTSAP_LO; ++ private byte RemoteTSAP_HI; ++ private byte RemoteTSAP_LO; ++ private byte LastPDUType; ++ ++ private short ConnType = S7.PG; ++ private int _PDULength = 0; ++ ++ // Telegrams ++ // ISO Connection Request telegram (contains also ISO Header and COTP Header) ++ private static final byte ISO_CR[] = { ++ // TPKT (RFC1006 Header) ++ (byte)0x03, // RFC 1006 ID (3) ++ (byte)0x00, // Reserved, always 0 ++ (byte)0x00, // High part of packet lenght (entire frame, payload and TPDU included) ++ (byte)0x16, // Low part of packet lenght (entire frame, payload and TPDU included) ++ // COTP (ISO 8073 Header) ++ (byte)0x11, // PDU Size Length ++ (byte)0xE0, // CR - Connection Request ID ++ (byte)0x00, // Dst Reference HI ++ (byte)0x00, // Dst Reference LO ++ (byte)0x00, // Src Reference HI ++ (byte)0x01, // Src Reference LO ++ (byte)0x00, // Class + Options Flags ++ (byte)0xC0, // PDU Max Length ID ++ (byte)0x01, // PDU Max Length HI ++ (byte)0x0A, // PDU Max Length LO ++ (byte)0xC1, // Src TSAP Identifier ++ (byte)0x02, // Src TSAP Length (2 bytes) ++ (byte)0x01, // Src TSAP HI (will be overwritten) ++ (byte)0x00, // Src TSAP LO (will be overwritten) ++ (byte)0xC2, // Dst TSAP Identifier ++ (byte)0x02, // Dst TSAP Length (2 bytes) ++ (byte)0x01, // Dst TSAP HI (will be overwritten) ++ (byte)0x02 // Dst TSAP LO (will be overwritten) ++ }; ++ ++ // S7 PDU Negotiation Telegram (contains also ISO Header and COTP Header) ++ private static final byte S7_PN[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x19, ++ (byte)0x02, (byte)0xf0, (byte)0x80, // TPKT + COTP (see above for info) ++ (byte)0x32, (byte)0x01, (byte)0x00, (byte)0x00, ++ (byte)0x04, (byte)0x00, (byte)0x00, (byte)0x08, ++ (byte)0x00, (byte)0x00, (byte)0xf0, (byte)0x00, ++ (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01, ++ (byte)0x00, (byte)0x1e // PDU Length Requested = HI-LO 480 bytes ++ }; ++ ++ // S7 Read/Write Request Header (contains also ISO Header and COTP Header) ++ private static final byte S7_RW[] = { // 31-35 bytes ++ (byte)0x03,(byte)0x00, ++ (byte)0x00,(byte)0x1f, // Telegram Length (Data Size + 31 or 35) ++ (byte)0x02,(byte)0xf0, (byte)0x80, // COTP (see above for info) ++ (byte)0x32, // S7 Protocol ID ++ (byte)0x01, // Job Type ++ (byte)0x00,(byte)0x00, // Redundancy identification ++ (byte)0x05,(byte)0x00, // PDU Reference ++ (byte)0x00,(byte)0x0e, // Parameters Length ++ (byte)0x00,(byte)0x00, // Data Length = Size(bytes) + 4 ++ (byte)0x04, // Function 4 Read Var, 5 Write Var ++ (byte)0x01, // Items count ++ (byte)0x12, // Var spec. ++ (byte)0x0a, // Length of remaining bytes ++ (byte)0x10, // Syntax ID ++ S7WLByte, // Transport Size ++ (byte)0x00,(byte)0x00, // Num Elements ++ (byte)0x00,(byte)0x00, // DB Number (if any, else 0) ++ (byte)0x84, // Area Type ++ (byte)0x00,(byte)0x00,(byte)0x00, // Area Offset ++ // WR area ++ (byte)0x00, // Reserved ++ (byte)0x04, // Transport size ++ (byte)0x00,(byte)0x00, // Data Length * 8 (if not timer or counter) ++ }; ++ private static final int Size_RD = 31; ++ private static final int Size_WR = 35; ++ ++ // S7 Get Block Info Request Header (contains also ISO Header and COTP Header) ++ private static final byte S7_BI[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x05, ++ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, ++ (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12, ++ (byte)0x04, (byte)0x11, (byte)0x43, (byte)0x03, ++ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, ++ (byte)0x08, (byte)0x30, ++ (byte)0x41, // Block Type ++ (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, (byte)0x30, // ASCII Block Number ++ (byte)0x41 ++ }; ++ ++ // SZL First telegram request ++ private static final byte S7_SZL_FIRST[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x07, (byte)0x00, (byte)0x00, ++ (byte)0x05, (byte)0x00, // Sequence out ++ (byte)0x00, (byte)0x08, (byte)0x00, ++ (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12, ++ (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01, ++ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, ++ (byte)0x04, ++ (byte)0x00, (byte)0x00, // ID (29) ++ (byte)0x00, (byte)0x00 // Index (31) ++ }; ++ ++ // SZL Next telegram request ++ private static final byte S7_SZL_NEXT[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x06, ++ (byte)0x00, (byte)0x00, (byte)0x0c, (byte)0x00, ++ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, ++ (byte)0x08, (byte)0x12, (byte)0x44, (byte)0x01, ++ (byte)0x01, // Sequence ++ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, ++ (byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00 ++ }; ++ ++ // Get Date/Time request ++ private static final byte S7_GET_DT[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x38, ++ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, ++ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, ++ (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x01, ++ (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, ++ (byte)0x00 ++ }; ++ ++ // Set Date/Time command ++ private static final byte S7_SET_DT[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x89, ++ (byte)0x03, (byte)0x00, (byte)0x08, (byte)0x00, ++ (byte)0x0e, (byte)0x00, (byte)0x01, (byte)0x12, ++ (byte)0x04, (byte)0x11, (byte)0x47, (byte)0x02, ++ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, ++ (byte)0x0a, (byte)0x00, (byte)0x19, // Hi part of Year ++ (byte)0x13, // Lo part of Year ++ (byte)0x12, // Month ++ (byte)0x06, // Day ++ (byte)0x17, // Hour ++ (byte)0x37, // Min ++ (byte)0x13, // Sec ++ (byte)0x00, (byte)0x01 // ms + Day of week ++ }; ++ ++ // S7 STOP request ++ private static final byte S7_STOP[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0e, ++ (byte)0x00, (byte)0x00, (byte)0x10, (byte)0x00, ++ (byte)0x00, (byte)0x29, (byte)0x00, (byte)0x00, ++ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, ++ (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52, ++ (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41, ++ (byte)0x4d ++ }; ++ ++ // S7 HOT Start request ++ private static final byte S7_HOT_START[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0c, ++ (byte)0x00, (byte)0x00, (byte)0x14, (byte)0x00, ++ (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00, ++ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, ++ (byte)0xfd, (byte)0x00, (byte)0x00, (byte)0x09, ++ (byte)0x50, (byte)0x5f, (byte)0x50, (byte)0x52, ++ (byte)0x4f, (byte)0x47, (byte)0x52, (byte)0x41, ++ (byte)0x4d ++ }; ++ ++ // S7 COLD Start request ++ private static final byte S7_COLD_START[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x27, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x0f, ++ (byte)0x00, (byte)0x00, (byte)0x16, (byte)0x00, ++ (byte)0x00, (byte)0x28, (byte)0x00, (byte)0x00, ++ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, ++ (byte)0xfd, (byte)0x00, (byte)0x02, (byte)0x43, ++ (byte)0x20, (byte)0x09, (byte)0x50, (byte)0x5f, ++ (byte)0x50, (byte)0x52, (byte)0x4f, (byte)0x47, ++ (byte)0x52, (byte)0x41, (byte)0x4d ++ }; ++ ++ // S7 Get PLC Status ++ private static final byte S7_GET_STAT[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x21, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x2c, ++ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, ++ (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x12, ++ (byte)0x04, (byte)0x11, (byte)0x44, (byte)0x01, ++ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, ++ (byte)0x04, (byte)0x04, (byte)0x24, (byte)0x00, ++ (byte)0x00 ++ }; ++ ++ // S7 Set Session Password ++ private static final byte S7_SET_PWD[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x25, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x27, ++ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, ++ (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x12, ++ (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x01, ++ (byte)0x00, (byte)0xff, (byte)0x09, (byte)0x00, ++ (byte)0x08, ++ // 8 Char Encoded Password ++ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, ++ (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 ++ }; ++ ++ // S7 Clear Session Password ++ private static final byte S7_CLR_PWD[] = { ++ (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x1d, ++ (byte)0x02, (byte)0xf0, (byte)0x80, (byte)0x32, ++ (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x29, ++ (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x00, ++ (byte)0x04, (byte)0x00, (byte)0x01, (byte)0x12, ++ (byte)0x04, (byte)0x11, (byte)0x45, (byte)0x02, ++ (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x00, ++ (byte)0x00 ++ }; ++ ++ public S7Client() ++ { ++ // Placeholder for future implementations ++ } ++ ++ public static String ErrorText(int Error) ++ { ++ switch (Error) ++ { ++ case errTCPConnectionFailed : ++ return "TCP Connection failed."; ++ case errTCPDataSend : ++ return "TCP Sending error."; ++ case errTCPDataRecv : ++ return "TCP Receiving error."; ++ case errTCPDataRecvTout : ++ return "Data Receiving timeout."; ++ case errTCPConnectionReset : ++ return "Connection reset by the peer."; ++ case errISOInvalidPDU : ++ return "Invalid ISO PDU received."; ++ case errISOConnectionFailed : ++ return "ISO connection refused by the CPU."; ++ case errISONegotiatingPDU : ++ return "ISO error negotiating the PDU length."; ++ case errS7InvalidPDU : ++ return "Invalid S7 PDU received."; ++ case errS7DataRead : ++ return "S7 Error reading data from the CPU."; ++ case errS7DataWrite : ++ return "S7 Error writing data to the CPU."; ++ case errS7BufferTooSmall : ++ return "The Buffer supplied to the function is too small."; ++ case errS7FunctionError : ++ return "S7 function refused by the CPU."; ++ case errS7InvalidParams : ++ return "Invalid parameters supplied to the function."; ++ default : ++ return "Unknown error : 0x"+Integer.toHexString(Error); ++ } ++ } ++ ++ private int TCPConnect() ++ { ++ SocketAddress sockaddr = new InetSocketAddress(IPAddress, ISOTCP); ++ LastError=0; ++ try { ++ TCPSocket = new Socket(); ++ TCPSocket.connect(sockaddr ,5000); ++ TCPSocket.setTcpNoDelay(true); ++ InStream = new DataInputStream(TCPSocket.getInputStream()); ++ OutStream = new DataOutputStream(TCPSocket.getOutputStream()); ++ } ++ catch (IOException e) { ++ LastError=errTCPConnectionFailed; ++ } ++ return LastError; ++ } ++ ++ private int WaitForData(int Size, int Timeout) ++ { ++ int cnt = 0; ++ LastError=0; ++ int SizeAvail; ++ boolean Expired = false; ++ try ++ { ++ SizeAvail=InStream.available(); ++ while ((SizeAvailTimeout; ++ // If timeout we clean the buffer ++ if (Expired && (SizeAvail>0) && (LastError==0)) ++ InStream.read(PDU, 0, SizeAvail); ++ } ++ } ++ catch (IOException ex) ++ { ++ LastError=errTCPDataRecvTout; ++ } ++ if (cnt>=Timeout) ++ { ++ LastError=errTCPDataRecvTout; ++ } ++ return LastError; ++ } ++ ++ private int RecvPacket(byte[] Buffer, int Start, int Size) ++ { ++ int BytesRead=0; ++ LastError=WaitForData(Size,RecvTimeout); ++ if (LastError==0) ++ { ++ try { ++ BytesRead = InStream.read(Buffer, Start, Size); ++ } catch (IOException ex) { ++ LastError=errTCPDataRecv; ++ } ++ if (BytesRead==0) ++ LastError=errTCPConnectionReset; ++ } ++ return LastError; ++ } ++ ++ private void SendPacket(byte[] Buffer, int Len) ++ { ++ LastError = 0; ++ try { ++ OutStream.write(Buffer,0,Len); ++ OutStream.flush(); ++ } catch (IOException ex) { ++ LastError = errTCPDataSend; ++ } ++ } ++ private void SendPacket(byte[] Buffer) ++ { ++ SendPacket(Buffer,Buffer.length); ++ } ++ ++ private int RecvIsoPacket() ++ { ++ Boolean Done = false; ++ int Size = 0; ++ while ((LastError==0) && !Done) ++ { ++ // Get TPKT (4 bytes) ++ RecvPacket(PDU, 0, 4); ++ if (LastError==0) ++ { ++ Size=S7.GetWordAt(PDU,2); ++ // Check 0 bytes Data Packet (only TPKT+COTP = 7 bytes) ++ if (Size==IsoHSize) ++ RecvPacket(PDU,4, 3); // Skip remaining 3 bytes and Done is still false ++ else ++ { ++ if ((Size>MaxPduSize) || (Size16 && <247 ++ } ++ } ++ } ++ if (LastError==0) ++ { ++ RecvPacket(PDU,4, 3); // Skip remaining 3 COTP bytes ++ LastPDUType=PDU[5]; // Stores PDU Type, we need it ++ // Receives the S7 Payload ++ RecvPacket(PDU, 7, Size-IsoHSize); ++ } ++ if (LastError==0) ++ return Size; ++ else ++ return 0; ++ } ++ ++ private int ISOConnect() ++ { ++ int Size; ++ ISO_CR[16]=LocalTSAP_HI; ++ ISO_CR[17]=LocalTSAP_LO; ++ ISO_CR[20]=RemoteTSAP_HI; ++ ISO_CR[21]=RemoteTSAP_LO; ++ ++ // Sends the connection request telegram ++ SendPacket(ISO_CR); ++ if (LastError==0) ++ { ++ // Gets the reply (if any) ++ Size=RecvIsoPacket(); ++ if (LastError==0) ++ { ++ if (Size==22) ++ { ++ if (LastPDUType!=(byte)0xD0) // 0xD0 = CC Connection confirm ++ LastError=errISOConnectionFailed; ++ } ++ else ++ LastError=errISOInvalidPDU; ++ } ++ } ++ return LastError; ++ } ++ ++ private int NegotiatePduLength() ++ { ++ int Length; ++ // Set PDU Size Requested ++ S7.SetWordAt(S7_PN,23,DefaultPduSizeRequested); ++ // Sends the connection request telegram ++ SendPacket(S7_PN); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (LastError==0) ++ { ++ // check S7 Error ++ if ((Length==27) && (PDU[17]==0) && (PDU[18]==0)) // 20 = size of Negotiate Answer ++ { ++ // Get PDU Size Negotiated ++ _PDULength = S7.GetWordAt(PDU,25); ++ if (_PDULength>0) ++ return 0; ++ else ++ LastError=errISONegotiatingPDU; ++ } ++ else ++ LastError=errISONegotiatingPDU; ++ } ++ } ++ return LastError; ++ } ++ ++ public void SetConnectionType(short ConnectionType) ++ { ++ ConnType=ConnectionType; ++ } ++ ++ public int Connect() ++ { ++ LastError=0; ++ if (!Connected) ++ { ++ TCPConnect(); ++ if (LastError==0) // First stage : TCP Connection ++ { ++ ISOConnect(); ++ if (LastError==0) // Second stage : ISOTCP (ISO 8073) Connection ++ { ++ LastError=NegotiatePduLength(); // Third stage : S7 PDU negotiation ++ } ++ } ++ } ++ Connected=LastError==0; ++ ++ // In case the connection is not completely established (TCP connection + ISO connection + PDU negotiation) ++ // we close the socket and its IO streams to revert the object back to pre-Connect() state ++ if (!Connected) ++ { ++ if (TCPSocket != null) { ++ try { ++ TCPSocket.close(); ++ } catch (IOException ex) { ++ } ++ } ++ if (InStream != null) { ++ try { ++ InStream.close(); ++ } catch (IOException ex) { ++ } ++ } ++ if (OutStream != null) { ++ try { ++ OutStream.close(); ++ } catch (IOException ex) { ++ } ++ } ++ _PDULength = 0; ++ } ++ ++ return LastError; ++ } ++ ++ public void Disconnect() ++ { ++ if (Connected) ++ { ++ try { ++ OutStream.close(); ++ InStream.close(); ++ TCPSocket.close(); ++ _PDULength=0; ++ } catch (IOException ex) { ++ } ++ Connected=false; ++ } ++ } ++ ++ public int ConnectTo(String Address, int Rack, int Slot) ++ { ++ int RemoteTSAP=(ConnType<<8)+ (Rack * 0x20) + Slot; ++ SetConnectionParams(Address, 0x0100, RemoteTSAP); ++ return Connect(); ++ } ++ ++ public int PDULength() ++ { ++ return _PDULength; ++ } ++ ++ public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP) ++ { ++ int LocTSAP = LocalTSAP & 0x0000FFFF; ++ int RemTSAP = RemoteTSAP & 0x0000FFFF; ++ IPAddress = Address; ++ LocalTSAP_HI = (byte) (LocTSAP>>8); ++ LocalTSAP_LO = (byte) (LocTSAP & 0x00FF); ++ RemoteTSAP_HI= (byte) (RemTSAP>>8); ++ RemoteTSAP_LO= (byte) (RemTSAP & 0x00FF); ++ } ++ ++ public int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) ++ { ++ int Address; ++ int NumElements; ++ int MaxElements; ++ int TotElements; ++ int SizeRequested; ++ int Length; ++ int Offset = 0; ++ byte WordSize = 1; ++ ++ LastError=0; ++ ++ // If we are addressing Timers or counters the element size is 2 ++ if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) ++ WordSize = 2; ++ ++ MaxElements=(_PDULength-18) / WordSize; // 18 = Reply telegram header ++ TotElements=Amount; ++ ++ while ((TotElements>0) && (LastError==0)) ++ { ++ NumElements=TotElements; ++ if (NumElements>MaxElements) ++ NumElements=MaxElements; ++ ++ SizeRequested = NumElements * WordSize; ++ ++ // Setup the telegram ++ System.arraycopy(S7_RW, 0, PDU, 0, Size_RD); ++ // Set DB Number ++ PDU[27] = (byte) Area; ++ // Set Area ++ if (Area==S7.S7AreaDB) ++ S7.SetWordAt(PDU,25,DBNumber); ++ ++ PDU[22] = (byte) WordLength; ++ // Adjusts Start and word length ++ if ((WordLength==S7WLBit) || (WordLength==S7WLTimer) || (WordLength==S7WLCounter)) ++ { ++ Address = Start; ++ } ++ else ++ { ++ Address = Start<<3; ++ } ++ ++ // Num elements ++ S7.SetWordAt(PDU,23,NumElements); ++ ++ // Address into the PLC (only 3 bytes) ++ PDU[30] = (byte) (Address & 0x0FF); ++ Address = Address >> 8; ++ PDU[29] = (byte) (Address & 0x0FF); ++ Address = Address >> 8; ++ PDU[28] = (byte) (Address & 0x0FF); ++ ++ // Transport Size ++ PDU[32] = 0x04; ++ if (WordLength==S7WLBit) ++ { ++ PDU[32] = 0x03; ++ } ++ else if ((WordLength==S7WLTimer) || (WordLength==S7WLCounter)) ++ { ++ PDU[32] = 0x09; ++ } ++ ++ SendPacket(PDU, Size_RD); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (LastError==0) ++ { ++ if (Length>=25) ++ { ++ if ((Length-25==SizeRequested) && (PDU[21]==(byte)0xFF)) ++ { ++ System.arraycopy(PDU, 25, Data, Offset, SizeRequested); ++ Offset+=SizeRequested; ++ } ++ else ++ LastError = errS7DataRead; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ } ++ ++ TotElements -= NumElements; ++ Start += NumElements*WordSize; ++ } ++ return LastError; ++ } ++ ++ public int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) ++ { ++ int Address; ++ int NumElements; ++ int MaxElements; ++ int TotElements; ++ int DataSize; ++ int IsoSize; ++ int Length; ++ int Offset = 0; ++ byte WordSize = 1; ++ ++ LastError=0; ++ ++ // If we are addressing Timers or counters the element size is 2 ++ if ((Area==S7.S7AreaCT) || (Area==S7.S7AreaTM)) ++ WordSize = 2; ++ ++ MaxElements=(_PDULength-35) / WordSize; // 35 = Reply telegram header ++ TotElements=Amount; ++ ++ while ((TotElements>0) && (LastError==0)) ++ { ++ NumElements=TotElements; ++ if (NumElements>MaxElements) ++ NumElements=MaxElements; ++ ++ DataSize = NumElements * WordSize; ++ IsoSize = Size_WR + DataSize; ++ ++ // Setup the telegram ++ System.arraycopy(S7_RW, 0, PDU, 0, Size_WR); ++ // Whole telegram Size ++ S7.SetWordAt(PDU,2,IsoSize); ++ // Data Length ++ Length=DataSize+4; ++ S7.SetWordAt(PDU,15,Length); ++ // Function ++ PDU[17]= (byte) 0x05; ++ // Set DB Number ++ PDU[27] = (byte) Area; ++ if (Area==S7.S7AreaDB) ++ S7.SetWordAt(PDU,25,DBNumber); ++ ++ PDU[22] = (byte) WordLength; ++ // Adjusts Start and word length ++ if ((WordLength==S7WLBit) || (WordLength==S7WLTimer) || (WordLength==S7WLCounter)) ++ { ++ Address = Start; ++ Length = DataSize; ++ } ++ else ++ { ++ Address = Start<<3; ++ Length = DataSize<<3; ++ } ++ ++ // Num elements ++ S7.SetWordAt(PDU,23,NumElements); ++ // Address into the PLC ++ PDU[30] = (byte) (Address & 0x0FF); ++ Address = Address >> 8; ++ PDU[29] = (byte) (Address & 0x0FF); ++ Address = Address >> 8; ++ PDU[28] = (byte) (Address & 0x0FF); ++ ++ // Transport Size ++ PDU[32] = 0x04; ++ if (WordLength==S7WLBit) ++ { ++ PDU[32] = 0x03; ++ } ++ else if ((WordLength==S7WLTimer) || (WordLength==S7WLCounter)) ++ { ++ PDU[32] = 0x09; ++ } ++ ++ // Length ++ S7.SetWordAt(PDU,33,Length); ++ ++ // Copies the Data ++ System.arraycopy(Data, Offset, PDU, 35, DataSize); ++ ++ SendPacket(PDU, IsoSize); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (LastError==0) ++ { ++ if (Length==22) ++ { ++ if ((S7.GetWordAt(PDU,17)!=0) || (PDU[21]!=(byte)0xFF)) ++ LastError = errS7DataWrite; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ } ++ ++ Offset+=DataSize; ++ TotElements -= NumElements; ++ Start += NumElements*WordSize; ++ } ++ return LastError; ++ } ++ ++ public int GetAgBlockInfo(int BlockType, int BlockNumber, S7BlockInfo Block) ++ { ++ int Length; ++ LastError=0; ++ // Block Type ++ S7_BI[30] = (byte) BlockType; ++ // Block Number ++ S7_BI[31]=(byte) ((BlockNumber / 10000)+0x30); ++ BlockNumber=BlockNumber % 10000; ++ S7_BI[32]=(byte) ((BlockNumber / 1000)+0x30); ++ BlockNumber=BlockNumber % 1000; ++ S7_BI[33]=(byte) ((BlockNumber / 100)+0x30); ++ BlockNumber=BlockNumber % 100; ++ S7_BI[34]=(byte) ((BlockNumber / 10)+0x30); ++ BlockNumber=BlockNumber % 10; ++ S7_BI[35]=(byte) ((BlockNumber / 1)+0x30); ++ ++ SendPacket(S7_BI); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 32) // the minimum expected ++ { ++ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) ++ { ++ Block.Update(PDU, 42); ++ } ++ else ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ ++ return LastError; ++ } ++ /** ++ * ++ * @param DBNumber DB Number ++ * @param Buffer Destination buffer ++ * @param SizeRead How many bytes were read ++ * @return ++ */ ++ public int DBGet(int DBNumber, byte[] Buffer, IntByRef SizeRead) ++ { ++ S7BlockInfo Block = new S7BlockInfo(); ++ // Query the DB Length ++ LastError = GetAgBlockInfo(S7.Block_DB, DBNumber, Block); ++ if (LastError==0) ++ { ++ int SizeToRead = Block.MC7Size(); ++ // Checks the room ++ if (SizeToRead<=Buffer.length) ++ { ++ LastError=ReadArea(S7.S7AreaDB, DBNumber, 0, SizeToRead, S7WLByte, Buffer); ++ if (LastError==0) ++ SizeRead.Value=SizeToRead; ++ } ++ else ++ LastError=errS7BufferTooSmall; ++ } ++ return LastError; ++ } ++ ++ public int ReadSZL(int ID, int Index, S7Szl SZL) ++ { ++ int Length; ++ int DataSZL; ++ int Offset = 0; ++ boolean Done = false; ++ boolean First = true; ++ byte Seq_in =0x00; ++ int Seq_out =0x0000; ++ ++ LastError=0; ++ SZL.DataSize=0; ++ do ++ { ++ if (First) ++ { ++ S7.SetWordAt(S7_SZL_FIRST, 11, ++Seq_out); ++ S7.SetWordAt(S7_SZL_FIRST, 29, ID); ++ S7.SetWordAt(S7_SZL_FIRST, 31, Index); ++ SendPacket(S7_SZL_FIRST); ++ } ++ else ++ { ++ S7.SetWordAt(S7_SZL_NEXT, 11, ++Seq_out); ++ PDU[24] = (byte)Seq_in; ++ SendPacket(S7_SZL_NEXT); ++ } ++ if (LastError!=0) ++ return LastError; ++ ++ Length=RecvIsoPacket(); ++ if (LastError==0) ++ { ++ if (First) ++ { ++ if (Length > 32) // the minimum expected ++ { ++ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) ++ { ++ // Gets Amount of this slice ++ DataSZL=S7.GetWordAt(PDU,31)-8; // Skips extra params (ID, Index ...) ++ Done=PDU[26]==0x00; ++ Seq_in=(byte)PDU[24]; // Slice sequence ++ ++ SZL.LENTHDR=S7.GetWordAt(PDU, 37); ++ SZL.N_DR=S7.GetWordAt(PDU, 39); ++ SZL.Copy(PDU, 41, Offset, DataSZL); ++ Offset+=DataSZL; ++ SZL.DataSize+=DataSZL; ++ } ++ else ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ else ++ { ++ if (Length > 32) // the minimum expected ++ { ++ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) ++ { ++ // Gets Amount of this slice ++ DataSZL=S7.GetWordAt(PDU,31); ++ Done=PDU[26]==0x00; ++ Seq_in=(byte)PDU[24]; // Slice sequence ++ SZL.Copy(PDU, 37, Offset, DataSZL); ++ Offset+=DataSZL; ++ SZL.DataSize+=DataSZL; ++ } ++ else ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ } ++ First=false; ++ } ++ while(!Done && (LastError==0)); ++ ++ return LastError; ++ } ++ ++ public int GetCpuInfo(S7CpuInfo Info) ++ { ++ S7Szl SZL = new S7Szl(1024); ++ ++ LastError = ReadSZL(0x001C, 0x0000, SZL); ++ if (LastError==0) ++ { ++ Info.Update(SZL.Data, 0); ++ } ++ return LastError; ++ } ++ ++ public int GetCpInfo(S7CpInfo Info) ++ { ++ S7Szl SZL = new S7Szl(1024); ++ ++ LastError = ReadSZL(0x0131, 0x0001, SZL); ++ if (LastError==0) ++ { ++ Info.Update(SZL.Data, 0); ++ } ++ return LastError; ++ } ++ ++ public int GetOrderCode(S7OrderCode Code) ++ { ++ S7Szl SZL = new S7Szl(1024); ++ ++ LastError = ReadSZL(0x0011, 0x0000, SZL); ++ if (LastError==0) ++ { ++ Code.Update(SZL.Data, 0, SZL.DataSize); ++ } ++ return LastError; ++ } ++ ++ public int GetPlcDateTime(Date DateTime) ++ { ++ int Length; ++ ++ LastError = 0; ++ SendPacket(S7_GET_DT); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 30) // the minimum expected ++ { ++ if ((S7.GetWordAt(PDU,27)==0) && (PDU[29]==(byte)0xFF)) ++ { ++ DateTime=S7.GetDateAt(PDU, 34); ++ } ++ else ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ ++ return LastError; ++ } ++ ++ public int SetPlcDateTime(Date DateTime) ++ { ++ int Length; ++ ++ LastError = 0; ++ S7.SetDateAt(S7_SET_DT, 31, DateTime); ++ ++ SendPacket(S7_SET_DT); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 30) // the minimum expected ++ { ++ if (S7.GetWordAt(PDU,27)!=0) ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ ++ return LastError; ++ } ++ ++ public int SetPlcSystemDateTime() ++ { ++ return SetPlcDateTime(new Date()); ++ } ++ ++ public int PlcStop() ++ { ++ int Length; ++ ++ LastError = 0; ++ SendPacket(S7_STOP); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 18) // 18 is the minimum expected ++ { ++ if (S7.GetWordAt(PDU,17)!=0) ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ return LastError; ++ } ++ ++ public int PlcHotStart() ++ { ++ int Length; ++ ++ LastError = 0; ++ SendPacket(S7_HOT_START); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 18) // the minimum expected ++ { ++ if (S7.GetWordAt(PDU,17)!=0) ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ return LastError; ++ } ++ ++ public int PlcColdStart() ++ { ++ int Length; ++ ++ LastError = 0; ++ SendPacket(S7_COLD_START); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 18) // the minimum expected ++ { ++ if (S7.GetWordAt(PDU,17)!=0) ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ return LastError; ++ } ++ ++ public int GetPlcStatus(IntByRef Status) ++ { ++ int Length; ++ ++ LastError = 0; ++ SendPacket(S7_GET_STAT); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 30) // the minimum expected ++ { ++ if (S7.GetWordAt(PDU,27)==0) ++ { ++ switch (PDU[44]) ++ { ++ case S7.S7CpuStatusUnknown : ++ case S7.S7CpuStatusRun : ++ case S7.S7CpuStatusStop : Status.Value=PDU[44]; ++ break; ++ default : ++ // Since RUN status is always 0x08 for all CPUs and CPs, STOP status ++ // sometime can be coded as 0x03 (especially for old cpu...) ++ Status.Value=S7.S7CpuStatusStop; ++ } ++ } ++ else ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ return LastError; ++ } ++ ++ public int SetSessionPassword(String Password) ++ { ++ byte[] pwd = {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; ++ int Length; ++ ++ LastError = 0; ++ // Adjusts the Password length to 8 ++ if (Password.length()>8) ++ Password=Password.substring(0, 8); ++ else ++ { ++ while (Password.length()<8) ++ Password=Password+" "; ++ } ++ ++ try { ++ pwd = Password.getBytes("UTF-8"); ++ } catch (UnsupportedEncodingException ex) { ++ LastError = errS7InvalidParams; ++ } ++ if (LastError==0) ++ { ++ // Encodes the password ++ pwd[0]=(byte) (pwd[0] ^ 0x55); ++ pwd[1]=(byte) (pwd[1] ^ 0x55); ++ for (int c = 2; c < 8; c++) ++ { ++ pwd[c]=(byte) (pwd[c] ^ 0x55 ^ pwd[c-2]); ++ } ++ System.arraycopy(pwd, 0, S7_SET_PWD, 29, 8); ++ // Sends the telegrem ++ SendPacket(S7_SET_PWD); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 32) // the minimum expected ++ { ++ if (S7.GetWordAt(PDU,27)!=0) ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ } ++ return LastError; ++ } ++ ++ public int ClearSessionPassword() ++ { ++ int Length; ++ ++ LastError = 0; ++ SendPacket(S7_CLR_PWD); ++ if (LastError==0) ++ { ++ Length=RecvIsoPacket(); ++ if (Length > 30) // the minimum expected ++ { ++ if (S7.GetWordAt(PDU,27)!=0) ++ LastError = errS7FunctionError; ++ } ++ else ++ LastError = errS7InvalidPDU; ++ } ++ return LastError; ++ } ++ ++ public int GetProtection(S7Protection Protection) ++ { ++ S7Szl SZL = new S7Szl(256); ++ ++ LastError = ReadSZL(0x0232, 0x0004, SZL); ++ if (LastError==0) ++ { ++ Protection.Update(SZL.Data); ++ } ++ return LastError; ++ } ++ ++} +diff U3 S7CpInfo.java S7CpInfo.java +--- S7CpInfo.java Thu Mar 23 15:34:52 2017 ++++ S7CpInfo.java Tue Aug 08 18:53:37 2017 +@@ -1,41 +1,41 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +-package Moka7; +- +-/** +- * +- * @author Davide +- */ +-public class S7CpInfo { +- +- public int MaxPduLength; +- public int MaxConnections; +- public int MaxMpiRate; +- public int MaxBusRate; +- +- protected void Update(byte[] Src, int Pos) +- { +- MaxPduLength = S7.GetShortAt(Src, 2); +- MaxConnections = S7.GetShortAt(Src, 4); +- MaxMpiRate = S7.GetDIntAt(Src, 6); +- MaxBusRate = S7.GetDIntAt(Src, 10); +- } +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++package Moka7; ++ ++/** ++ * ++ * @author Davide Nardella ++ */ ++public class S7CpInfo { ++ ++ public int MaxPduLength; ++ public int MaxConnections; ++ public int MaxMpiRate; ++ public int MaxBusRate; ++ ++ protected void Update(byte[] Src, int Pos) ++ { ++ MaxPduLength = S7.GetShortAt(Src, 2); ++ MaxConnections = S7.GetShortAt(Src, 4); ++ MaxMpiRate = S7.GetDIntAt(Src, 6); ++ MaxBusRate = S7.GetDIntAt(Src, 10); ++ } ++} +diff U3 S7CpuInfo.java S7CpuInfo.java +--- S7CpuInfo.java Thu Mar 23 15:34:52 2017 ++++ S7CpuInfo.java Tue Aug 08 18:53:37 2017 +@@ -1,57 +1,57 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +-package Moka7; +- +-/** +- * +- * @author Davide +- */ +-public class S7CpuInfo { +- +- private final int BufSize = 256; +- protected byte[] Buffer = new byte[BufSize]; +- +- protected void Update(byte[] Src, int Pos) +- { +- System.arraycopy(Src, Pos, Buffer, 0, BufSize); +- } +- +- public String ModuleTypeName() +- { +- return S7.GetStringAt(Buffer,172,32); +- } +- public String SerialNumber() +- { +- return S7.GetStringAt(Buffer,138,24); +- } +- public String ASName() +- { +- return S7.GetStringAt(Buffer,2,24); +- } +- public String Copyright() +- { +- return S7.GetStringAt(Buffer,104,26); +- } +- public String ModuleName() +- { +- return S7.GetStringAt(Buffer,36,24); +- } +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++package Moka7; ++ ++/** ++ * ++ * @author Davide Nardella ++ */ ++public class S7CpuInfo { ++ ++ private final int BufSize = 256; ++ protected byte[] Buffer = new byte[BufSize]; ++ ++ protected void Update(byte[] Src, int Pos) ++ { ++ System.arraycopy(Src, Pos, Buffer, 0, BufSize); ++ } ++ ++ public String ModuleTypeName() ++ { ++ return S7.GetStringAt(Buffer,172,32); ++ } ++ public String SerialNumber() ++ { ++ return S7.GetStringAt(Buffer,138,24); ++ } ++ public String ASName() ++ { ++ return S7.GetStringAt(Buffer,2,24); ++ } ++ public String Copyright() ++ { ++ return S7.GetStringAt(Buffer,104,26); ++ } ++ public String ModuleName() ++ { ++ return S7.GetStringAt(Buffer,36,24); ++ } ++} +diff U3 S7OrderCode.java S7OrderCode.java +--- S7OrderCode.java Thu Mar 23 15:34:52 2017 ++++ S7OrderCode.java Tue Aug 08 18:53:37 2017 +@@ -1,46 +1,46 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +-package Moka7; +- +-/** +- * +- * @author Davide +- */ +-public class S7OrderCode { +- +- public int V1; +- public int V2; +- public int V3; +- protected byte[] Buffer = new byte[1024]; +- +- protected void Update(byte[] Src, int Pos, int Size) +- { +- System.arraycopy(Src, Pos, Buffer, 0, Size); +- V1 = (byte) Src[Size-3]; +- V2 = (byte) Src[Size-2]; +- V3 = (byte) Src[Size-1]; +- } +- +- public String Code() +- { +- return S7.GetStringAt(Buffer, 2, 20); +- } +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++package Moka7; ++ ++/** ++ * ++ * @author Davide Nardella ++ */ ++public class S7OrderCode { ++ ++ public int V1; ++ public int V2; ++ public int V3; ++ protected byte[] Buffer = new byte[1024]; ++ ++ protected void Update(byte[] Src, int Pos, int Size) ++ { ++ System.arraycopy(Src, Pos, Buffer, 0, Size); ++ V1 = (byte) Src[Size-3]; ++ V2 = (byte) Src[Size-2]; ++ V3 = (byte) Src[Size-1]; ++ } ++ ++ public String Code() ++ { ++ return S7.GetStringAt(Buffer, 2, 20); ++ } ++} +diff U3 S7Protection.java S7Protection.java +--- S7Protection.java Thu Mar 23 15:34:52 2017 ++++ S7Protection.java Tue Aug 08 18:53:37 2017 +@@ -1,38 +1,43 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +-package Moka7; +- +-// See §33.19 of "System Software for S7-300/400 System and Standard Functions" +-public class S7Protection { +- public int sch_schal; +- public int sch_par; +- public int sch_rel; +- public int bart_sch; +- public int anl_sch; +- protected void Update(byte[] Src) +- { +- sch_schal = S7.GetWordAt(Src,2); +- sch_par = S7.GetWordAt(Src,4); +- sch_rel = S7.GetWordAt(Src,6); +- bart_sch = S7.GetWordAt(Src,8); +- anl_sch = S7.GetWordAt(Src,10); +- } +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++package Moka7; ++ ++/** ++ * ++ * @author Davide Nardella ++ */ ++ ++// See §33.19 of "System Software for S7-300/400 System and Standard Functions" ++public class S7Protection { ++ public int sch_schal; ++ public int sch_par; ++ public int sch_rel; ++ public int bart_sch; ++ public int anl_sch; ++ protected void Update(byte[] Src) ++ { ++ sch_schal = S7.GetWordAt(Src,2); ++ sch_par = S7.GetWordAt(Src,4); ++ sch_rel = S7.GetWordAt(Src,6); ++ bart_sch = S7.GetWordAt(Src,8); ++ anl_sch = S7.GetWordAt(Src,10); ++ } ++} +diff U3 S7Szl.java S7Szl.java +--- S7Szl.java Thu Mar 23 15:34:52 2017 ++++ S7Szl.java Tue Aug 08 18:53:37 2017 +@@ -1,42 +1,42 @@ +-/*=============================================================================| +-| PROJECT Moka7 1.0.2 | +-|==============================================================================| +-| Copyright (C) 2013, 2016 Davide Nardella | +-| All rights reserved. | +-|==============================================================================| +-| SNAP7 is free software: you can redistribute it and/or modify | +-| it under the terms of the Lesser GNU General Public License as published by | +-| the Free Software Foundation, either version 3 of the License, or under | +-| EPL Eclipse Public License 1.0. | +-| | +-| This means that you have to chose in advance which take before you import | +-| the library into your project. | +-| | +-| SNAP7 is distributed in the hope that it will be useful, | +-| but WITHOUT ANY WARRANTY; without even the implied warranty of | +-| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | +-| decide to adopt. | +-| | +-|=============================================================================*/ +-package Moka7; +- +-/** +- * +- * @author Davide +- */ +-public class S7Szl { +- +- public int LENTHDR; +- public int N_DR; +- public int DataSize; +- public byte Data[]; +- +- public S7Szl(int BufferSize) +- { +- Data = new byte[BufferSize]; +- } +- protected void Copy(byte[] Src, int SrcPos, int DestPos, int Size) +- { +- System.arraycopy(Src, SrcPos, Data, DestPos, Size); +- } +-} ++/*=============================================================================| ++| PROJECT Moka7 1.0.2 | ++|==============================================================================| ++| Copyright (C) 2013, 2016 Davide Nardella | ++| All rights reserved. | ++|==============================================================================| ++| SNAP7 is free software: you can redistribute it and/or modify | ++| it under the terms of the Lesser GNU General Public License as published by | ++| the Free Software Foundation, either version 3 of the License, or under | ++| EPL Eclipse Public License 1.0. | ++| | ++| This means that you have to chose in advance which take before you import | ++| the library into your project. | ++| | ++| SNAP7 is distributed in the hope that it will be useful, | ++| but WITHOUT ANY WARRANTY; without even the implied warranty of | ++| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE whatever license you | ++| decide to adopt. | ++| | ++|=============================================================================*/ ++package Moka7; ++ ++/** ++ * ++ * @author Davide Nardella ++ */ ++public class S7Szl { ++ ++ public int LENTHDR; ++ public int N_DR; ++ public int DataSize; ++ public byte Data[]; ++ ++ public S7Szl(int BufferSize) ++ { ++ Data = new byte[BufferSize]; ++ } ++ protected void Copy(byte[] Src, int SrcPos, int DestPos, int Size) ++ { ++ System.arraycopy(Src, SrcPos, Data, DestPos, Size); ++ } ++} diff --git a/bundles/org.openhab.binding.plclogo/pom.xml b/bundles/org.openhab.binding.plclogo/pom.xml index 0e39b02020976..e101548a91627 100644 --- a/bundles/org.openhab.binding.plclogo/pom.xml +++ b/bundles/org.openhab.binding.plclogo/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.plclogo diff --git a/bundles/org.openhab.binding.plclogo/src/main/feature/feature.xml b/bundles/org.openhab.binding.plclogo/src/main/feature/feature.xml index a357f22f4f84a..15145b5edaa3a 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.plclogo/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.plclogo/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.plclogo/${project.version} + diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoBindingConstants.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoBindingConstants.java index 00bd25097929a..20900653f6964 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoBindingConstants.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoBindingConstants.java @@ -1,191 +1,190 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.plclogo.internal; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.thing.ThingTypeUID; - -/** - * The {@link PLCLogoBindingConstants} class defines common constants, which are - * used across the whole binding. - * - * @author Alexander Falkenstern - Initial contribution - */ -@NonNullByDefault -public class PLCLogoBindingConstants { - - public static final String BINDING_ID = "plclogo"; - - // List of all thing type UIDs - public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device"); - public static final ThingTypeUID THING_TYPE_ANALOG = new ThingTypeUID(BINDING_ID, "analog"); - public static final ThingTypeUID THING_TYPE_MEMORY = new ThingTypeUID(BINDING_ID, "memory"); - public static final ThingTypeUID THING_TYPE_DIGITAL = new ThingTypeUID(BINDING_ID, "digital"); - public static final ThingTypeUID THING_TYPE_DATETIME = new ThingTypeUID(BINDING_ID, "datetime"); - public static final ThingTypeUID THING_TYPE_PULSE = new ThingTypeUID(BINDING_ID, "pulse"); - - // Something goes wrong... - public static final String NOT_SUPPORTED = "NOT SUPPORTED"; - - // List of all channels - public static final String STATE_CHANNEL = "state"; - public static final String OBSERVE_CHANNEL = "observed"; - public static final String VALUE_CHANNEL = "value"; - public static final String RTC_CHANNEL = "rtc"; - public static final String DAIGNOSTICS_CHANNEL = "diagnostic"; - public static final String DAY_OF_WEEK_CHANNEL = "weekday"; - - // List of all channel properties - public static final String BLOCK_PROPERTY = "block"; - - // List of all item types - public static final String ANALOG_ITEM = "Number"; - public static final String DATE_TIME_ITEM = "DateTime"; - public static final String DIGITAL_INPUT_ITEM = "Contact"; - public static final String DIGITAL_OUTPUT_ITEM = "Switch"; - public static final String INFORMATION_ITEM = "String"; - - // LOGO! family definitions - public static final String LOGO_0BA7 = "0BA7"; - public static final String LOGO_0BA8 = "0BA8"; - - // LOGO! block definitions - public static final String MEMORY_BYTE = "VB"; // Bit or Byte memory - public static final String MEMORY_WORD = "VW"; // Word memory - public static final String MEMORY_DWORD = "VD"; // DWord memory - public static final String MEMORY_SIZE = "SIZE"; // Size of memory - - public static final String I_DIGITAL = "I"; // Physical digital input - public static final String Q_DIGITAL = "Q"; // Physical digital output - public static final String M_DIGITAL = "M"; // Program digital marker - public static final String NI_DIGITAL = "NI"; // Network digital input - public static final String NQ_DIGITAL = "NQ"; // Network digital output - - public static final String I_ANALOG = "AI"; // Physical analog input - public static final String Q_ANALOG = "AQ"; // Physical analog output - public static final String M_ANALOG = "AM"; // Program analog marker - public static final String NI_ANALOG = "NAI"; // Network analog input - public static final String NQ_ANALOG = "NAQ"; // Network analog output - - private static final Map LOGO_STATES_0BA7; - static { - Map buffer = new HashMap<>(); - // buffer.put(???, "Network access error"); // Netzwerkzugriffsfehler - // buffer.put(???, "Expansion module bus error"); // Erweiterungsmodul-Busfehler - // buffer.put(???, "SD card read/write error"); // Fehler beim Lesen oder Schreiben der SD-Karte - // buffer.put(???, "SD card write protection"); // Schreibschutz der SD-Karte - LOGO_STATES_0BA7 = Collections.unmodifiableMap(buffer); - } - - private static final Map LOGO_STATES_0BA8; - static { - Map buffer = new HashMap<>(); - buffer.put(1, "Ethernet link error"); // Netzwerk Verbindungsfehler - buffer.put(2, "Expansion module changed"); // Ausgetauschtes Erweiterungsmodul - buffer.put(4, "SD card read/write error"); // Fehler beim Lesen oder Schreiben der SD-Karte - buffer.put(8, "SD Card does not exist"); // "SD-Karte nicht vorhanden" - buffer.put(16, "SD Card is full"); // SD-Karte voll - // buffer.put(???, "Network S7 Tcp Error"); // - LOGO_STATES_0BA8 = Collections.unmodifiableMap(buffer); - } - - public static final Map> LOGO_STATES; - static { - Map> buffer = new HashMap<>(); - buffer.put(LOGO_0BA7, LOGO_STATES_0BA7); - buffer.put(LOGO_0BA8, LOGO_STATES_0BA8); - LOGO_STATES = Collections.unmodifiableMap(buffer); - } - - public static final class Layout { - public final int address; - public final int length; - - public Layout(int address, int length) { - this.address = address; - this.length = length; - } - } - - public static final Map LOGO_CHANNELS; - static { - Map buffer = new HashMap<>(); - buffer.put(DAIGNOSTICS_CHANNEL, new Layout(984, 1)); // Diagnostics starts at 984 for 1 byte - buffer.put(RTC_CHANNEL, new Layout(985, 6)); // RTC starts at 985 for 6 bytes: year month day hour minute second - buffer.put(DAY_OF_WEEK_CHANNEL, new Layout(998, 1)); // Diagnostics starts at 998 for 1 byte - LOGO_CHANNELS = Collections.unmodifiableMap(buffer); - } - - public static final Map DAY_OF_WEEK; - static { - Map buffer = new HashMap<>(); - buffer.put(1, "SUNDAY"); - buffer.put(2, "MONDAY"); - buffer.put(3, "TUEsDAY"); - buffer.put(4, "WEDNESDAY"); - buffer.put(5, "THURSDAY"); - buffer.put(6, "FRIDAY"); - buffer.put(7, "SATURDAY"); - DAY_OF_WEEK = Collections.unmodifiableMap(buffer); - } - - private static final Map LOGO_MEMORY_0BA7; - static { - Map buffer = new HashMap<>(); - buffer.put(MEMORY_BYTE, new Layout(0, 850)); - buffer.put(MEMORY_DWORD, new Layout(0, 850)); - buffer.put(MEMORY_WORD, new Layout(0, 850)); - buffer.put(I_DIGITAL, new Layout(923, 3)); // Digital inputs starts at 923 for 3 bytes - buffer.put(Q_DIGITAL, new Layout(942, 2)); // Digital outputs starts at 942 for 2 bytes - buffer.put(M_DIGITAL, new Layout(948, 4)); // Digital markers starts at 948 for 4 bytes - buffer.put(I_ANALOG, new Layout(926, 16)); // Analog inputs starts at 926 for 16 bytes -> 8 words - buffer.put(Q_ANALOG, new Layout(944, 4)); // Analog outputs starts at 944 for 4 bytes -> 2 words - buffer.put(M_ANALOG, new Layout(952, 32)); // Analog markers starts at 952 for 32 bytes -> 16 words - buffer.put(MEMORY_SIZE, new Layout(0, 984)); // Size of memory block for LOGO! 7 - LOGO_MEMORY_0BA7 = Collections.unmodifiableMap(buffer); - } - - private static final Map LOGO_MEMORY_0BA8; - static { - Map buffer = new HashMap<>(); - buffer.put(MEMORY_BYTE, new Layout(0, 850)); - buffer.put(MEMORY_DWORD, new Layout(0, 850)); - buffer.put(MEMORY_WORD, new Layout(0, 850)); - buffer.put(I_DIGITAL, new Layout(1024, 8)); // Digital inputs starts at 1024 for 8 bytes - buffer.put(Q_DIGITAL, new Layout(1064, 8)); // Digital outputs starts at 1064 for 8 bytes - buffer.put(M_DIGITAL, new Layout(1104, 14)); // Digital markers starts at 1104 for 14 bytes - buffer.put(I_ANALOG, new Layout(1032, 32)); // Analog inputs starts at 1032 for 32 bytes -> 16 words - buffer.put(Q_ANALOG, new Layout(1072, 32)); // Analog outputs starts at 1072 for 32 bytes -> 16 words - buffer.put(M_ANALOG, new Layout(1118, 128)); // Analog markers starts at 1118 for 128 bytes -> 64 words - buffer.put(NI_DIGITAL, new Layout(1246, 16)); // Network inputs starts at 1246 for 16 bytes - buffer.put(NI_ANALOG, new Layout(1262, 128)); // Network analog inputs starts at 1262 for 128 bytes -> 64 words - buffer.put(NQ_DIGITAL, new Layout(1390, 16)); // Network outputs starts at 1390 for 16 bytes - buffer.put(NQ_ANALOG, new Layout(1406, 64)); // Network analog inputs starts at 1406 for 64 bytes -> 32 words - buffer.put(MEMORY_SIZE, new Layout(0, 1470)); // Size of memory block for LOGO! 8 - LOGO_MEMORY_0BA8 = Collections.unmodifiableMap(buffer); - } - - public static final Map> LOGO_MEMORY_BLOCK; - static { - Map> buffer = new HashMap<>(); - buffer.put(LOGO_0BA7, LOGO_MEMORY_0BA7); - buffer.put(LOGO_0BA8, LOGO_MEMORY_0BA8); - LOGO_MEMORY_BLOCK = Collections.unmodifiableMap(buffer); - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.plclogo.internal; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * The {@link PLCLogoBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Alexander Falkenstern - Initial contribution + */ +@NonNullByDefault +public class PLCLogoBindingConstants { + + public static final String BINDING_ID = "plclogo"; + + // List of all thing type UIDs + public static final ThingTypeUID THING_TYPE_DEVICE = new ThingTypeUID(BINDING_ID, "device"); + public static final ThingTypeUID THING_TYPE_ANALOG = new ThingTypeUID(BINDING_ID, "analog"); + public static final ThingTypeUID THING_TYPE_MEMORY = new ThingTypeUID(BINDING_ID, "memory"); + public static final ThingTypeUID THING_TYPE_DIGITAL = new ThingTypeUID(BINDING_ID, "digital"); + public static final ThingTypeUID THING_TYPE_DATETIME = new ThingTypeUID(BINDING_ID, "datetime"); + public static final ThingTypeUID THING_TYPE_PULSE = new ThingTypeUID(BINDING_ID, "pulse"); + + // Something goes wrong... + public static final String NOT_SUPPORTED = "NOT SUPPORTED"; + + // List of all channels + public static final String STATE_CHANNEL = "state"; + public static final String OBSERVE_CHANNEL = "observed"; + public static final String VALUE_CHANNEL = "value"; + public static final String RTC_CHANNEL = "rtc"; + public static final String DAIGNOSTICS_CHANNEL = "diagnostic"; + public static final String DAY_OF_WEEK_CHANNEL = "weekday"; + + // List of all channel properties + public static final String BLOCK_PROPERTY = "block"; + + // List of all item types + public static final String ANALOG_ITEM = "Number"; + public static final String DATE_TIME_ITEM = "DateTime"; + public static final String DIGITAL_INPUT_ITEM = "Contact"; + public static final String DIGITAL_OUTPUT_ITEM = "Switch"; + public static final String INFORMATION_ITEM = "String"; + + // LOGO! family definitions + public static final String LOGO_0BA7 = "0BA7"; + public static final String LOGO_0BA8 = "0BA8"; + + // LOGO! block definitions + public static final String MEMORY_BYTE = "VB"; // Bit or Byte memory + public static final String MEMORY_WORD = "VW"; // Word memory + public static final String MEMORY_DWORD = "VD"; // DWord memory + public static final String MEMORY_SIZE = "SIZE"; // Size of memory + + public static final String I_DIGITAL = "I"; // Physical digital input + public static final String Q_DIGITAL = "Q"; // Physical digital output + public static final String M_DIGITAL = "M"; // Program digital marker + public static final String NI_DIGITAL = "NI"; // Network digital input + public static final String NQ_DIGITAL = "NQ"; // Network digital output + + public static final String I_ANALOG = "AI"; // Physical analog input + public static final String Q_ANALOG = "AQ"; // Physical analog output + public static final String M_ANALOG = "AM"; // Program analog marker + public static final String NI_ANALOG = "NAI"; // Network analog input + public static final String NQ_ANALOG = "NAQ"; // Network analog output + + private static final Map LOGO_STATES_0BA7; + static { + Map buffer = new HashMap<>(); + // buffer.put(???, "Network access error"); // Netzwerkzugriffsfehler + // buffer.put(???, "Expansion module bus error"); // Erweiterungsmodul-Busfehler + // buffer.put(???, "SD card read/write error"); // Fehler beim Lesen oder Schreiben der SD-Karte + // buffer.put(???, "SD card write protection"); // Schreibschutz der SD-Karte + LOGO_STATES_0BA7 = Collections.unmodifiableMap(buffer); + } + + private static final Map LOGO_STATES_0BA8; + static { + Map buffer = new HashMap<>(); + buffer.put(1, "Ethernet link error"); // Netzwerk Verbindungsfehler + buffer.put(2, "Expansion module changed"); // Ausgetauschtes Erweiterungsmodul + buffer.put(4, "SD card read/write error"); // Fehler beim Lesen oder Schreiben der SD-Karte + buffer.put(8, "SD Card does not exist"); // "SD-Karte nicht vorhanden" + buffer.put(16, "SD Card is full"); // SD-Karte voll + // buffer.put(???, "Network S7 Tcp Error"); // + LOGO_STATES_0BA8 = Collections.unmodifiableMap(buffer); + } + + public static final Map> LOGO_STATES; + static { + Map> buffer = new HashMap<>(); + buffer.put(LOGO_0BA7, LOGO_STATES_0BA7); + buffer.put(LOGO_0BA8, LOGO_STATES_0BA8); + LOGO_STATES = Collections.unmodifiableMap(buffer); + } + + public static final class Layout { + public final int address; + public final int length; + + public Layout(int address, int length) { + this.address = address; + this.length = length; + } + } + + public static final Map LOGO_CHANNELS; + static { + Map buffer = new HashMap<>(); + buffer.put(DAIGNOSTICS_CHANNEL, new Layout(984, 1)); // Diagnostics starts at 984 for 1 byte + buffer.put(RTC_CHANNEL, new Layout(985, 6)); // RTC starts at 985 for 6 bytes: year month day hour minute second + buffer.put(DAY_OF_WEEK_CHANNEL, new Layout(998, 1)); // Diagnostics starts at 998 for 1 byte + LOGO_CHANNELS = Collections.unmodifiableMap(buffer); + } + + public static final Map DAY_OF_WEEK; + static { + Map buffer = new HashMap<>(); + buffer.put(1, "SUNDAY"); + buffer.put(2, "MONDAY"); + buffer.put(3, "TUEsDAY"); + buffer.put(4, "WEDNESDAY"); + buffer.put(5, "THURSDAY"); + buffer.put(6, "FRIDAY"); + buffer.put(7, "SATURDAY"); + DAY_OF_WEEK = Collections.unmodifiableMap(buffer); + } + + private static final Map LOGO_MEMORY_0BA7; + static { + Map buffer = new HashMap<>(); + buffer.put(MEMORY_BYTE, new Layout(0, 850)); + buffer.put(MEMORY_DWORD, new Layout(0, 850)); + buffer.put(MEMORY_WORD, new Layout(0, 850)); + buffer.put(I_DIGITAL, new Layout(923, 3)); // Digital inputs starts at 923 for 3 bytes + buffer.put(Q_DIGITAL, new Layout(942, 2)); // Digital outputs starts at 942 for 2 bytes + buffer.put(M_DIGITAL, new Layout(948, 4)); // Digital markers starts at 948 for 4 bytes + buffer.put(I_ANALOG, new Layout(926, 16)); // Analog inputs starts at 926 for 16 bytes -> 8 words + buffer.put(Q_ANALOG, new Layout(944, 4)); // Analog outputs starts at 944 for 4 bytes -> 2 words + buffer.put(M_ANALOG, new Layout(952, 32)); // Analog markers starts at 952 for 32 bytes -> 16 words + buffer.put(MEMORY_SIZE, new Layout(0, 984)); // Size of memory block for LOGO! 7 + LOGO_MEMORY_0BA7 = Collections.unmodifiableMap(buffer); + } + + private static final Map LOGO_MEMORY_0BA8; + static { + Map buffer = new HashMap<>(); + buffer.put(MEMORY_BYTE, new Layout(0, 850)); + buffer.put(MEMORY_DWORD, new Layout(0, 850)); + buffer.put(MEMORY_WORD, new Layout(0, 850)); + buffer.put(I_DIGITAL, new Layout(1024, 8)); // Digital inputs starts at 1024 for 8 bytes + buffer.put(Q_DIGITAL, new Layout(1064, 8)); // Digital outputs starts at 1064 for 8 bytes + buffer.put(M_DIGITAL, new Layout(1104, 14)); // Digital markers starts at 1104 for 14 bytes + buffer.put(I_ANALOG, new Layout(1032, 32)); // Analog inputs starts at 1032 for 32 bytes -> 16 words + buffer.put(Q_ANALOG, new Layout(1072, 32)); // Analog outputs starts at 1072 for 32 bytes -> 16 words + buffer.put(M_ANALOG, new Layout(1118, 128)); // Analog markers starts at 1118 for 128 bytes -> 64 words + buffer.put(NI_DIGITAL, new Layout(1246, 16)); // Network inputs starts at 1246 for 16 bytes + buffer.put(NI_ANALOG, new Layout(1262, 128)); // Network analog inputs starts at 1262 for 128 bytes -> 64 words + buffer.put(NQ_DIGITAL, new Layout(1390, 16)); // Network outputs starts at 1390 for 16 bytes + buffer.put(NQ_ANALOG, new Layout(1406, 64)); // Network analog inputs starts at 1406 for 64 bytes -> 32 words + buffer.put(MEMORY_SIZE, new Layout(0, 1470)); // Size of memory block for LOGO! 8 + LOGO_MEMORY_0BA8 = Collections.unmodifiableMap(buffer); + } + + public static final Map> LOGO_MEMORY_BLOCK; + static { + Map> buffer = new HashMap<>(); + buffer.put(LOGO_0BA7, LOGO_MEMORY_0BA7); + buffer.put(LOGO_0BA8, LOGO_MEMORY_0BA8); + LOGO_MEMORY_BLOCK = Collections.unmodifiableMap(buffer); + } +} diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoClient.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoClient.java index 93bcb01b3efa1..e9c66e6190f6e 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoClient.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoClient.java @@ -1,205 +1,205 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.plclogo.internal; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import Moka7.S7; -import Moka7.S7Client; - -/** - * The {@link PLCLogoClient} is thread safe LOGO! client. - * - * @author Alexander Falkenstern - Initial contribution - */ -public class PLCLogoClient extends S7Client { - - private static final int MAX_RETRY_NUMBER = 10; - private final Logger logger = LoggerFactory.getLogger(PLCLogoClient.class); - - private String plcIPAddress = "INVALID_IP"; - - /** - * Connects a client to a PLC - */ - @Override - public synchronized int Connect() { - return super.Connect(); - } - - /** - * Connects a client to a PLC with specified parameters - * - * @param Address IP address of PLC - * @param LocalTSAP Local TSAP for the connection - * @param RemoteTSAP Remote TSAP for the connection - * @return Zero on success, error code otherwise - */ - public synchronized int Connect(String Address, int LocalTSAP, int RemoteTSAP) { - SetConnectionParams(Address, LocalTSAP, RemoteTSAP); - return super.Connect(); - } - - /** - * Set connection parameters - * - * @param Address IP address of PLC - * @param LocalTSAP Local TSAP for the connection - * @param RemoteTSAP Remote TSAP for the connection - */ - @Override - public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP) { - plcIPAddress = Address; // Store ip address for logging - super.SetConnectionParams(Address, LocalTSAP, RemoteTSAP); - } - - /** - * Disconnects a client from a PLC - */ - @Override - public synchronized void Disconnect() { - super.Disconnect(); - } - - /** - * Reads a data area from a PLC - * - * @param Area S7 Area ID. Can be S7AreaPE, S7AreaPA, S7AreaMK, S7AreaDB, S7AreaCT or S7AreaTM - * @param DBNumber S7 data block number - * @param Start First position within data block read from - * @param Amount Number of words to read - * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer - * @param Data Buffer to read into - * @return Zero on success, error code otherwise - */ - @Override - public synchronized int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) { - if (LastError != 0) { - logger.debug("Reconnect during read from {}: {}", plcIPAddress, ErrorText(LastError)); - Disconnect(); - } - if (!Connected) { - Connect(); - } - - final int packet = Math.min(Amount, 1024); - int offset = packet; - - int retry = 0; - int result = -1; - do { - // read first portion directly to data - result = super.ReadArea(Area, DBNumber, Start, packet, WordLength, Data); - while ((result == 0) && (offset < Amount)) { - byte buffer[] = new byte[Math.min(Amount - offset, packet)]; - result = super.ReadArea(Area, DBNumber, offset, buffer.length, WordLength, buffer); - System.arraycopy(buffer, 0, Data, offset, buffer.length); - offset = offset + buffer.length; - } - - if (retry == MAX_RETRY_NUMBER) { - logger.info("Giving up reading from {} after {} retries.", plcIPAddress, MAX_RETRY_NUMBER); - break; - } - - if (result != 0) { - logger.info("Reconnect during read from {}: {}", plcIPAddress, ErrorText(result)); - retry = retry + 1; - Disconnect(); - Connect(); - } - } while (result != 0); - - return result; - } - - /** - * Reads a data block area from a PLC - * - * @param DBNumber S7 data block number - * @param Start First position within data block read from - * @param Amount Number of words to read - * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer - * @param Data Buffer to read into - * @return Zero on success, error code otherwise - */ - public int readDBArea(int DBNumber, int Start, int Amount, int WordLength, byte[] Data) { - return ReadArea(S7.S7AreaDB, DBNumber, Start, Amount, WordLength, Data); - } - - /** - * Writes a data area into a PLC - * - * @param Area S7 Area ID. Can be S7AreaPE, S7AreaPA, S7AreaMK, S7AreaDB, S7AreaCT or S7AreaTM - * @param DBNumber S7 data block number - * @param Start First position within data block write into - * @param Amount Number of words to write - * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer - * @param Data Buffer to write from - * @return Zero on success, error code otherwise - */ - @Override - public synchronized int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) { - if (LastError != 0) { - logger.debug("Reconnect during write to {}: {}", plcIPAddress, ErrorText(LastError)); - Disconnect(); - } - if (!Connected) { - Connect(); - } - - int retry = 0; - int result = -1; - do { - result = super.WriteArea(Area, DBNumber, Start, Amount, WordLength, Data); - - if (retry == MAX_RETRY_NUMBER) { - logger.info("Giving up writing to {} after {} retries.", plcIPAddress, MAX_RETRY_NUMBER); - break; - } - - if (result != 0) { - logger.info("Reconnect during write to {}: {}", plcIPAddress, ErrorText(result)); - retry = retry + 1; - Disconnect(); - Connect(); - } - } while (result != 0); - - return result; - } - - /** - * Writes a data block area into a PLC - * - * @param DBNumber S7 data block number - * @param Start First position within data block write into - * @param Amount Number of words to write - * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer - * @param Data Buffer to write from - * @return Zero on success, error code otherwise - */ - public int writeDBArea(int DBNumber, int Start, int Amount, int WordLength, byte[] Data) { - return WriteArea(S7.S7AreaDB, DBNumber, Start, Amount, WordLength, Data); - } - - /** - * Returns, if client is already connected or not - * - * @return True, if client is connected and false otherwise - */ - public synchronized boolean isConnected() { - return Connected; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.plclogo.internal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import Moka7.S7; +import Moka7.S7Client; + +/** + * The {@link PLCLogoClient} is thread safe LOGO! client. + * + * @author Alexander Falkenstern - Initial contribution + */ +public class PLCLogoClient extends S7Client { + + private static final int MAX_RETRY_NUMBER = 10; + private final Logger logger = LoggerFactory.getLogger(PLCLogoClient.class); + + private String plcIPAddress = "INVALID_IP"; + + /** + * Connects a client to a PLC + */ + @Override + public synchronized int Connect() { + return super.Connect(); + } + + /** + * Connects a client to a PLC with specified parameters + * + * @param Address IP address of PLC + * @param LocalTSAP Local TSAP for the connection + * @param RemoteTSAP Remote TSAP for the connection + * @return Zero on success, error code otherwise + */ + public synchronized int Connect(String Address, int LocalTSAP, int RemoteTSAP) { + SetConnectionParams(Address, LocalTSAP, RemoteTSAP); + return super.Connect(); + } + + /** + * Set connection parameters + * + * @param Address IP address of PLC + * @param LocalTSAP Local TSAP for the connection + * @param RemoteTSAP Remote TSAP for the connection + */ + @Override + public void SetConnectionParams(String Address, int LocalTSAP, int RemoteTSAP) { + plcIPAddress = Address; // Store ip address for logging + super.SetConnectionParams(Address, LocalTSAP, RemoteTSAP); + } + + /** + * Disconnects a client from a PLC + */ + @Override + public synchronized void Disconnect() { + super.Disconnect(); + } + + /** + * Reads a data area from a PLC + * + * @param Area S7 Area ID. Can be S7AreaPE, S7AreaPA, S7AreaMK, S7AreaDB, S7AreaCT or S7AreaTM + * @param DBNumber S7 data block number + * @param Start First position within data block read from + * @param Amount Number of words to read + * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer + * @param Data Buffer to read into + * @return Zero on success, error code otherwise + */ + @Override + public synchronized int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) { + if (LastError != 0) { + logger.debug("Reconnect during read from {}: {}", plcIPAddress, ErrorText(LastError)); + Disconnect(); + } + if (!Connected) { + Connect(); + } + + final int packet = Math.min(Amount, 1024); + int offset = packet; + + int retry = 0; + int result = -1; + do { + // read first portion directly to data + result = super.ReadArea(Area, DBNumber, Start, packet, WordLength, Data); + while ((result == 0) && (offset < Amount)) { + byte buffer[] = new byte[Math.min(Amount - offset, packet)]; + result = super.ReadArea(Area, DBNumber, offset, buffer.length, WordLength, buffer); + System.arraycopy(buffer, 0, Data, offset, buffer.length); + offset = offset + buffer.length; + } + + if (retry == MAX_RETRY_NUMBER) { + logger.info("Giving up reading from {} after {} retries.", plcIPAddress, MAX_RETRY_NUMBER); + break; + } + + if (result != 0) { + logger.info("Reconnect during read from {}: {}", plcIPAddress, ErrorText(result)); + retry = retry + 1; + Disconnect(); + Connect(); + } + } while (result != 0); + + return result; + } + + /** + * Reads a data block area from a PLC + * + * @param DBNumber S7 data block number + * @param Start First position within data block read from + * @param Amount Number of words to read + * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer + * @param Data Buffer to read into + * @return Zero on success, error code otherwise + */ + public int readDBArea(int DBNumber, int Start, int Amount, int WordLength, byte[] Data) { + return ReadArea(S7.S7AreaDB, DBNumber, Start, Amount, WordLength, Data); + } + + /** + * Writes a data area into a PLC + * + * @param Area S7 Area ID. Can be S7AreaPE, S7AreaPA, S7AreaMK, S7AreaDB, S7AreaCT or S7AreaTM + * @param DBNumber S7 data block number + * @param Start First position within data block write into + * @param Amount Number of words to write + * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer + * @param Data Buffer to write from + * @return Zero on success, error code otherwise + */ + @Override + public synchronized int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLength, byte[] Data) { + if (LastError != 0) { + logger.debug("Reconnect during write to {}: {}", plcIPAddress, ErrorText(LastError)); + Disconnect(); + } + if (!Connected) { + Connect(); + } + + int retry = 0; + int result = -1; + do { + result = super.WriteArea(Area, DBNumber, Start, Amount, WordLength, Data); + + if (retry == MAX_RETRY_NUMBER) { + logger.info("Giving up writing to {} after {} retries.", plcIPAddress, MAX_RETRY_NUMBER); + break; + } + + if (result != 0) { + logger.info("Reconnect during write to {}: {}", plcIPAddress, ErrorText(result)); + retry = retry + 1; + Disconnect(); + Connect(); + } + } while (result != 0); + + return result; + } + + /** + * Writes a data block area into a PLC + * + * @param DBNumber S7 data block number + * @param Start First position within data block write into + * @param Amount Number of words to write + * @param WordLength Length of single word. Can be S7WLBit, S7WLByte, S7WLCounter or S7WLTimer + * @param Data Buffer to write from + * @return Zero on success, error code otherwise + */ + public int writeDBArea(int DBNumber, int Start, int Amount, int WordLength, byte[] Data) { + return WriteArea(S7.S7AreaDB, DBNumber, Start, Amount, WordLength, Data); + } + + /** + * Returns, if client is already connected or not + * + * @return True, if client is connected and false otherwise + */ + public synchronized boolean isConnected() { + return Connected; + } +} diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoHandlerFactory.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoHandlerFactory.java index 77a9ec0cb06ee..7464247a92a62 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoHandlerFactory.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/PLCLogoHandlerFactory.java @@ -85,5 +85,4 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return null; } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCAnalogConfiguration.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCAnalogConfiguration.java index 99f92fa612633..3820da56c4584 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCAnalogConfiguration.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCAnalogConfiguration.java @@ -49,5 +49,4 @@ public void setThreshold(final Integer threshold) { public String getChannelType() { return ANALOG_ITEM; } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCCommonConfiguration.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCCommonConfiguration.java index e2c920011a385..28bde7b19795c 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCCommonConfiguration.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCCommonConfiguration.java @@ -59,5 +59,4 @@ public void setForceUpdate(final Boolean force) { * @return Configured Siemens LOGO! blocks kind */ public abstract String getBlockKind(); - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCDateTimeConfiguration.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCDateTimeConfiguration.java index cce4bfd6cb516..3ac3e3862e635 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCDateTimeConfiguration.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCDateTimeConfiguration.java @@ -73,5 +73,4 @@ public String getChannelType() { public String getBlockKind() { return block.substring(0, 2); } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCDigitalConfiguration.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCDigitalConfiguration.java index 6262e1b4db9d3..311d8fe98d8a5 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCDigitalConfiguration.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCDigitalConfiguration.java @@ -48,5 +48,4 @@ public String getChannelType() { boolean isInput = kind.equalsIgnoreCase(I_DIGITAL) || kind.equalsIgnoreCase(NI_DIGITAL); return isInput ? DIGITAL_INPUT_ITEM : DIGITAL_OUTPUT_ITEM; } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCLogoBridgeConfiguration.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCLogoBridgeConfiguration.java index 7a9008f36acfd..4661af42bb520 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCLogoBridgeConfiguration.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCLogoBridgeConfiguration.java @@ -1,137 +1,136 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.plclogo.internal.config; - -import static org.openhab.binding.plclogo.internal.PLCLogoBindingConstants.NOT_SUPPORTED; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.openhab.binding.plclogo.internal.PLCLogoBindingConstants; - -/** - * The {@link PLCLogoBridgeConfiguration} hold configuration of Siemens LOGO! PLCs. - * - * @author Alexander Falkenstern - Initial contribution - */ -@NonNullByDefault -public class PLCLogoBridgeConfiguration { - - private String address = ""; - private String family = NOT_SUPPORTED; - private String localTSAP = "0x3000"; - private String remoteTSAP = "0x2000"; - private Integer refresh = 100; - - /** - * Get configured Siemens LOGO! device IP address. - * - * @return Configured Siemens LOGO! IP address - */ - public String getAddress() { - return address; - } - - /** - * Set IP address for Siemens LOGO! device. - * - * @param address IP address of Siemens LOGO! device - */ - public void setAddress(final String address) { - this.address = address.trim(); - } - - /** - * Get configured Siemens LOGO! device family. - * - * @see PLCLogoBindingConstants#LOGO_0BA7 - * @see PLCLogoBindingConstants#LOGO_0BA8 - * @return Configured Siemens LOGO! device family - */ - public String getFamily() { - return family; - } - - /** - * Set Siemens LOGO! device family. - * - * @param family Family of Siemens LOGO! device - * @see PLCLogoBindingConstants#LOGO_0BA7 - * @see PLCLogoBindingConstants#LOGO_0BA8 - */ - public void setFamily(final String family) { - this.family = family.trim(); - } - - /** - * Get configured local TSAP of Siemens LOGO! device. - * - * @return Configured local TSAP of Siemens LOGO! - */ - public @Nullable Integer getLocalTSAP() { - Integer result = null; - if (localTSAP.startsWith("0x")) { - result = Integer.decode(localTSAP); - } - return result; - } - - /** - * Set local TSAP of Siemens LOGO! device. - * - * @param tsap Local TSAP of Siemens LOGO! device - */ - public void setLocalTSAP(final String tsap) { - this.localTSAP = tsap.trim(); - } - - /** - * Get configured remote TSAP of Siemens LOGO! device. - * - * @return Configured local TSAP of Siemens LOGO! - */ - public @Nullable Integer getRemoteTSAP() { - Integer result = null; - if (remoteTSAP.startsWith("0x")) { - result = Integer.decode(remoteTSAP); - } - return result; - } - - /** - * Set remote TSAP of Siemens LOGO! device. - * - * @param tsap Remote TSAP of Siemens LOGO! device - */ - public void setRemoteTSAP(final String tsap) { - this.remoteTSAP = tsap.trim(); - } - - /** - * Get configured refresh rate of Siemens LOGO! device blocks in milliseconds. - * - * @return Configured refresh rate of Siemens LOGO! device blocks - */ - public Integer getRefreshRate() { - return refresh; - } - - /** - * Set refresh rate of Siemens LOGO! device blocks in milliseconds. - * - * @param rate Refresh rate of Siemens LOGO! device blocks - */ - public void setRefreshRate(final Integer rate) { - this.refresh = rate; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.plclogo.internal.config; + +import static org.openhab.binding.plclogo.internal.PLCLogoBindingConstants.NOT_SUPPORTED; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.plclogo.internal.PLCLogoBindingConstants; + +/** + * The {@link PLCLogoBridgeConfiguration} hold configuration of Siemens LOGO! PLCs. + * + * @author Alexander Falkenstern - Initial contribution + */ +@NonNullByDefault +public class PLCLogoBridgeConfiguration { + + private String address = ""; + private String family = NOT_SUPPORTED; + private String localTSAP = "0x3000"; + private String remoteTSAP = "0x2000"; + private Integer refresh = 100; + + /** + * Get configured Siemens LOGO! device IP address. + * + * @return Configured Siemens LOGO! IP address + */ + public String getAddress() { + return address; + } + + /** + * Set IP address for Siemens LOGO! device. + * + * @param address IP address of Siemens LOGO! device + */ + public void setAddress(final String address) { + this.address = address.trim(); + } + + /** + * Get configured Siemens LOGO! device family. + * + * @see PLCLogoBindingConstants#LOGO_0BA7 + * @see PLCLogoBindingConstants#LOGO_0BA8 + * @return Configured Siemens LOGO! device family + */ + public String getFamily() { + return family; + } + + /** + * Set Siemens LOGO! device family. + * + * @param family Family of Siemens LOGO! device + * @see PLCLogoBindingConstants#LOGO_0BA7 + * @see PLCLogoBindingConstants#LOGO_0BA8 + */ + public void setFamily(final String family) { + this.family = family.trim(); + } + + /** + * Get configured local TSAP of Siemens LOGO! device. + * + * @return Configured local TSAP of Siemens LOGO! + */ + public @Nullable Integer getLocalTSAP() { + Integer result = null; + if (localTSAP.startsWith("0x")) { + result = Integer.decode(localTSAP); + } + return result; + } + + /** + * Set local TSAP of Siemens LOGO! device. + * + * @param tsap Local TSAP of Siemens LOGO! device + */ + public void setLocalTSAP(final String tsap) { + this.localTSAP = tsap.trim(); + } + + /** + * Get configured remote TSAP of Siemens LOGO! device. + * + * @return Configured local TSAP of Siemens LOGO! + */ + public @Nullable Integer getRemoteTSAP() { + Integer result = null; + if (remoteTSAP.startsWith("0x")) { + result = Integer.decode(remoteTSAP); + } + return result; + } + + /** + * Set remote TSAP of Siemens LOGO! device. + * + * @param tsap Remote TSAP of Siemens LOGO! device + */ + public void setRemoteTSAP(final String tsap) { + this.remoteTSAP = tsap.trim(); + } + + /** + * Get configured refresh rate of Siemens LOGO! device blocks in milliseconds. + * + * @return Configured refresh rate of Siemens LOGO! device blocks + */ + public Integer getRefreshRate() { + return refresh; + } + + /** + * Set refresh rate of Siemens LOGO! device blocks in milliseconds. + * + * @param rate Refresh rate of Siemens LOGO! device blocks + */ + public void setRefreshRate(final Integer rate) { + this.refresh = rate; + } +} diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCPulseConfiguration.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCPulseConfiguration.java index f291ea68a7278..479578c94ce81 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCPulseConfiguration.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/config/PLCPulseConfiguration.java @@ -74,5 +74,4 @@ public Integer getPulseLength() { public void setPulseLength(Integer pulse) { this.pulse = pulse; } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/discovery/PLCDiscoveryService.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/discovery/PLCDiscoveryService.java index 3d90bbe588bcd..756c14a20b063 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/discovery/PLCDiscoveryService.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/discovery/PLCDiscoveryService.java @@ -159,5 +159,4 @@ protected synchronized void stopScan() { logger.debug("Stop scan for LOGO! bridge"); super.stopScan(); } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCAnalogHandler.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCAnalogHandler.java index 9480cbea377de..90fe029d615b0 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCAnalogHandler.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCAnalogHandler.java @@ -283,5 +283,4 @@ private void updateChannel(final Channel channel, int value) { logger.debug("Channel {} will not accept {} items.", channelUID, type); } } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCBridgeHandler.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCBridgeHandler.java index 1506f199d6a41..0ef4f2468a11d 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCBridgeHandler.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCBridgeHandler.java @@ -1,378 +1,377 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.plclogo.internal.handler; - -import static org.openhab.binding.plclogo.internal.PLCLogoBindingConstants.*; - -import java.time.DateTimeException; -import java.time.ZonedDateTime; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.config.core.Configuration; -import org.eclipse.smarthome.core.library.types.DateTimeType; -import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Channel; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; -import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.openhab.binding.plclogo.internal.PLCLogoClient; -import org.openhab.binding.plclogo.internal.PLCLogoBindingConstants.Layout; -import org.openhab.binding.plclogo.internal.config.PLCLogoBridgeConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import Moka7.S7Client; - -/** - * The {@link PLCBridgeHandler} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Alexander Falkenstern - Initial contribution - */ -@NonNullByDefault -public class PLCBridgeHandler extends BaseBridgeHandler { - - public static final Set SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_DEVICE); - - private final Logger logger = LoggerFactory.getLogger(PLCBridgeHandler.class); - - private Map oldValues = new HashMap<>(); - - @Nullable - private volatile PLCLogoClient client; // S7 client used for communication with Logo! - private final Set handlers = new HashSet<>(); - private AtomicReference config = new AtomicReference<>(); - - @Nullable - private ScheduledFuture rtcJob; - private AtomicReference rtc = new AtomicReference<>(ZonedDateTime.now()); - private final Runnable rtcReader = new Runnable() { - private final List channels = getThing().getChannels(); - - @Override - public void run() { - for (Channel channel : channels) { - handleCommand(channel.getUID(), RefreshType.REFRESH); - } - } - }; - - @Nullable - private ScheduledFuture readerJob; - private final Runnable dataReader = new Runnable() { - // Buffer for block data read operation - private final byte[] buffer = new byte[2048]; - - @Override - public void run() { - PLCLogoClient localClient = client; - Map memory = LOGO_MEMORY_BLOCK.get(getLogoFamily()); - Layout layout = (memory != null) ? memory.get(MEMORY_SIZE) : null; - if ((layout != null) && (localClient != null)) { - try { - int result = localClient.readDBArea(1, 0, layout.length, S7Client.S7WLByte, buffer); - if (result == 0) { - synchronized (handlers) { - for (PLCCommonHandler handler : handlers) { - int length = handler.getBufferLength(); - int address = handler.getStartAddress(); - if ((length > 0) && (address != PLCCommonHandler.INVALID)) { - handler.setData(Arrays.copyOfRange(buffer, address, address + length)); - } else { - logger.debug("Invalid handler {} found.", handler.getClass().getSimpleName()); - } - } - } - } else { - logger.debug("Can not read data from LOGO!: {}.", S7Client.ErrorText(result)); - } - } catch (Exception exception) { - logger.error("Reader thread got exception: {}.", exception.getMessage()); - } - } else { - logger.debug("Either memory block {} or LOGO! client {} is invalid.", memory, localClient); - } - } - }; - - /** - * Constructor. - */ - public PLCBridgeHandler(Bridge bridge) { - super(bridge); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - logger.debug("Handle command {} on channel {}", command, channelUID); - - Thing thing = getThing(); - if (ThingStatus.ONLINE != thing.getStatus()) { - return; - } - - if (!(command instanceof RefreshType)) { - logger.debug("Not supported command {} received.", command); - return; - } - - PLCLogoClient localClient = client; - String channelId = channelUID.getId(); - Channel channel = thing.getChannel(channelId); - Layout layout = LOGO_CHANNELS.get(channelId); - if ((localClient != null) && (channel != null) && (layout != null)) { - byte[] buffer = new byte[layout.length]; - Arrays.fill(buffer, (byte) 0); - int result = localClient.readDBArea(1, layout.address, buffer.length, S7Client.S7WLByte, buffer); - if (result == 0) { - if (RTC_CHANNEL.equals(channelId)) { - ZonedDateTime clock = ZonedDateTime.now(); - if (!LOGO_0BA7.equalsIgnoreCase(getLogoFamily())) { - try { - int year = clock.getYear() / 100; - clock = clock.withYear(100 * year + buffer[0]); - clock = clock.withMonth(buffer[1]); - clock = clock.withDayOfMonth(buffer[2]); - clock = clock.withHour(buffer[3]); - clock = clock.withMinute(buffer[4]); - clock = clock.withSecond(buffer[5]); - } catch (DateTimeException exception) { - clock = ZonedDateTime.now(); - logger.info("Return local server time: {}.", exception.getMessage()); - } - } - rtc.set(clock); - updateState(channelUID, new DateTimeType(clock)); - } else if (DAIGNOSTICS_CHANNEL.equals(channelId)) { - Map states = LOGO_STATES.get(getLogoFamily()); - if (states != null) { - for (Integer key : states.keySet()) { - String message = states.get(buffer[0] & key.intValue()); - synchronized (oldValues) { - if ((message != null) && (oldValues.get(channelUID) != message)) { - updateState(channelUID, new StringType(message)); - oldValues.put(channelUID, message); - } - } - } - } - } else if (DAY_OF_WEEK_CHANNEL.equals(channelId)) { - String value = DAY_OF_WEEK.get(Integer.valueOf(buffer[0])); - synchronized (oldValues) { - if ((value != null) && (oldValues.get(channelUID) != value)) { - updateState(channelUID, new StringType(value)); - oldValues.put(channelUID, value); - } - } - } else { - logger.info("Invalid channel {} or client {} found.", channelUID, client); - } - - if (logger.isTraceEnabled()) { - String raw = Arrays.toString(buffer); - String type = channel.getAcceptedItemType(); - logger.trace("Channel {} accepting {} received {}.", channelUID, type, raw); - } - } else { - logger.debug("Can not read data from LOGO!: {}.", S7Client.ErrorText(result)); - } - } else { - logger.info("Invalid channel {} or client {} found.", channelUID, client); - } - } - - @Override - public void initialize() { - logger.debug("Initialize LOGO! bridge handler."); - - synchronized (oldValues) { - oldValues.clear(); - } - config.set(getConfigAs(PLCLogoBridgeConfiguration.class)); - - boolean configured = (config.get().getLocalTSAP() != null); - configured = configured && (config.get().getRemoteTSAP() != null); - - if (configured) { - if (client == null) { - client = new PLCLogoClient(); - } - configured = connect(); - } else { - String message = "Can not initialize LOGO!. Please, check ip address / TSAP settings."; - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message); - } - - if (configured) { - String host = config.get().getAddress(); - if (readerJob == null) { - Integer interval = config.get().getRefreshRate(); - logger.info("Creating new reader job for {} with interval {} ms.", host, interval); - readerJob = scheduler.scheduleWithFixedDelay(dataReader, 100, interval, TimeUnit.MILLISECONDS); - } - if (rtcJob == null) { - logger.info("Creating new RTC job for {} with interval 1 s.", host); - rtcJob = scheduler.scheduleAtFixedRate(rtcReader, 100, 1000, TimeUnit.MILLISECONDS); - } - - updateStatus(ThingStatus.ONLINE); - } else { - String message = "Can not initialize LOGO!. Please, check network connection."; - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message); - client = null; - } - } - - @Override - public void dispose() { - logger.debug("Dispose LOGO! bridge handler."); - super.dispose(); - - if (rtcJob != null) { - rtcJob.cancel(false); - rtcJob = null; - logger.info("Destroy RTC job for {}.", config.get().getAddress()); - } - - if (readerJob != null) { - readerJob.cancel(false); - readerJob = null; - logger.info("Destroy reader job for {}.", config.get().getAddress()); - } - - if (disconnect()) { - client = null; - } - - synchronized (oldValues) { - oldValues.clear(); - } - } - - @Override - public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { - super.childHandlerInitialized(childHandler, childThing); - if (childHandler instanceof PLCCommonHandler) { - PLCCommonHandler handler = (PLCCommonHandler) childHandler; - synchronized (handlers) { - if (!handlers.contains(handler)) { - handlers.add(handler); - } - } - } - } - - @Override - public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { - if (childHandler instanceof PLCCommonHandler) { - PLCCommonHandler handler = (PLCCommonHandler) childHandler; - synchronized (handlers) { - if (handlers.contains(handler)) { - handlers.remove(handler); - } - } - } - super.childHandlerDisposed(childHandler, childThing); - } - - /** - * Returns Siemens LOGO! communication client - * - * @return Configured Siemens LOGO! client - */ - public @Nullable PLCLogoClient getLogoClient() { - return client; - } - - /** - * Returns configured Siemens LOGO! family: 0BA7 or 0BA8 - * - * @return Configured Siemens LOGO! family - */ - public String getLogoFamily() { - return config.get().getFamily(); - } - - /** - * Returns RTC was fetched last from Siemens LOGO! - * - * @return Siemens LOGO! RTC - */ - public ZonedDateTime getLogoRTC() { - return rtc.get(); - } - - @Override - protected void updateConfiguration(Configuration configuration) { - super.updateConfiguration(configuration); - config.set(getConfigAs(PLCLogoBridgeConfiguration.class)); - } - - /** - * Read connection parameter and connect to Siemens LOGO! - * - * @return True, if connected and false otherwise - */ - private boolean connect() { - boolean result = false; - - PLCLogoClient localClient = client; - if (localClient != null) { - Integer local = config.get().getLocalTSAP(); - Integer remote = config.get().getRemoteTSAP(); - if (!localClient.isConnected() && (local != null) && (remote != null)) { - localClient.Connect(config.get().getAddress(), local.intValue(), remote.intValue()); - } - result = localClient.isConnected(); - } - return result; - } - - /** - * Disconnect from Siemens LOGO! - * - * @return True, if disconnected and false otherwise - */ - private boolean disconnect() { - boolean result = false; - - PLCLogoClient localClient = client; - if (localClient != null) { - if (localClient.isConnected()) { - localClient.Disconnect(); - } - result = !localClient.isConnected(); - } - - return result; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.plclogo.internal.handler; + +import static org.openhab.binding.plclogo.internal.PLCLogoBindingConstants.*; + +import java.time.DateTimeException; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.library.types.DateTimeType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.plclogo.internal.PLCLogoBindingConstants.Layout; +import org.openhab.binding.plclogo.internal.PLCLogoClient; +import org.openhab.binding.plclogo.internal.config.PLCLogoBridgeConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import Moka7.S7Client; + +/** + * The {@link PLCBridgeHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Alexander Falkenstern - Initial contribution + */ +@NonNullByDefault +public class PLCBridgeHandler extends BaseBridgeHandler { + + public static final Set SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_DEVICE); + + private final Logger logger = LoggerFactory.getLogger(PLCBridgeHandler.class); + + private Map oldValues = new HashMap<>(); + + @Nullable + private volatile PLCLogoClient client; // S7 client used for communication with Logo! + private final Set handlers = new HashSet<>(); + private AtomicReference config = new AtomicReference<>(); + + @Nullable + private ScheduledFuture rtcJob; + private AtomicReference rtc = new AtomicReference<>(ZonedDateTime.now()); + private final Runnable rtcReader = new Runnable() { + private final List channels = getThing().getChannels(); + + @Override + public void run() { + for (Channel channel : channels) { + handleCommand(channel.getUID(), RefreshType.REFRESH); + } + } + }; + + @Nullable + private ScheduledFuture readerJob; + private final Runnable dataReader = new Runnable() { + // Buffer for block data read operation + private final byte[] buffer = new byte[2048]; + + @Override + public void run() { + PLCLogoClient localClient = client; + Map memory = LOGO_MEMORY_BLOCK.get(getLogoFamily()); + Layout layout = (memory != null) ? memory.get(MEMORY_SIZE) : null; + if ((layout != null) && (localClient != null)) { + try { + int result = localClient.readDBArea(1, 0, layout.length, S7Client.S7WLByte, buffer); + if (result == 0) { + synchronized (handlers) { + for (PLCCommonHandler handler : handlers) { + int length = handler.getBufferLength(); + int address = handler.getStartAddress(); + if ((length > 0) && (address != PLCCommonHandler.INVALID)) { + handler.setData(Arrays.copyOfRange(buffer, address, address + length)); + } else { + logger.debug("Invalid handler {} found.", handler.getClass().getSimpleName()); + } + } + } + } else { + logger.debug("Can not read data from LOGO!: {}.", S7Client.ErrorText(result)); + } + } catch (Exception exception) { + logger.error("Reader thread got exception: {}.", exception.getMessage()); + } + } else { + logger.debug("Either memory block {} or LOGO! client {} is invalid.", memory, localClient); + } + } + }; + + /** + * Constructor. + */ + public PLCBridgeHandler(Bridge bridge) { + super(bridge); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + logger.debug("Handle command {} on channel {}", command, channelUID); + + Thing thing = getThing(); + if (ThingStatus.ONLINE != thing.getStatus()) { + return; + } + + if (!(command instanceof RefreshType)) { + logger.debug("Not supported command {} received.", command); + return; + } + + PLCLogoClient localClient = client; + String channelId = channelUID.getId(); + Channel channel = thing.getChannel(channelId); + Layout layout = LOGO_CHANNELS.get(channelId); + if ((localClient != null) && (channel != null) && (layout != null)) { + byte[] buffer = new byte[layout.length]; + Arrays.fill(buffer, (byte) 0); + int result = localClient.readDBArea(1, layout.address, buffer.length, S7Client.S7WLByte, buffer); + if (result == 0) { + if (RTC_CHANNEL.equals(channelId)) { + ZonedDateTime clock = ZonedDateTime.now(); + if (!LOGO_0BA7.equalsIgnoreCase(getLogoFamily())) { + try { + int year = clock.getYear() / 100; + clock = clock.withYear(100 * year + buffer[0]); + clock = clock.withMonth(buffer[1]); + clock = clock.withDayOfMonth(buffer[2]); + clock = clock.withHour(buffer[3]); + clock = clock.withMinute(buffer[4]); + clock = clock.withSecond(buffer[5]); + } catch (DateTimeException exception) { + clock = ZonedDateTime.now(); + logger.info("Return local server time: {}.", exception.getMessage()); + } + } + rtc.set(clock); + updateState(channelUID, new DateTimeType(clock)); + } else if (DAIGNOSTICS_CHANNEL.equals(channelId)) { + Map states = LOGO_STATES.get(getLogoFamily()); + if (states != null) { + for (Integer key : states.keySet()) { + String message = states.get(buffer[0] & key.intValue()); + synchronized (oldValues) { + if ((message != null) && (oldValues.get(channelUID) != message)) { + updateState(channelUID, new StringType(message)); + oldValues.put(channelUID, message); + } + } + } + } + } else if (DAY_OF_WEEK_CHANNEL.equals(channelId)) { + String value = DAY_OF_WEEK.get(Integer.valueOf(buffer[0])); + synchronized (oldValues) { + if ((value != null) && (oldValues.get(channelUID) != value)) { + updateState(channelUID, new StringType(value)); + oldValues.put(channelUID, value); + } + } + } else { + logger.info("Invalid channel {} or client {} found.", channelUID, client); + } + + if (logger.isTraceEnabled()) { + String raw = Arrays.toString(buffer); + String type = channel.getAcceptedItemType(); + logger.trace("Channel {} accepting {} received {}.", channelUID, type, raw); + } + } else { + logger.debug("Can not read data from LOGO!: {}.", S7Client.ErrorText(result)); + } + } else { + logger.info("Invalid channel {} or client {} found.", channelUID, client); + } + } + + @Override + public void initialize() { + logger.debug("Initialize LOGO! bridge handler."); + + synchronized (oldValues) { + oldValues.clear(); + } + config.set(getConfigAs(PLCLogoBridgeConfiguration.class)); + + boolean configured = (config.get().getLocalTSAP() != null); + configured = configured && (config.get().getRemoteTSAP() != null); + + if (configured) { + if (client == null) { + client = new PLCLogoClient(); + } + configured = connect(); + } else { + String message = "Can not initialize LOGO!. Please, check ip address / TSAP settings."; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, message); + } + + if (configured) { + String host = config.get().getAddress(); + if (readerJob == null) { + Integer interval = config.get().getRefreshRate(); + logger.info("Creating new reader job for {} with interval {} ms.", host, interval); + readerJob = scheduler.scheduleWithFixedDelay(dataReader, 100, interval, TimeUnit.MILLISECONDS); + } + if (rtcJob == null) { + logger.info("Creating new RTC job for {} with interval 1 s.", host); + rtcJob = scheduler.scheduleAtFixedRate(rtcReader, 100, 1000, TimeUnit.MILLISECONDS); + } + + updateStatus(ThingStatus.ONLINE); + } else { + String message = "Can not initialize LOGO!. Please, check network connection."; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, message); + client = null; + } + } + + @Override + public void dispose() { + logger.debug("Dispose LOGO! bridge handler."); + super.dispose(); + + if (rtcJob != null) { + rtcJob.cancel(false); + rtcJob = null; + logger.info("Destroy RTC job for {}.", config.get().getAddress()); + } + + if (readerJob != null) { + readerJob.cancel(false); + readerJob = null; + logger.info("Destroy reader job for {}.", config.get().getAddress()); + } + + if (disconnect()) { + client = null; + } + + synchronized (oldValues) { + oldValues.clear(); + } + } + + @Override + public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { + super.childHandlerInitialized(childHandler, childThing); + if (childHandler instanceof PLCCommonHandler) { + PLCCommonHandler handler = (PLCCommonHandler) childHandler; + synchronized (handlers) { + if (!handlers.contains(handler)) { + handlers.add(handler); + } + } + } + } + + @Override + public void childHandlerDisposed(ThingHandler childHandler, Thing childThing) { + if (childHandler instanceof PLCCommonHandler) { + PLCCommonHandler handler = (PLCCommonHandler) childHandler; + synchronized (handlers) { + if (handlers.contains(handler)) { + handlers.remove(handler); + } + } + } + super.childHandlerDisposed(childHandler, childThing); + } + + /** + * Returns Siemens LOGO! communication client + * + * @return Configured Siemens LOGO! client + */ + public @Nullable PLCLogoClient getLogoClient() { + return client; + } + + /** + * Returns configured Siemens LOGO! family: 0BA7 or 0BA8 + * + * @return Configured Siemens LOGO! family + */ + public String getLogoFamily() { + return config.get().getFamily(); + } + + /** + * Returns RTC was fetched last from Siemens LOGO! + * + * @return Siemens LOGO! RTC + */ + public ZonedDateTime getLogoRTC() { + return rtc.get(); + } + + @Override + protected void updateConfiguration(Configuration configuration) { + super.updateConfiguration(configuration); + config.set(getConfigAs(PLCLogoBridgeConfiguration.class)); + } + + /** + * Read connection parameter and connect to Siemens LOGO! + * + * @return True, if connected and false otherwise + */ + private boolean connect() { + boolean result = false; + + PLCLogoClient localClient = client; + if (localClient != null) { + Integer local = config.get().getLocalTSAP(); + Integer remote = config.get().getRemoteTSAP(); + if (!localClient.isConnected() && (local != null) && (remote != null)) { + localClient.Connect(config.get().getAddress(), local.intValue(), remote.intValue()); + } + result = localClient.isConnected(); + } + return result; + } + + /** + * Disconnect from Siemens LOGO! + * + * @return True, if disconnected and false otherwise + */ + private boolean disconnect() { + boolean result = false; + + PLCLogoClient localClient = client; + if (localClient != null) { + if (localClient.isConnected()) { + localClient.Disconnect(); + } + result = !localClient.isConnected(); + } + + return result; + } +} diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCCommonHandler.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCCommonHandler.java index 532f7ffeca82d..203340d04530c 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCCommonHandler.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCCommonHandler.java @@ -282,5 +282,4 @@ protected void doInitialization() { protected static String getBlockFromChannel(final @Nullable Channel channel) { return channel == null ? NOT_SUPPORTED : channel.getProperties().get(BLOCK_PROPERTY); } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCDateTimeHandler.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCDateTimeHandler.java index 9bafaa28fd46d..bd9b39f2e06b0 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCDateTimeHandler.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCDateTimeHandler.java @@ -272,5 +272,4 @@ private void updateChannel(final Channel channel, int value) { logger.debug("Channel {} will not accept {} items.", channelUID, type); } } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCDigitalHandler.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCDigitalHandler.java index 055b604565b3c..f6c5d1d280595 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCDigitalHandler.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCDigitalHandler.java @@ -321,5 +321,4 @@ private void updateChannel(final Channel channel, boolean value) { logger.debug("Channel {} will not accept {} items.", channelUID, type); } } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCMemoryHandler.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCMemoryHandler.java index 6856d54cae05e..6da212b3c8032 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCMemoryHandler.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCMemoryHandler.java @@ -1,326 +1,325 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.plclogo.internal.handler; - -import static org.openhab.binding.plclogo.internal.PLCLogoBindingConstants.*; - -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.config.core.Configuration; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.eclipse.smarthome.core.thing.Bridge; -import org.eclipse.smarthome.core.thing.Channel; -import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Thing; -import org.eclipse.smarthome.core.thing.ThingStatus; -import org.eclipse.smarthome.core.thing.ThingTypeUID; -import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; -import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; -import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; -import org.eclipse.smarthome.core.types.Command; -import org.eclipse.smarthome.core.types.RefreshType; -import org.eclipse.smarthome.core.types.State; -import org.openhab.binding.plclogo.internal.PLCLogoClient; -import org.openhab.binding.plclogo.internal.config.PLCMemoryConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import Moka7.S7; -import Moka7.S7Client; - -/** - * The {@link PLCMemoryHandler} is responsible for handling commands, which are - * sent to one of the channels. - * - * @author Alexander Falkenstern - Initial contribution - */ -@NonNullByDefault -public class PLCMemoryHandler extends PLCCommonHandler { - - public static final Set SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_MEMORY); - - private final Logger logger = LoggerFactory.getLogger(PLCMemoryHandler.class); - private AtomicReference config = new AtomicReference<>(); - - /** - * Constructor. - */ - public PLCMemoryHandler(Thing thing) { - super(thing); - } - - @Override - public void handleCommand(ChannelUID channelUID, Command command) { - if (!isThingOnline()) { - return; - } - - Channel channel = getThing().getChannel(channelUID.getId()); - String name = getBlockFromChannel(channel); - if (!isValid(name) || (channel == null)) { - logger.debug("Can not update channel {}, block {}.", channelUID, name); - return; - } - - int address = getAddress(name); - PLCLogoClient client = getLogoClient(); - if ((address != INVALID) && (client != null)) { - String kind = getBlockKind(); - String type = channel.getAcceptedItemType(); - if (command instanceof RefreshType) { - byte[] buffer = new byte[getBufferLength()]; - int result = client.readDBArea(1, 0, buffer.length, S7Client.S7WLByte, buffer); - if (result == 0) { - if (DIGITAL_OUTPUT_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { - boolean value = S7.GetBitAt(buffer, address, getBit(name)); - updateState(channelUID, value ? OnOffType.ON : OnOffType.OFF); - logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); - } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { - int value = buffer[address]; - updateState(channelUID, new DecimalType(value)); - logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); - } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_WORD.equalsIgnoreCase(kind)) { - int value = S7.GetShortAt(buffer, address); - updateState(channelUID, new DecimalType(value)); - logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); - } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_DWORD.equalsIgnoreCase(kind)) { - int value = S7.GetDIntAt(buffer, address); - updateState(channelUID, new DecimalType(value)); - logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); - } else { - logger.debug("Channel {} will not accept {} items.", channelUID, type); - } - } else { - logger.debug("Can not read data from LOGO!: {}.", S7Client.ErrorText(result)); - } - } else if (command instanceof DecimalType) { - int length = MEMORY_BYTE.equalsIgnoreCase(kind) ? 1 : 2; - byte[] buffer = new byte[MEMORY_DWORD.equalsIgnoreCase(kind) ? 4 : length]; - if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { - buffer[0] = ((DecimalType) command).byteValue(); - } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_WORD.equalsIgnoreCase(kind)) { - S7.SetShortAt(buffer, 0, ((DecimalType) command).intValue()); - } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_DWORD.equalsIgnoreCase(kind)) { - S7.SetDIntAt(buffer, 0, ((DecimalType) command).intValue()); - } else { - logger.debug("Channel {} will not accept {} items.", channelUID, type); - } - int result = client.writeDBArea(1, address, buffer.length, S7Client.S7WLByte, buffer); - if (result != 0) { - logger.debug("Can not write data to LOGO!: {}.", S7Client.ErrorText(result)); - } - } else if (command instanceof OnOffType) { - byte[] buffer = new byte[1]; - if (DIGITAL_OUTPUT_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { - S7.SetBitAt(buffer, 0, 0, ((OnOffType) command) == OnOffType.ON); - } else { - logger.debug("Channel {} will not accept {} items.", channelUID, type); - } - int result = client.writeDBArea(1, 8 * address + getBit(name), buffer.length, S7Client.S7WLBit, buffer); - if (result != 0) { - logger.debug("Can not write data to LOGO!: {}.", S7Client.ErrorText(result)); - } - } else { - logger.debug("Channel {} received not supported command {}.", channelUID, command); - } - } else { - logger.info("Invalid channel {} or client {} found.", channelUID, client); - } - } - - @Override - public void setData(final byte[] data) { - if (!isThingOnline()) { - return; - } - - if (data.length != getBufferLength()) { - logger.info("Received and configured data sizes does not match."); - return; - } - - List channels = thing.getChannels(); - if (channels.size() != getNumberOfChannels()) { - logger.info("Received and configured channel sizes does not match."); - return; - } - - for (Channel channel : channels) { - ChannelUID channelUID = channel.getUID(); - String name = getBlockFromChannel(channel); - - int address = getAddress(name); - if (address != INVALID) { - String kind = getBlockKind(); - String type = channel.getAcceptedItemType(); - Boolean force = config.get().isUpdateForced(); - - if (DIGITAL_OUTPUT_ITEM.equalsIgnoreCase(type) && kind.equalsIgnoreCase(MEMORY_BYTE)) { - OnOffType state = (OnOffType) getOldValue(name); - OnOffType value = S7.GetBitAt(data, address, getBit(name)) ? OnOffType.ON : OnOffType.OFF; - if ((state == null) || (value != state) || force) { - updateState(channelUID, value); - logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); - } - if (logger.isTraceEnabled()) { - int buffer = (data[address] & 0xFF) + 0x100; - logger.trace("Channel {} received [{}].", channelUID, - Integer.toBinaryString(buffer).substring(1)); - } - } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { - Integer threshold = config.get().getThreshold(); - DecimalType state = (DecimalType) getOldValue(name); - int value = data[address]; - if ((state == null) || (Math.abs(value - state.intValue()) > threshold) || force) { - updateState(channelUID, new DecimalType(value)); - logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); - } - if (logger.isTraceEnabled()) { - logger.trace("Channel {} received [{}].", channelUID, data[address]); - } - } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_WORD.equalsIgnoreCase(kind)) { - Integer threshold = config.get().getThreshold(); - DecimalType state = (DecimalType) getOldValue(name); - int value = S7.GetShortAt(data, address); - if ((state == null) || (Math.abs(value - state.intValue()) > threshold) || force) { - updateState(channelUID, new DecimalType(value)); - logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); - } - if (logger.isTraceEnabled()) { - logger.trace("Channel {} received [{}, {}].", channelUID, data[address], data[address + 1]); - } - } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_DWORD.equalsIgnoreCase(kind)) { - Integer threshold = config.get().getThreshold(); - DecimalType state = (DecimalType) getOldValue(name); - int value = S7.GetDIntAt(data, address); - if ((state == null) || (Math.abs(value - state.intValue()) > threshold) || force) { - updateState(channelUID, new DecimalType(value)); - logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); - } - if (logger.isTraceEnabled()) { - logger.trace("Channel {} received [{}, {}, {}, {}].", channelUID, data[address], - data[address + 1], data[address + 2], data[address + 3]); - } - } else { - logger.debug("Channel {} will not accept {} items.", channelUID, type); - } - } else { - logger.info("Invalid channel {} found.", channelUID); - } - } - } - - @Override - protected void updateState(ChannelUID channelUID, State state) { - super.updateState(channelUID, state); - - Channel channel = thing.getChannel(channelUID.getId()); - setOldValue(getBlockFromChannel(channel), state); - } - - @Override - protected void updateConfiguration(Configuration configuration) { - super.updateConfiguration(configuration); - config.set(getConfigAs(PLCMemoryConfiguration.class)); - } - - @Override - protected boolean isValid(final String name) { - if (3 <= name.length() && (name.length() <= 7)) { - String kind = getBlockKind(); - if (Character.isDigit(name.charAt(2))) { - boolean valid = MEMORY_BYTE.equalsIgnoreCase(kind) || MEMORY_WORD.equalsIgnoreCase(kind); - return name.startsWith(kind) && (valid || MEMORY_DWORD.equalsIgnoreCase(kind)); - } - } - return false; - } - - @Override - protected String getBlockKind() { - return config.get().getBlockKind(); - } - - @Override - protected int getNumberOfChannels() { - return 1; - } - - @Override - protected void doInitialization() { - Thing thing = getThing(); - logger.debug("Initialize LOGO! memory handler."); - - config.set(getConfigAs(PLCMemoryConfiguration.class)); - - super.doInitialization(); - if (ThingStatus.OFFLINE != thing.getStatus()) { - String kind = getBlockKind(); - String name = config.get().getBlockName(); - boolean isDigital = MEMORY_BYTE.equalsIgnoreCase(kind) && (getBit(name) != INVALID); - String text = isDigital ? "Digital" : "Analog"; - - ThingBuilder tBuilder = editThing(); - - String label = thing.getLabel(); - if (label == null) { - Bridge bridge = getBridge(); - label = (bridge == null) || (bridge.getLabel() == null) ? "Siemens Logo!" : bridge.getLabel(); - label += (": " + text.toLowerCase() + " in/output"); - } - tBuilder.withLabel(label); - - String type = config.get().getChannelType(); - ChannelUID uid = new ChannelUID(thing.getUID(), isDigital ? STATE_CHANNEL : VALUE_CHANNEL); - ChannelBuilder cBuilder = ChannelBuilder.create(uid, type); - cBuilder.withType(new ChannelTypeUID(BINDING_ID, type.toLowerCase())); - cBuilder.withLabel(name); - cBuilder.withDescription(text + " in/output block " + name); - cBuilder.withProperties(Collections.singletonMap(BLOCK_PROPERTY, name)); - tBuilder.withChannel(cBuilder.build()); - setOldValue(name, null); - - updateThing(tBuilder.build()); - updateStatus(ThingStatus.ONLINE); - } - } - - /** - * Calculate bit within address for block with given name. - * - * @param name Name of the LOGO! block - * @return Calculated bit - */ - private int getBit(final String name) { - int bit = INVALID; - - logger.debug("Get bit of {} LOGO! for block {} .", getLogoFamily(), name); - - if (isValid(name) && (getAddress(name) != INVALID)) { - String[] parts = name.trim().split("\\."); - if (parts.length > 1) { - bit = Integer.parseInt(parts[1]); - } - } else { - logger.info("Wrong configurated LOGO! block {} found.", name); - } - - return bit; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.plclogo.internal.handler; + +import static org.openhab.binding.plclogo.internal.PLCLogoBindingConstants.*; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Channel; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.builder.ChannelBuilder; +import org.eclipse.smarthome.core.thing.binding.builder.ThingBuilder; +import org.eclipse.smarthome.core.thing.type.ChannelTypeUID; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.State; +import org.openhab.binding.plclogo.internal.PLCLogoClient; +import org.openhab.binding.plclogo.internal.config.PLCMemoryConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import Moka7.S7; +import Moka7.S7Client; + +/** + * The {@link PLCMemoryHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Alexander Falkenstern - Initial contribution + */ +@NonNullByDefault +public class PLCMemoryHandler extends PLCCommonHandler { + + public static final Set SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_MEMORY); + + private final Logger logger = LoggerFactory.getLogger(PLCMemoryHandler.class); + private AtomicReference config = new AtomicReference<>(); + + /** + * Constructor. + */ + public PLCMemoryHandler(Thing thing) { + super(thing); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + if (!isThingOnline()) { + return; + } + + Channel channel = getThing().getChannel(channelUID.getId()); + String name = getBlockFromChannel(channel); + if (!isValid(name) || (channel == null)) { + logger.debug("Can not update channel {}, block {}.", channelUID, name); + return; + } + + int address = getAddress(name); + PLCLogoClient client = getLogoClient(); + if ((address != INVALID) && (client != null)) { + String kind = getBlockKind(); + String type = channel.getAcceptedItemType(); + if (command instanceof RefreshType) { + byte[] buffer = new byte[getBufferLength()]; + int result = client.readDBArea(1, 0, buffer.length, S7Client.S7WLByte, buffer); + if (result == 0) { + if (DIGITAL_OUTPUT_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { + boolean value = S7.GetBitAt(buffer, address, getBit(name)); + updateState(channelUID, value ? OnOffType.ON : OnOffType.OFF); + logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); + } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { + int value = buffer[address]; + updateState(channelUID, new DecimalType(value)); + logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); + } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_WORD.equalsIgnoreCase(kind)) { + int value = S7.GetShortAt(buffer, address); + updateState(channelUID, new DecimalType(value)); + logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); + } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_DWORD.equalsIgnoreCase(kind)) { + int value = S7.GetDIntAt(buffer, address); + updateState(channelUID, new DecimalType(value)); + logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); + } else { + logger.debug("Channel {} will not accept {} items.", channelUID, type); + } + } else { + logger.debug("Can not read data from LOGO!: {}.", S7Client.ErrorText(result)); + } + } else if (command instanceof DecimalType) { + int length = MEMORY_BYTE.equalsIgnoreCase(kind) ? 1 : 2; + byte[] buffer = new byte[MEMORY_DWORD.equalsIgnoreCase(kind) ? 4 : length]; + if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { + buffer[0] = ((DecimalType) command).byteValue(); + } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_WORD.equalsIgnoreCase(kind)) { + S7.SetShortAt(buffer, 0, ((DecimalType) command).intValue()); + } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_DWORD.equalsIgnoreCase(kind)) { + S7.SetDIntAt(buffer, 0, ((DecimalType) command).intValue()); + } else { + logger.debug("Channel {} will not accept {} items.", channelUID, type); + } + int result = client.writeDBArea(1, address, buffer.length, S7Client.S7WLByte, buffer); + if (result != 0) { + logger.debug("Can not write data to LOGO!: {}.", S7Client.ErrorText(result)); + } + } else if (command instanceof OnOffType) { + byte[] buffer = new byte[1]; + if (DIGITAL_OUTPUT_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { + S7.SetBitAt(buffer, 0, 0, ((OnOffType) command) == OnOffType.ON); + } else { + logger.debug("Channel {} will not accept {} items.", channelUID, type); + } + int result = client.writeDBArea(1, 8 * address + getBit(name), buffer.length, S7Client.S7WLBit, buffer); + if (result != 0) { + logger.debug("Can not write data to LOGO!: {}.", S7Client.ErrorText(result)); + } + } else { + logger.debug("Channel {} received not supported command {}.", channelUID, command); + } + } else { + logger.info("Invalid channel {} or client {} found.", channelUID, client); + } + } + + @Override + public void setData(final byte[] data) { + if (!isThingOnline()) { + return; + } + + if (data.length != getBufferLength()) { + logger.info("Received and configured data sizes does not match."); + return; + } + + List channels = thing.getChannels(); + if (channels.size() != getNumberOfChannels()) { + logger.info("Received and configured channel sizes does not match."); + return; + } + + for (Channel channel : channels) { + ChannelUID channelUID = channel.getUID(); + String name = getBlockFromChannel(channel); + + int address = getAddress(name); + if (address != INVALID) { + String kind = getBlockKind(); + String type = channel.getAcceptedItemType(); + Boolean force = config.get().isUpdateForced(); + + if (DIGITAL_OUTPUT_ITEM.equalsIgnoreCase(type) && kind.equalsIgnoreCase(MEMORY_BYTE)) { + OnOffType state = (OnOffType) getOldValue(name); + OnOffType value = S7.GetBitAt(data, address, getBit(name)) ? OnOffType.ON : OnOffType.OFF; + if ((state == null) || (value != state) || force) { + updateState(channelUID, value); + logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); + } + if (logger.isTraceEnabled()) { + int buffer = (data[address] & 0xFF) + 0x100; + logger.trace("Channel {} received [{}].", channelUID, + Integer.toBinaryString(buffer).substring(1)); + } + } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_BYTE.equalsIgnoreCase(kind)) { + Integer threshold = config.get().getThreshold(); + DecimalType state = (DecimalType) getOldValue(name); + int value = data[address]; + if ((state == null) || (Math.abs(value - state.intValue()) > threshold) || force) { + updateState(channelUID, new DecimalType(value)); + logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); + } + if (logger.isTraceEnabled()) { + logger.trace("Channel {} received [{}].", channelUID, data[address]); + } + } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_WORD.equalsIgnoreCase(kind)) { + Integer threshold = config.get().getThreshold(); + DecimalType state = (DecimalType) getOldValue(name); + int value = S7.GetShortAt(data, address); + if ((state == null) || (Math.abs(value - state.intValue()) > threshold) || force) { + updateState(channelUID, new DecimalType(value)); + logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); + } + if (logger.isTraceEnabled()) { + logger.trace("Channel {} received [{}, {}].", channelUID, data[address], data[address + 1]); + } + } else if (ANALOG_ITEM.equalsIgnoreCase(type) && MEMORY_DWORD.equalsIgnoreCase(kind)) { + Integer threshold = config.get().getThreshold(); + DecimalType state = (DecimalType) getOldValue(name); + int value = S7.GetDIntAt(data, address); + if ((state == null) || (Math.abs(value - state.intValue()) > threshold) || force) { + updateState(channelUID, new DecimalType(value)); + logger.debug("Channel {} accepting {} was set to {}.", channelUID, type, value); + } + if (logger.isTraceEnabled()) { + logger.trace("Channel {} received [{}, {}, {}, {}].", channelUID, data[address], + data[address + 1], data[address + 2], data[address + 3]); + } + } else { + logger.debug("Channel {} will not accept {} items.", channelUID, type); + } + } else { + logger.info("Invalid channel {} found.", channelUID); + } + } + } + + @Override + protected void updateState(ChannelUID channelUID, State state) { + super.updateState(channelUID, state); + + Channel channel = thing.getChannel(channelUID.getId()); + setOldValue(getBlockFromChannel(channel), state); + } + + @Override + protected void updateConfiguration(Configuration configuration) { + super.updateConfiguration(configuration); + config.set(getConfigAs(PLCMemoryConfiguration.class)); + } + + @Override + protected boolean isValid(final String name) { + if (3 <= name.length() && (name.length() <= 7)) { + String kind = getBlockKind(); + if (Character.isDigit(name.charAt(2))) { + boolean valid = MEMORY_BYTE.equalsIgnoreCase(kind) || MEMORY_WORD.equalsIgnoreCase(kind); + return name.startsWith(kind) && (valid || MEMORY_DWORD.equalsIgnoreCase(kind)); + } + } + return false; + } + + @Override + protected String getBlockKind() { + return config.get().getBlockKind(); + } + + @Override + protected int getNumberOfChannels() { + return 1; + } + + @Override + protected void doInitialization() { + Thing thing = getThing(); + logger.debug("Initialize LOGO! memory handler."); + + config.set(getConfigAs(PLCMemoryConfiguration.class)); + + super.doInitialization(); + if (ThingStatus.OFFLINE != thing.getStatus()) { + String kind = getBlockKind(); + String name = config.get().getBlockName(); + boolean isDigital = MEMORY_BYTE.equalsIgnoreCase(kind) && (getBit(name) != INVALID); + String text = isDigital ? "Digital" : "Analog"; + + ThingBuilder tBuilder = editThing(); + + String label = thing.getLabel(); + if (label == null) { + Bridge bridge = getBridge(); + label = (bridge == null) || (bridge.getLabel() == null) ? "Siemens Logo!" : bridge.getLabel(); + label += (": " + text.toLowerCase() + " in/output"); + } + tBuilder.withLabel(label); + + String type = config.get().getChannelType(); + ChannelUID uid = new ChannelUID(thing.getUID(), isDigital ? STATE_CHANNEL : VALUE_CHANNEL); + ChannelBuilder cBuilder = ChannelBuilder.create(uid, type); + cBuilder.withType(new ChannelTypeUID(BINDING_ID, type.toLowerCase())); + cBuilder.withLabel(name); + cBuilder.withDescription(text + " in/output block " + name); + cBuilder.withProperties(Collections.singletonMap(BLOCK_PROPERTY, name)); + tBuilder.withChannel(cBuilder.build()); + setOldValue(name, null); + + updateThing(tBuilder.build()); + updateStatus(ThingStatus.ONLINE); + } + } + + /** + * Calculate bit within address for block with given name. + * + * @param name Name of the LOGO! block + * @return Calculated bit + */ + private int getBit(final String name) { + int bit = INVALID; + + logger.debug("Get bit of {} LOGO! for block {} .", getLogoFamily(), name); + + if (isValid(name) && (getAddress(name) != INVALID)) { + String[] parts = name.trim().split("\\."); + if (parts.length > 1) { + bit = Integer.parseInt(parts[1]); + } + } else { + logger.info("Wrong configurated LOGO! block {} found.", name); + } + + return bit; + } +} diff --git a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCPulseHandler.java b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCPulseHandler.java index eb85d0477f0b3..66fcd74ee3752 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCPulseHandler.java +++ b/bundles/org.openhab.binding.plclogo/src/main/java/org/openhab/binding/plclogo/internal/handler/PLCPulseHandler.java @@ -336,5 +336,4 @@ private void updateChannel(final Channel channel, boolean value) { logger.debug("Channel {} will not accept {} items.", channelUID, type); } } - } diff --git a/bundles/org.openhab.binding.plclogo/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.plclogo/src/main/resources/ESH-INF/binding/binding.xml index 5416bd87367d8..05ec335d36cbe 100644 --- a/bundles/org.openhab.binding.plclogo/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.plclogo/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - - - + + Chill temperature in degree Celsius - - - + + + diff --git a/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComCamera1MessageTest.java b/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComCamera1MessageTest.java index b0f2364790c84..ae521a5c01b1d 100644 --- a/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComCamera1MessageTest.java +++ b/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComCamera1MessageTest.java @@ -29,5 +29,4 @@ public class RFXComCamera1MessageTest { public void checkNotImplemented() throws Exception { RFXComMessageFactory.createMessage(PacketType.CAMERA1); } - } diff --git a/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComLighting1MessageTest.java b/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComLighting1MessageTest.java index 7e6e24f4b0fd6..1cb37e9b984df 100644 --- a/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComLighting1MessageTest.java +++ b/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComLighting1MessageTest.java @@ -109,5 +109,4 @@ public void testCommandStringDim() throws RFXComUnsupportedChannelException { assertEquals(OpenClosedType.CLOSED, msg.convertToState(CHANNEL_CONTACT, deviceState)); assertEquals(StringType.valueOf("DIM"), msg.convertToState(CHANNEL_COMMAND_STRING, deviceState)); } - } diff --git a/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComTemperatureHumidityMessageTest.java b/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComTemperatureHumidityMessageTest.java index c86ff87201bfe..0bba145bea620 100644 --- a/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComTemperatureHumidityMessageTest.java +++ b/bundles/org.openhab.binding.rfxcom/src/test/java/org/openhab/binding/rfxcom/internal/messages/RFXComTemperatureHumidityMessageTest.java @@ -57,5 +57,4 @@ public void testSomeMessages() throws RFXComException { testMessage("0A520211700200A72D0089", TH2, 17, 28674, 16.7, 45, NORMAL, 8, 9); testMessage("0A5205D42F000082590379", TH5, 212, 12032, 13, 89, WET, 7, 9); } - } diff --git a/bundles/org.openhab.binding.rme/pom.xml b/bundles/org.openhab.binding.rme/pom.xml index 1e725fc58d6f7..c62db87d48f95 100644 --- a/bundles/org.openhab.binding.rme/pom.xml +++ b/bundles/org.openhab.binding.rme/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.rme diff --git a/bundles/org.openhab.binding.rme/src/main/feature/feature.xml b/bundles/org.openhab.binding.rme/src/main/feature/feature.xml index c63a7ae985243..89deb767af363 100644 --- a/bundles/org.openhab.binding.rme/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.rme/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.rme/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.rme/${project.version} + diff --git a/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/RMEBindingConstants.java b/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/RMEBindingConstants.java index c2b23b72cf428..12dceb420a51b 100644 --- a/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/RMEBindingConstants.java +++ b/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/RMEBindingConstants.java @@ -83,7 +83,5 @@ public static DataField get(String valueSelectorText) throws IllegalArgumentExce public String channelID() { return this.id; } - } - } diff --git a/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/RMEHandlerFactory.java b/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/RMEHandlerFactory.java index f2d020d50423f..d58ba1ab27257 100644 --- a/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/RMEHandlerFactory.java +++ b/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/RMEHandlerFactory.java @@ -17,13 +17,18 @@ import java.util.Collections; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.rme.internal.handler.RMEThingHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link RMEHandlerFactory} is responsible for creating things and thing @@ -31,22 +36,30 @@ * * @author Karel Goderis - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.rme") public class RMEHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_MANAGER); + private final SerialPortManager serialPortManager; + + @Activate + public RMEHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(THING_TYPE_MANAGER)) { - return new RMEThingHandler(thing); + return new RMEThingHandler(thing, serialPortManager); } return null; diff --git a/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/handler/RMEThingHandler.java b/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/handler/RMEThingHandler.java index 49b28e76dfbaa..6e77fab7ec9c3 100644 --- a/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/handler/RMEThingHandler.java +++ b/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/handler/RMEThingHandler.java @@ -22,6 +22,7 @@ import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.rme.internal.RMEBindingConstants.DataField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,8 +42,8 @@ public class RMEThingHandler extends SerialThingHandler { private static final StringType MANUAL = new StringType("Manual"); private static final StringType RAIN = new StringType("Rain"); - public RMEThingHandler(Thing thing) { - super(thing); + public RMEThingHandler(Thing thing, SerialPortManager serialPortManager) { + super(thing, serialPortManager); } @Override @@ -76,8 +77,8 @@ public void handleCommand(ChannelUID channelUID, Command command) { } @Override - public void onDataReceived(String line) { - line = StringUtils.chomp(line); + public void onDataReceived(String receivedLine) { + String line = StringUtils.chomp(receivedLine); // little hack to overcome Locale limits of the RME Rain Manager // note to the attentive reader : should we add support for system diff --git a/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/handler/SerialThingHandler.java b/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/handler/SerialThingHandler.java index d2a79f192ae53..9b8b89233b692 100644 --- a/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/handler/SerialThingHandler.java +++ b/bundles/org.openhab.binding.rme/src/main/java/org/openhab/binding/rme/internal/handler/SerialThingHandler.java @@ -18,26 +18,25 @@ import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Enumeration; import java.util.TooManyListenersException; +import java.util.stream.Collectors; -import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - /** * The {@link SerialThingHandler} is responsible for handling commands, which * are sent to one of the channels. Thing Handler classes that use serial @@ -58,7 +57,8 @@ public abstract class SerialThingHandler extends BaseThingHandler implements Ser private final Logger logger = LoggerFactory.getLogger(SerialThingHandler.class); private SerialPort serialPort; - private CommPortIdentifier portId; + private SerialPortIdentifier portId; + private final SerialPortManager serialPortManager; private InputStream inputStream; private OutputStream outputStream; protected int baud; @@ -66,17 +66,17 @@ public abstract class SerialThingHandler extends BaseThingHandler implements Ser protected int bufferSize; protected long sleep = 100; protected long interval = 0; - Thread readerThread = null; + private Thread readerThread = null; - public SerialThingHandler(Thing thing) { + public SerialThingHandler(Thing thing, SerialPortManager serialPortManager) { super(thing); + this.serialPortManager = serialPortManager; } /** * Called when data is received on the serial port * - * @param line - * - the received data as a String + * @param line the received data as a String * **/ public abstract void onDataReceived(String line); @@ -84,8 +84,7 @@ public SerialThingHandler(Thing thing) { /** * Write data to the serial port * - * @param msg - * - the received data as a String + * @param msg the received data as a String * **/ public void writeString(String msg) { @@ -123,12 +122,6 @@ public void dispose() { if (serialPort != null) { serialPort.removeEventListener(); } - IOUtils.closeQuietly(inputStream); - IOUtils.closeQuietly(outputStream); - if (serialPort != null) { - serialPort.close(); - } - if (readerThread != null) { try { readerThread.interrupt(); @@ -136,98 +129,107 @@ public void dispose() { } catch (InterruptedException e) { } } + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + logger.debug("Error while closing the input stream: {}", e.getMessage()); + } + } + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + logger.debug("Error while closing the output stream: {}", e.getMessage()); + } + } + if (serialPort != null) { + serialPort.close(); + } + readerThread = null; + inputStream = null; + outputStream = null; + serialPort = null; } @Override public void initialize() { logger.debug("Initializing serial thing handler."); - if (serialPort == null && port != null && baud != 0) { - // parse ports and if the default port is found, initialized the - // reader - @SuppressWarnings("rawtypes") - Enumeration portList = CommPortIdentifier.getPortIdentifiers(); - while (portList.hasMoreElements()) { - CommPortIdentifier id = (CommPortIdentifier) portList.nextElement(); - if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) { - if (id.getName().equals(port)) { - logger.debug("Serial port '{}' has been found.", port); - portId = id; - } - } - } + if (baud == 0) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Baud rate is not configured"); + return; + } else if (port == null || port.isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Serial port is not configured"); + return; + } - if (portId != null) { - // initialize serial port - try { - serialPort = portId.open("openHAB", 2000); - } catch (PortInUseException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not open serial port " + serialPort + ": " + e.getMessage()); - return; - } + portId = serialPortManager.getIdentifier(port); - try { - inputStream = serialPort.getInputStream(); - } catch (IOException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not open serial port " + serialPort + ": " + e.getMessage()); - return; - } + if (portId == null) { + String availablePorts = serialPortManager.getIdentifiers().map(id -> id.getName()) + .collect(Collectors.joining(System.lineSeparator())); + String description = String.format("Serial port '%s' could not be found. Available ports are:%n%s", port, + availablePorts); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, description); + return; - try { - serialPort.addEventListener(this); - } catch (TooManyListenersException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not open serial port " + serialPort + ": " + e.getMessage()); - return; - } + } - // activate the DATA_AVAILABLE notifier - serialPort.notifyOnDataAvailable(true); - - try { - // set port parameters - serialPort.setSerialPortParams(baud, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, - SerialPort.PARITY_NONE); - } catch (UnsupportedCommOperationException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not configure serial port " + serialPort + ": " + e.getMessage()); - return; - } + // initialize serial port + try { + serialPort = portId.open("openHAB", 2000); + } catch (PortInUseException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Could not open serial port " + port + ": " + e.getMessage()); + return; + } - try { - // get the output stream - outputStream = serialPort.getOutputStream(); - updateStatus(ThingStatus.ONLINE); - } catch (IOException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "Could not communicate with the serial port " + serialPort + ": " + e.getMessage()); - return; - } + try { + inputStream = serialPort.getInputStream(); + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Could not open serial port " + port + ": " + e.getMessage()); + return; + } - readerThread = new SerialPortReader(inputStream); - readerThread.start(); + try { + serialPort.addEventListener(this); + } catch (TooManyListenersException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Could not open serial port " + port + ": " + e.getMessage()); + return; + } - } else { - StringBuilder sb = new StringBuilder(); - portList = CommPortIdentifier.getPortIdentifiers(); - while (portList.hasMoreElements()) { - CommPortIdentifier id = (CommPortIdentifier) portList.nextElement(); - if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) { - sb.append(id.getName() + "\n"); - } - } - logger.error("Serial port '{}' could not be found. Available ports are:\n {}", port, sb); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR); - } + // activate the DATA_AVAILABLE notifier + serialPort.notifyOnDataAvailable(true); + + try { + // set port parameters + serialPort.setSerialPortParams(baud, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); + } catch (UnsupportedCommOperationException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Could not configure serial port " + port + ": " + e.getMessage()); + return; } + + try { + // get the output stream + outputStream = serialPort.getOutputStream(); + updateStatus(ThingStatus.ONLINE); + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Could not communicate with the serial port " + port + ": " + e.getMessage()); + return; + } + + readerThread = new SerialPortReader(inputStream); + readerThread.start(); } @Override public void handleCommand(ChannelUID channelUID, Command command) { - // by default, we write anything we received as a string to the serial - // port + // by default, we write anything we received as a string to the serial port writeString(command.toString()); } @@ -251,10 +253,6 @@ public SerialPortReader(InputStream in) { public void interrupt() { interrupted = true; super.interrupt(); - try { - inputStream.close(); - } catch (IOException e) { - } // quietly close } @Override diff --git a/bundles/org.openhab.binding.rme/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.rme/src/main/resources/ESH-INF/binding/binding.xml index 161e6d0eb753e..64b6332e3c657 100644 --- a/bundles/org.openhab.binding.rme/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.rme/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - openHAB RME Binding diff --git a/bundles/org.openhab.binding.rme/src/main/resources/ESH-INF/thing/rme.xml b/bundles/org.openhab.binding.rme/src/main/resources/ESH-INF/thing/rme.xml index c673f50ca04a1..b11b176b1d5d0 100644 --- a/bundles/org.openhab.binding.rme/src/main/resources/ESH-INF/thing/rme.xml +++ b/bundles/org.openhab.binding.rme/src/main/resources/ESH-INF/thing/rme.xml @@ -5,12 +5,13 @@ - The RME Rain Manager is a controllable water supply unit that can monitor a gauge in a cistern, and switch between rain water and city provided water + The RME Rain Manager is a controllable water supply unit that can monitor a gauge in a cistern, and + switch between rain water and city provided water - - - + + + @@ -38,6 +39,7 @@ serial-port + false Serial Port the RME Rain Manager is connected to true @@ -49,7 +51,7 @@ Number Indicates the % the cistern is filled with water - + diff --git a/bundles/org.openhab.binding.robonect/pom.xml b/bundles/org.openhab.binding.robonect/pom.xml index fa738593db47d..45d38ea44389c 100644 --- a/bundles/org.openhab.binding.robonect/pom.xml +++ b/bundles/org.openhab.binding.robonect/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.robonect diff --git a/bundles/org.openhab.binding.robonect/src/main/feature/feature.xml b/bundles/org.openhab.binding.robonect/src/main/feature/feature.xml index ccc77ebac3e70..a7409bc1202eb 100644 --- a/bundles/org.openhab.binding.robonect/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.robonect/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.robonect/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.robonect/${project.version} + diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectBindingConstants.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectBindingConstants.java index 61b68ff47fadc..2fb93218649aa 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectBindingConstants.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectBindingConstants.java @@ -39,22 +39,20 @@ public class RobonectBindingConstants { public static final String CHANNEL_TIMER_STATUS = "timer-status"; public static final String CHANNEL_TIMER_NEXT_TIMER = "timer-next"; public static final String CHANNEL_WLAN_SIGNAL = "wlan-signal"; - + public static final String CHANNEL_JOB = "job"; - + public static final String CHANNEL_ERROR_CODE = "error-code"; public static final String CHANNEL_ERROR_MESSAGE = "error-message"; public static final String CHANNEL_ERROR_DATE = "error-date"; - + public static final String CHANNEL_LAST_ERROR_CODE = "last-error-code"; public static final String CHANNEL_LAST_ERROR_MESSAGE = "last-error-message"; public static final String CHANNEL_LAST_ERROR_DATE = "last-error-date"; - + public static final String CHANNEL_HEALTH_TEMP = "health-temperature"; public static final String CHANNEL_HEALTH_HUM = "health-humidity"; - + public static final String PROPERTY_COMPILED = "compiled"; public static final String PROPERTY_COMMENT = "comment"; - - } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectClient.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectClient.java index 1bef800975c74..df04beb1c20f6 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectClient.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectClient.java @@ -68,7 +68,7 @@ public class RobonectClient { * The {@link JobSettings} class holds the values required for starting a job. */ public static class JobSettings { - + private static final String TIME_REGEX = "^[012]\\d:\\d\\d$"; private final Logger logger = LoggerFactory.getLogger(RobonectClient.class); @@ -128,7 +128,6 @@ public JobSettings withDuration(int duration) { this.duration = duration; return this; } - } private static class BasicResult implements Authentication.Result { @@ -137,7 +136,6 @@ private static class BasicResult implements Authentication.Result { private final URI uri; private final String value; - public BasicResult(HttpHeader header, URI uri, String value) { this.header = header; this.uri = uri; @@ -155,16 +153,14 @@ public void apply(Request request) { public String toString() { return String.format("Basic authentication result for %s", this.uri); } - } - /** * Creates an instance of RobonectClient which allows to communicate with the specified endpoint via the passed * httpClient instance. * * @param httpClient - The HttpClient to use for the communication. - * @param endpoint - The endpoint information for connecting and issuing commands. + * @param endpoint - The endpoint information for connecting and issuing commands. */ public RobonectClient(HttpClient httpClient, RobonectEndpoint endpoint) { this.httpClient = httpClient; @@ -179,10 +175,8 @@ public RobonectClient(HttpClient httpClient, RobonectEndpoint endpoint) { private void addPreemptiveAuthentication(HttpClient httpClient, RobonectEndpoint endpoint) { AuthenticationStore auth = httpClient.getAuthenticationStore(); URI uri = URI.create(baseUrl); - auth.addAuthenticationResult(new BasicResult(HttpHeader.AUTHORIZATION, uri, - "Basic " - + B64Code.encode(endpoint.getUser() + ":" + endpoint.getPassword(), - StandardCharsets.ISO_8859_1))); + auth.addAuthenticationResult(new BasicResult(HttpHeader.AUTHORIZATION, uri, "Basic " + + B64Code.encode(endpoint.getUser() + ":" + endpoint.getPassword(), StandardCharsets.ISO_8859_1))); } /** @@ -194,9 +188,10 @@ public MowerInfo getMowerInfo() { String responseString = sendCommand(new StatusCommand()); MowerInfo mowerInfo = parser.parse(responseString, MowerInfo.class); if (jobRunning) { - // mode might have been changed on the mower. Also Mode JOB does not really exist on the mower, thus cannot be checked here + // mode might have been changed on the mower. Also Mode JOB does not really exist on the mower, thus cannot + // be checked here if (mowerInfo.getStatus().getMode() == MowerMode.AUTO - || mowerInfo.getStatus().getMode() == MowerMode.HOME) { + || mowerInfo.getStatus().getMode() == MowerMode.HOME) { jobRunning = false; } else if (mowerInfo.getError() != null) { jobRunning = false; @@ -246,7 +241,8 @@ public ErrorList errorList() { } /** - * Sets the mode of the mower. See {@link ModeCommand.Mode} for details about the available modes. Not allowed is mode + * Sets the mode of the mower. See {@link ModeCommand.Mode} for details about the available modes. Not allowed is + * mode * {@link ModeCommand.Mode#JOB}. * * @param mode - the desired mower mode. @@ -291,7 +287,7 @@ private String sendCommand(Command command) { logger.debug("send HTTP GET to: {} ", command.toCommandURL(baseUrl)); } ContentResponse response = httpClient.newRequest(command.toCommandURL(baseUrl)).method(HttpMethod.GET) - .timeout(30000, TimeUnit.MILLISECONDS).send(); + .timeout(30000, TimeUnit.MILLISECONDS).send(); String responseString = null; // jetty uses UTF-8 as default encoding. However, HTTP 1.1 specifies ISO_8859_1 @@ -322,14 +318,13 @@ public VersionInfo getVersionInfo() { return parser.parse(versionResponse, VersionInfo.class); } - public boolean isJobRunning() { return jobRunning; } public RobonectAnswer startJob(JobSettings settings) { - Command jobCommand = new ModeCommand(ModeCommand.Mode.JOB).withRemoteStart(settings.remoteStart).withAfter( - settings.after).withDuration(settings.duration); + Command jobCommand = new ModeCommand(ModeCommand.Mode.JOB).withRemoteStart(settings.remoteStart) + .withAfter(settings.after).withDuration(settings.duration); String responseString = sendCommand(jobCommand); RobonectAnswer answer = parser.parse(responseString, RobonectAnswer.class); if (answer.isSuccessful()) { diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectEndpoint.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectEndpoint.java index cdbef928859d6..c2fe001256261 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectEndpoint.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectEndpoint.java @@ -20,13 +20,13 @@ * @author Marco Meyer - Initial contribution */ public class RobonectEndpoint { - + private final String ipAddress; - + private final String user; - + private final String password; - + private boolean useAuthentication = false; public RobonectEndpoint(String ipAddress, String user, String password) { diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectHandlerFactory.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectHandlerFactory.java index a7826b46ef912..09d7939f21de2 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectHandlerFactory.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/RobonectHandlerFactory.java @@ -65,5 +65,4 @@ protected void setHttpClientFactory(HttpClientFactory httpClientFactory) { protected void unsetHttpClientFactory(HttpClientFactory httpClientFactory) { this.httpClient = null; } - } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/config/JobChannelConfig.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/config/JobChannelConfig.java index 75543dd60212a..fd47bab8f9d7d 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/config/JobChannelConfig.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/config/JobChannelConfig.java @@ -18,11 +18,11 @@ * @author Marco Meyer - Initial contribution */ public class JobChannelConfig { - + private String remoteStart; - + private String afterMode; - + private int duration; public String getRemoteStart() { diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/config/RobonectConfig.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/config/RobonectConfig.java index 53b3cec6a2372..db5b246b5e567 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/config/RobonectConfig.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/config/RobonectConfig.java @@ -19,15 +19,15 @@ * @author Marco Meyer - Initial contribution */ public class RobonectConfig { - + private String host; - + private String user; - + private String password; - + private int pollInterval; - + private int offlineTimeout; public String getHost() { diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/handler/RobonectHandler.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/handler/RobonectHandler.java index d8651b231941b..583eaf317c654 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/handler/RobonectHandler.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/handler/RobonectHandler.java @@ -250,7 +250,6 @@ private void refreshMowerInfo() { } else { logger.error("Could not retrieve mower info. Robonect error response message: {}", info.getErrorMessage()); } - } private void clearErrorInfo() { @@ -340,7 +339,6 @@ public void initialize() { Runnable runnable = new MowerChannelPoller(TimeUnit.SECONDS.toMillis(robonectConfig.getOfflineTimeout())); int pollInterval = robonectConfig.getPollInterval(); pollingJob = scheduler.scheduleWithFixedDelay(runnable, 0, pollInterval, TimeUnit.SECONDS); - } @Override diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ErrorEntry.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ErrorEntry.java index ec9a4da22b57a..74cbf6d63608e 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ErrorEntry.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ErrorEntry.java @@ -19,18 +19,18 @@ * * @author Marco Meyer - Initial contribution */ -public class ErrorEntry { - - private String date; - +public class ErrorEntry { + + private String date; + @SerializedName("error_code") private Integer errorCode; - + @SerializedName("error_message") private String errorMessage; private String time; - + private String unix; /** @@ -48,7 +48,7 @@ public Integer getErrorCode() { } /** - * @return - The localized error message from the mower. + * @return - The localized error message from the mower. */ public String getErrorMessage() { return errorMessage; diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ErrorList.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ErrorList.java index 2cbd2d2b170f4..32de9ea43120b 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ErrorList.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ErrorList.java @@ -20,7 +20,7 @@ * @author Marco Meyer - Initial contribution */ public class ErrorList extends RobonectAnswer { - + private List errors; /** diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Health.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Health.java index 3f5ea7fbe62ad..38e46260a5853 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Health.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Health.java @@ -19,9 +19,9 @@ * @author Marco Meyer - Initial contribution */ public class Health { - + private int temperature; - + private int humidity; /** diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ModelParser.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ModelParser.java index 59cc8fa3ec0ab..a3b0a08044986 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ModelParser.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/ModelParser.java @@ -21,12 +21,11 @@ * @author Marco Meyer - Initial contribution */ public class ModelParser { - - + private final Gson gson; /** - * Creates a parser with containing a preconfigured Gson object capable of parsing the JSON answers from the + * Creates a parser with containing a preconfigured Gson object capable of parsing the JSON answers from the * Robonect module. */ public ModelParser() { @@ -34,18 +33,18 @@ public ModelParser() { gsonBuilder.registerTypeAdapter(MowerStatus.class, new MowerStatusDeserializer()); gsonBuilder.registerTypeAdapter(MowerMode.class, new MowerModeDeserializer()); gsonBuilder.registerTypeAdapter(Timer.TimerMode.class, new TimerModeDeserializer()); - this.gson = gsonBuilder.create(); + this.gson = gsonBuilder.create(); } /** * Parses a jsonString to a Java Object of the specified type. + * * @param jsonString - the json string to parse * @param type - the class of the type of the expected object to be returned. * @param - the type of expected return value. * @return */ - public T parse(String jsonString,Class type){ + public T parse(String jsonString, Class type) { return gson.fromJson(jsonString, type); } - } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerMode.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerMode.java index 28abf8930948e..91847ccee4ee1 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerMode.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerMode.java @@ -13,7 +13,7 @@ package org.openhab.binding.robonect.internal.model; /** - * The mower mode from the status information. Please note + * The mower mode from the status information. Please note * that EOD and JOB from {@link org.openhab.binding.robonect.internal.model.cmd.ModeCommand.Mode} * are just artificial and are therfore not reported in the status information. * @@ -55,6 +55,7 @@ public enum MowerMode { /** * Translate the numeric mode from the JSON response into enum values. + * * @param mode - the numeric value of the mode. * @return - the enum value of the mode. */ @@ -73,5 +74,4 @@ public static MowerMode fromMode(int mode) { public int getCode() { return code; } - } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerStatus.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerStatus.java index 31933364d4573..63dd47b7c27f3 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerStatus.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerStatus.java @@ -16,7 +16,7 @@ import org.slf4j.LoggerFactory; /** - * An enumeration for the possible mower status. + * An enumeration for the possible mower status. * * @author Marco Meyer - Initial contribution */ @@ -71,6 +71,11 @@ public enum MowerStatus { */ SLEEPING(17), + /** + * Mower waits for door to open + */ + DOORDELAY(18), + /** * unknown status. If the module return any not listed code here it will result in this state in the binding. */ @@ -86,6 +91,7 @@ public enum MowerStatus { /** * translates a numeric code into an enum value. If code is not known the value {@link #UNKNOWN} is returned. + * * @param code - the code to translate * @return - the correpsonding enum value. */ @@ -101,10 +107,10 @@ public static MowerStatus fromCode(int code) { /** * returns the numeric code of the status. + * * @return */ public int getStatusCode() { return statusCode; } - } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerStatusDeserializer.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerStatusDeserializer.java index 38668d5827f3b..391bdbf8128fa 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerStatusDeserializer.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/MowerStatusDeserializer.java @@ -24,7 +24,7 @@ * * @author Marco Meyer - Initial contribution */ -public class MowerStatusDeserializer implements JsonDeserializer{ +public class MowerStatusDeserializer implements JsonDeserializer { @Override public MowerStatus deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Name.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Name.java index 5061bd4bc2a8e..3bfa46d4e4a24 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Name.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Name.java @@ -18,7 +18,7 @@ * @author Marco Meyer - Initial contribution */ public class Name extends RobonectAnswer { - + private String name; /** diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/NextTimer.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/NextTimer.java index 1cf3393da288b..2e019b47a07d6 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/NextTimer.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/NextTimer.java @@ -18,7 +18,7 @@ * @author Marco Meyer - Initial contribution */ public class NextTimer { - + private String date; private String time; private String unix; diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/RobonectAnswer.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/RobonectAnswer.java index b5a44fccf98a6..47d8c51332cc8 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/RobonectAnswer.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/RobonectAnswer.java @@ -22,12 +22,12 @@ * @author Marco Meyer - Initial contribution */ public class RobonectAnswer { - + private boolean successful; @SerializedName("error_code") private Integer errorCode; - + @SerializedName("error_message") private String errorMessage; @@ -40,12 +40,13 @@ public boolean isSuccessful() { /** * allows to set the successful status for testing. + * * @param successful */ - public void setSuccessful(boolean successful){ + public void setSuccessful(boolean successful) { this.successful = successful; } - + /** * @return - in case of a not successful request, the error code, null otherwise. */ @@ -59,5 +60,4 @@ public Integer getErrorCode() { public String getErrorMessage() { return errorMessage; } - } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Timer.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Timer.java index d69c80f27af98..bd8fe7276482b 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Timer.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/Timer.java @@ -20,9 +20,9 @@ public class Timer { /** - * an enum defining the possible timer status. + * an enum defining the possible timer status. */ - public enum TimerMode{ + public enum TimerMode { /** * timer is inactive. No timer is set or the mower is not in AUTO mode. */ @@ -37,10 +37,10 @@ public enum TimerMode{ * timer is standby. A timer is set, the mower is in AUTO mode but the timer period did not start yet. */ STANDBY(2); - + private int code; - - TimerMode(int code){ + + TimerMode(int code) { this.code = code; } @@ -57,7 +57,7 @@ public static TimerMode fromCode(int code) { return INACTIVE; } } - + private TimerMode status; private NextTimer next; diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/TimerModeDeserializer.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/TimerModeDeserializer.java index c641f79be3b7a..ccbfb7e908dcd 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/TimerModeDeserializer.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/TimerModeDeserializer.java @@ -25,13 +25,11 @@ * @author Marco Meyer - Initial contribution */ public class TimerModeDeserializer implements JsonDeserializer { - @Override public Timer.TimerMode deserialize(JsonElement jsonElement, Type type, - JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { int code = jsonElement.getAsInt(); return Timer.TimerMode.fromCode(code); } -} - +} diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/VersionInfo.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/VersionInfo.java index aef9dd09a2498..f994e7d7752e2 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/VersionInfo.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/VersionInfo.java @@ -19,15 +19,15 @@ */ public class VersionInfo extends RobonectAnswer { - private static final RobonectVersion NA_VERSION = new RobonectVersion(); + /** * encapsulates the robonect version information. */ public static class RobonectVersion { - + private static final String NA = "n/a"; - + private String serial; private String version; @@ -36,10 +36,10 @@ public static class RobonectVersion { private String comment; - public RobonectVersion(){ - this(NA,NA,NA,NA); + public RobonectVersion() { + this(NA, NA, NA, NA); } - + public RobonectVersion(String serial, String version, String compiled, String comment) { this.serial = serial; this.version = version; @@ -91,16 +91,16 @@ public void setComment(String comment) { this.comment = comment; } } - + private RobonectVersion robonect; /** * @return - the object encapsulating the version information. See {@link RobonectVersion} */ public RobonectVersion getRobonect() { - if(robonect != null){ + if (robonect != null) { return robonect; - }else { + } else { return NA_VERSION; } } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/Command.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/Command.java index ae3a8fd49e78b..a1a7b2051f3d4 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/Command.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/Command.java @@ -16,7 +16,7 @@ /** * - * Interface implemented by all commands. The robonect module is called with urls like + * Interface implemented by all commands. The robonect module is called with urls like * http://xxx.xxx.xxx/json?cmd=[command]. The command implementation is responsible to construct the full command url. * * @@ -25,10 +25,11 @@ public interface Command { /** - * Implementations of this interface have to return baseUrl + command specific extensions, where the baseURL + * Implementations of this interface have to return baseUrl + command specific extensions, where the baseURL * already is in the form http://xxx.xxx.xxx/json? - * @param baseURL - will be passed by the {@link RobonectClient} in the form - * http://xxx.xxx.xxx/json? + * + * @param baseURL - will be passed by the {@link RobonectClient} in the form + * http://xxx.xxx.xxx/json? * @return - the full command string like for example for a name command http://xxx.xxx.xxx/json?cmd=name */ String toCommandURL(String baseURL); diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/ErrorCommand.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/ErrorCommand.java index b60ab0fd0056f..b359c558ea993 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/ErrorCommand.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/ErrorCommand.java @@ -20,29 +20,30 @@ * @author Marco Meyer - Initial contribution */ public class ErrorCommand implements Command { - + private boolean reset = false; /** * has to be set to 'true' if the errors should be reset. + * * @param reset - true if errors should be reset, false if the list of errors should be retrieved. * @return */ - public ErrorCommand withReset(boolean reset){ + public ErrorCommand withReset(boolean reset) { this.reset = reset; return this; } /** - * @param baseURL - will be passed by the {@link RobonectClient} in the form - * http://xxx.xxx.xxx/json? + * @param baseURL - will be passed by the {@link RobonectClient} in the form + * http://xxx.xxx.xxx/json? * @return - the command for retrieving or resetting the error list. */ @Override public String toCommandURL(String baseURL) { - if(reset){ + if (reset) { return baseURL + "?cmd=error&reset"; - }else { + } else { return baseURL + "?cmd=error"; } } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/ModeCommand.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/ModeCommand.java index f34c28e1fcf99..88fbcf3ff76a0 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/ModeCommand.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/ModeCommand.java @@ -19,7 +19,8 @@ * The mode commands sets the mower into the corresponding mode. In addition to the mowers standard modes * (HOME, MAN, AUTO) the module supports following modes: * - * EOD (End Of Day): The mower is set into HOME mode until midnight. After midnight the module sets the mower in AUTO mode + * EOD (End Of Day): The mower is set into HOME mode until midnight. After midnight the module sets the mower in AUTO + * mode * JOB: The JOB mode triggers a JOB and supports following additional parameter: * * remoteStart: where to start the job (STANDARD, REMOTE_1 or REMOTE_2) * * after: The mode to be set after the JOB is done. Allowed are all except JOB. @@ -75,7 +76,6 @@ public enum RemoteStart { RemoteStart(int code) { this.code = code; } - } private Mode mode; @@ -96,6 +96,7 @@ public ModeCommand(Mode mode) { /** * sets the desired remoteStart option. + * * @param remoteStart - the remoteStart option. * @return - the command instance. */ @@ -106,6 +107,7 @@ public ModeCommand withRemoteStart(RemoteStart remoteStart) { /** * set the mode after the job is done. + * * @param afterMode - the desired mode after job execution. * @return - the command instance. */ @@ -116,6 +118,7 @@ public ModeCommand withAfter(Mode afterMode) { /** * The desired start time in the format HH:MM (H=Hour, M=Minute) + * * @param startTime - the start time. * @return - the command instance. */ @@ -126,6 +129,7 @@ public ModeCommand withStart(String startTime) { /** * The desired end time in the format HH:MM (H=Hour, M=Minute) + * * @param endTime - the end time. * @return - the command instance. */ @@ -136,6 +140,7 @@ public ModeCommand withEnd(String endTime) { /** * Sets the duration in minutes. + * * @param durationInMinutes - the duration in minutes. * @return - the command instance. */ @@ -147,8 +152,8 @@ public ModeCommand withDuration(Integer durationInMinutes) { /** * {@inheritDoc} * - * @param baseURL - will be passed by the {@link RobonectClient} in the form - * http://xxx.xxx.xxx/json? + * @param baseURL - will be passed by the {@link RobonectClient} in the form + * http://xxx.xxx.xxx/json? * @return */ @Override @@ -156,30 +161,30 @@ public String toCommandURL(String baseURL) { StringBuilder sb = new StringBuilder(baseURL); sb.append("?cmd=mode&mode="); sb.append(mode.cmd); - switch (mode){ + switch (mode) { case EOD: case MANUAL: case AUTO: case HOME: break; case JOB: - if(remoteStart != null){ + if (remoteStart != null) { sb.append("&remotestart="); sb.append(remoteStart.code); } - if(after != null){ + if (after != null) { sb.append("&after="); sb.append(after.code); } - if(start != null){ + if (start != null) { sb.append("&start="); sb.append(start); } - if(end != null){ + if (end != null) { sb.append("&end="); sb.append(end); } - if(duration != null){ + if (duration != null) { sb.append("&duration="); sb.append(duration); } @@ -187,5 +192,4 @@ public String toCommandURL(String baseURL) { } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/NameCommand.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/NameCommand.java index 1dc0619e7fd03..e0d068e9d54ca 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/NameCommand.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/NameCommand.java @@ -33,6 +33,7 @@ public class NameCommand implements Command { /** * sets the mower name. + * * @param newName - the mower name. * @return - the command instance. */ @@ -42,8 +43,8 @@ public NameCommand withNewName(String newName) { } /** - * @param baseURL - will be passed by the {@link RobonectClient} in the form - * http://xxx.xxx.xxx/json? + * @param baseURL - will be passed by the {@link RobonectClient} in the form + * http://xxx.xxx.xxx/json? * @return */ @Override @@ -52,9 +53,10 @@ public String toCommandURL(String baseURL) { return baseURL + "?cmd=name"; } else { try { - return baseURL + "?cmd=name&name=" + URLEncoder.encode(newName, StandardCharsets.ISO_8859_1.displayName()); + return baseURL + "?cmd=name&name=" + + URLEncoder.encode(newName, StandardCharsets.ISO_8859_1.displayName()); } catch (UnsupportedEncodingException e) { - logger.error( "Could not encode name {} ",newName, e); + logger.error("Could not encode name {} ", newName, e); return baseURL + "?cmd=name"; } } diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StartCommand.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StartCommand.java index bf8dbbc167abc..59ad08ce571c8 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StartCommand.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StartCommand.java @@ -24,8 +24,8 @@ public class StartCommand implements Command { /** * {@inheritDoc} * - * @param baseURL - will be passed by the {@link RobonectClient} in the form - * http://xxx.xxx.xxx/json? + * @param baseURL - will be passed by the {@link RobonectClient} in the form + * http://xxx.xxx.xxx/json? * @return */ @Override diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StatusCommand.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StatusCommand.java index 2d5270dd83325..3398bfb639305 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StatusCommand.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StatusCommand.java @@ -15,7 +15,7 @@ import org.openhab.binding.robonect.internal.model.MowerStatus; /** - * Queries the mowers status. The status holds a lot of status information. + * Queries the mowers status. The status holds a lot of status information. * See {@link MowerStatus} * or the documentation at: http://www.robonect.de/viewtopic.php?f=11&t=38 * diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StopCommand.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StopCommand.java index dfa838cb94ceb..41b48404b1a20 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StopCommand.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/StopCommand.java @@ -23,8 +23,9 @@ public class StopCommand implements Command { /** * {@inheritDoc} - * @param baseURL - will be passed by the {@link RobonectClient} in the form - * http://xxx.xxx.xxx/json? + * + * @param baseURL - will be passed by the {@link RobonectClient} in the form + * http://xxx.xxx.xxx/json? * @return */ @Override diff --git a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/VersionCommand.java b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/VersionCommand.java index 61d9e7d13f5cd..1b4e3172b38a1 100644 --- a/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/VersionCommand.java +++ b/bundles/org.openhab.binding.robonect/src/main/java/org/openhab/binding/robonect/internal/model/cmd/VersionCommand.java @@ -15,8 +15,8 @@ import org.openhab.binding.robonect.internal.model.VersionInfo; /** - * Queries version information about the mower and the module. See {@link VersionInfo} - * for more information. + * Queries version information about the mower and the module. See {@link VersionInfo} + * for more information. * * @author Marco Meyer - Initial contribution */ @@ -25,5 +25,4 @@ public class VersionCommand implements Command { public String toCommandURL(String baseURL) { return baseURL + "?cmd=version"; } - } diff --git a/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/binding/binding.xml index adfc004269696..e5c43e5d8f05c 100644 --- a/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/binding/binding.xml @@ -1,9 +1,7 @@ - + Robonect Binding This is the binding for Robonect. diff --git a/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/config/config.xml index 2551acac7ede0..be33730542f66 100644 --- a/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/thing/thing-types.xml index 1317448ac775b..478a66b1966b2 100644 --- a/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.robonect/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ - + @@ -17,7 +17,7 @@ - + @@ -160,7 +160,7 @@ Switch Starts a mowing job - + diff --git a/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/RobonectClientTest.java b/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/RobonectClientTest.java index 2d07f6839925d..14a4717ff67b6 100644 --- a/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/RobonectClientTest.java +++ b/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/RobonectClientTest.java @@ -12,6 +12,11 @@ */ package org.openhab.binding.robonect.internal; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import java.nio.charset.StandardCharsets; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -30,11 +35,6 @@ import org.openhab.binding.robonect.internal.model.Name; import org.openhab.binding.robonect.internal.model.VersionInfo; -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - /** * The goal of this class is to test the functionality of the RobonectClient, * by mocking the module responses. @@ -163,11 +163,11 @@ public void shouldRetrieveVersionInfo() throws InterruptedException, ExecutionEx assertEquals("05D92D32-38355048-43203030", info.getRobonect().getSerial()); verify(httpClientMock, times(1)).newRequest("http://123.456.789.123/json?cmd=version"); } - + @Test public void shouldHandleProperEncoding() throws InterruptedException, ExecutionException, TimeoutException { - byte[] responseBytesISO88591 = "{\"successful\": true, \"name\": \"Mein Automower\", \"status\": {\"status\": 7, \"stopped\": true, \"duration\": 192, \"mode\": 1, \"battery\": 95, \"hours\": 41}, \"timer\": {\"status\": 2}, \"error\" : {\"error_code\": 15, \"error_message\": \"Utanför arbetsområdet\", \"date\": \"02.05.2017\", \"time\": \"20:36:43\", \"unix\": 1493757403}, \"wlan\": {\"signal\": -75}}".getBytes( - StandardCharsets.ISO_8859_1); + byte[] responseBytesISO88591 = "{\"successful\": true, \"name\": \"Mein Automower\", \"status\": {\"status\": 7, \"stopped\": true, \"duration\": 192, \"mode\": 1, \"battery\": 95, \"hours\": 41}, \"timer\": {\"status\": 2}, \"error\" : {\"error_code\": 15, \"error_message\": \"Utanför arbetsområdet\", \"date\": \"02.05.2017\", \"time\": \"20:36:43\", \"unix\": 1493757403}, \"wlan\": {\"signal\": -75}}" + .getBytes(StandardCharsets.ISO_8859_1); when(httpClientMock.newRequest("http://123.456.789.123/json?cmd=status")).thenReturn(requestMock); when(requestMock.method(HttpMethod.GET)).thenReturn(requestMock); when(requestMock.timeout(30000L, TimeUnit.MILLISECONDS)).thenReturn(requestMock); @@ -208,5 +208,4 @@ public void shouldReceiveErrorAnswerOnTimeoutException() when(requestMock.send()).thenThrow(new TimeoutException("Mock Timeout Exception")); MowerInfo answer = subject.getMowerInfo(); } - } diff --git a/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/handler/RobonectHandlerTest.java b/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/handler/RobonectHandlerTest.java index 070851d68e6db..9fd6fa89c0026 100644 --- a/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/handler/RobonectHandlerTest.java +++ b/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/handler/RobonectHandlerTest.java @@ -12,6 +12,13 @@ */ package org.openhab.binding.robonect.internal.handler; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import java.util.Calendar; import org.eclipse.jetty.client.HttpClient; @@ -34,7 +41,6 @@ import org.mockito.MockitoAnnotations; import org.openhab.binding.robonect.internal.RobonectBindingConstants; import org.openhab.binding.robonect.internal.RobonectClient; -import org.openhab.binding.robonect.internal.handler.RobonectHandler; import org.openhab.binding.robonect.internal.model.ErrorEntry; import org.openhab.binding.robonect.internal.model.ErrorList; import org.openhab.binding.robonect.internal.model.MowerInfo; @@ -45,20 +51,13 @@ import org.openhab.binding.robonect.internal.model.Timer; import org.openhab.binding.robonect.internal.model.Wlan; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - /** * The goal of this class is to test RobonectHandler in isolation. * * @author Marco Meyer - Initial contribution */ public class RobonectHandlerTest { - + private RobonectHandler subject; @Mock @@ -69,7 +68,7 @@ public class RobonectHandlerTest { @Mock private ThingHandlerCallback callbackMock; - + @Mock private HttpClient httpClientMock; @@ -100,7 +99,7 @@ public void shouldUpdateNextTimerChannelWithDateTimeState() throws InterruptedEx when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3")); subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_TIMER_NEXT_TIMER), - RefreshType.REFRESH); + RefreshType.REFRESH); // then verify(callbackMock, times(1)).stateUpdated( @@ -145,18 +144,18 @@ public void shouldUpdateErrorChannelsIfErrorStatusReturned() throws InterruptedE when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3")); subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS), - RefreshType.REFRESH); + RefreshType.REFRESH); // then - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_CODE)), - errorCodeCaptor.capture()); - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_MESSAGE)), - errorMessageCaptor.capture()); - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_DATE)), - errorDateCaptor.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_CODE)), + errorCodeCaptor.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_MESSAGE)), + errorMessageCaptor.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_DATE)), + errorDateCaptor.capture()); State errorDate = errorDateCaptor.getValue(); assertTrue(errorDate instanceof DateTimeType); @@ -196,18 +195,18 @@ public void shouldResetErrorStateIfNoErrorInStatusUpdate() throws InterruptedExc when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3")); subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS), - RefreshType.REFRESH); + RefreshType.REFRESH); // then - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_CODE)), - errorCodeCaptor.capture()); - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_MESSAGE)), - errorMessageCaptor.capture()); - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_DATE)), - errorDateCaptor.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_CODE)), + errorCodeCaptor.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_MESSAGE)), + errorMessageCaptor.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_ERROR_DATE)), + errorDateCaptor.capture()); assertEquals(errorCodeCaptor.getValue(), UnDefType.UNDEF); assertEquals(errorMessageCaptor.getValue(), UnDefType.UNDEF); @@ -227,19 +226,18 @@ public void shouldUpdateNumericStateOnMowerStatusRefresh() throws InterruptedExc when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3")); subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS), - RefreshType.REFRESH); + RefreshType.REFRESH); // then - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS)), - stateCaptor.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS)), + stateCaptor.capture()); State value = stateCaptor.getValue(); assertTrue(value instanceof DecimalType); DecimalType status = (DecimalType) value; assertEquals(MowerStatus.MOWING.getStatusCode(), status.intValue()); - } @Test @@ -257,50 +255,49 @@ public void shouldUpdateAllChannels() { MowerInfo mowerInfo = createSuccessfulMowerInfoResponse(); ErrorList errorList = new ErrorList(); errorList.setSuccessful(true); - + // when when(robonectClientMock.getMowerInfo()).thenReturn(mowerInfo); when(robonectClientMock.errorList()).thenReturn(errorList); when(robonectThingMock.getUID()).thenReturn(new ThingUID("1:2:3")); subject.handleCommand(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS), - RefreshType.REFRESH); - + RefreshType.REFRESH); + // then - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_MOWER_NAME)), - stateCaptorName.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_MOWER_NAME)), + stateCaptorName.capture()); verify(callbackMock, times(1)).stateUpdated( eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_BATTERY)), stateCaptorBattery.capture()); - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS)), - stateCaptorStatus.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS)), + stateCaptorStatus.capture()); verify(callbackMock, times(1)).stateUpdated( eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_DURATION)), stateCaptorDuration.capture()); - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_HOURS)), - stateCaptorHours.capture()); - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_MODE)), - stateCaptorMode.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_HOURS)), + stateCaptorHours.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_STATUS_MODE)), + stateCaptorMode.capture()); verify(callbackMock, times(1)).stateUpdated( eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_MOWER_START)), stateCaptorStarted.capture()); - verify(callbackMock, times(1)) - .stateUpdated(eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_WLAN_SIGNAL)), - stateCaptorWlan.capture()); + verify(callbackMock, times(1)).stateUpdated( + eq(new ChannelUID(new ThingUID("1:2:3"), RobonectBindingConstants.CHANNEL_WLAN_SIGNAL)), + stateCaptorWlan.capture()); assertEquals("Mowy", stateCaptorName.getValue().toFullString()); - assertEquals(99, ((DecimalType)stateCaptorBattery.getValue()).intValue()); - assertEquals(4, ((DecimalType)stateCaptorStatus.getValue()).intValue()); - assertEquals(55, ((QuantityType)stateCaptorDuration.getValue()).intValue()); - assertEquals(22, ((QuantityType)stateCaptorHours.getValue()).intValue()); + assertEquals(99, ((DecimalType) stateCaptorBattery.getValue()).intValue()); + assertEquals(4, ((DecimalType) stateCaptorStatus.getValue()).intValue()); + assertEquals(55, ((QuantityType) stateCaptorDuration.getValue()).intValue()); + assertEquals(22, ((QuantityType) stateCaptorHours.getValue()).intValue()); assertEquals(MowerMode.AUTO.name(), stateCaptorMode.getValue().toFullString()); assertEquals(OnOffType.ON, stateCaptorStarted.getValue()); - assertEquals(-88, ((DecimalType)stateCaptorWlan.getValue()).intValue()); - + assertEquals(-88, ((DecimalType) stateCaptorWlan.getValue()).intValue()); } private MowerInfo createSuccessfulMowerInfoResponse() { diff --git a/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/model/ModelParserTest.java b/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/model/ModelParserTest.java index e23f6ccb2108d..83d74c82cc3fe 100644 --- a/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/model/ModelParserTest.java +++ b/bundles/org.openhab.binding.robonect/src/test/java/org/openhab/binding/robonect/internal/model/ModelParserTest.java @@ -12,15 +12,13 @@ */ package org.openhab.binding.robonect.internal.model; -import java.nio.charset.StandardCharsets; +import static org.junit.Assert.*; -import org.openhab.binding.robonect.internal.model.ModelParser; +import java.nio.charset.StandardCharsets; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; - /** * The goal of this class is to test the model parser to make sure the structures * returned from the module can be handled. @@ -101,17 +99,17 @@ public void shouldParseCorrectStatusModelWithHealth() { assertEquals(28, mowerInfo.getHealth().getTemperature()); assertEquals(32, mowerInfo.getHealth().getHumidity()); // "health": { "temperature": 28, "humidity": 32 } - } @Test public void shouldParseISOEncodedStatusModel() { - byte[] responseBytesISO88591 = "{\"successful\": true, \"name\": \"Mein Automower\", \"status\": {\"status\": 7, \"stopped\": true, \"duration\": 192, \"mode\": 1, \"battery\": 95, \"hours\": 41}, \"timer\": {\"status\": 2}, \"error\" : {\"error_code\": 15, \"error_message\": \"Utanför arbetsområdet\", \"date\": \"02.05.2017\", \"time\": \"20:36:43\", \"unix\": 1493757403}, \"wlan\": {\"signal\": -75}}".getBytes( - StandardCharsets.ISO_8859_1); - MowerInfo mowerInfo = subject.parse(new String(responseBytesISO88591, StandardCharsets.ISO_8859_1), MowerInfo.class); + byte[] responseBytesISO88591 = "{\"successful\": true, \"name\": \"Mein Automower\", \"status\": {\"status\": 7, \"stopped\": true, \"duration\": 192, \"mode\": 1, \"battery\": 95, \"hours\": 41}, \"timer\": {\"status\": 2}, \"error\" : {\"error_code\": 15, \"error_message\": \"Utanför arbetsområdet\", \"date\": \"02.05.2017\", \"time\": \"20:36:43\", \"unix\": 1493757403}, \"wlan\": {\"signal\": -75}}" + .getBytes(StandardCharsets.ISO_8859_1); + MowerInfo mowerInfo = subject.parse(new String(responseBytesISO88591, StandardCharsets.ISO_8859_1), + MowerInfo.class); assertEquals("Utanför arbetsområdet", mowerInfo.getError().getErrorMessage()); } - + @Test public void shouldParseCorrectStatusModelWithErrorCode() { String correctModel = "{\"successful\": true, \"name\": \"Grasi\", \"status\": {\"status\": 7, \"stopped\": true, \"duration\": 423, \"mode\": 0, \"battery\": 83, \"hours\": 55}, \"timer\": {\"status\": 2, \"next\": {\"date\": \"15.05.2017\", \"time\": \"19:00:00\", \"unix\": 1494874800}}, \"wlan\": {\"signal\": -76}, \"error\": {\"error_code\": 9, \"error_message\": \"Grasi ist eingeklemmt\", \"date\": \"13.05.2017\", \"time\": \"23:00:22\", \"unix\": 1494716422}}"; @@ -133,7 +131,6 @@ public void shouldParseCorrectStatusModelMowing() { assertEquals(MowerStatus.MOWING, mowerInfo.getStatus().getStatus()); assertFalse(mowerInfo.getStatus().isStopped()); assertEquals(MowerMode.MANUAL, mowerInfo.getStatus().getMode()); - } @Test @@ -183,41 +180,17 @@ public void shouldParseVersionInfo() { assertEquals("2017-03-25 20:10:00", versionInfo.getRobonect().getCompiled()); assertEquals("V0.9c", versionInfo.getRobonect().getComment()); } - + @Test - public void shouldParseVersionInfoV1betaToNA(){ - String versionResponse = "{\n" + - "mower: {\n" + - "hardware: {\n" + - "serial: 170602001,\n" + - "production: \"2017-02-07 15:12:00\"\n" + - "},\n" + - "msw: {\n" + - "title: \"420\",\n" + - "version: \"7.10.00\",\n" + - "compiled: \"2016-11-29 08:44:06\"\n" + - "},\n" + - "sub: {\n" + - "version: \"6.01.00\"\n" + - "}\n" + - "},\n" + - "serial: \"05D80037-39355548-43163930\",\n" + - "bootloader: {\n" + - "version: \"V0.4\",\n" + - "compiled: \"2016-10-22 01:12:00\",\n" + - "comment: \"\"\n" + - "},\n" + - "wlan: {\n" + - "at-version: \"V1.4.0\",\n" + - "sdk-version: \"V2.1.0\"\n" + - "},\n" + - "application: {\n" + - "version: \"V1.0\",\n" + - "compiled: \"2018-03-12 21:01:00\",\n" + - "comment: \"Release V1.0 Beta2\"\n" + - "},\n" + - "successful: true\n" + - "}"; + public void shouldParseVersionInfoV1betaToNA() { + String versionResponse = "{\n" + "mower: {\n" + "hardware: {\n" + "serial: 170602001,\n" + + "production: \"2017-02-07 15:12:00\"\n" + "},\n" + "msw: {\n" + "title: \"420\",\n" + + "version: \"7.10.00\",\n" + "compiled: \"2016-11-29 08:44:06\"\n" + "},\n" + "sub: {\n" + + "version: \"6.01.00\"\n" + "}\n" + "},\n" + "serial: \"05D80037-39355548-43163930\",\n" + + "bootloader: {\n" + "version: \"V0.4\",\n" + "compiled: \"2016-10-22 01:12:00\",\n" + + "comment: \"\"\n" + "},\n" + "wlan: {\n" + "at-version: \"V1.4.0\",\n" + "sdk-version: \"V2.1.0\"\n" + + "},\n" + "application: {\n" + "version: \"V1.0\",\n" + "compiled: \"2018-03-12 21:01:00\",\n" + + "comment: \"Release V1.0 Beta2\"\n" + "},\n" + "successful: true\n" + "}"; VersionInfo versionInfo = subject.parse(versionResponse, VersionInfo.class); assertTrue(versionInfo.isSuccessful()); assertEquals("n/a", versionInfo.getRobonect().getSerial()); diff --git a/bundles/org.openhab.binding.rotel/pom.xml b/bundles/org.openhab.binding.rotel/pom.xml index 2153d880c7d77..169a49143254d 100644 --- a/bundles/org.openhab.binding.rotel/pom.xml +++ b/bundles/org.openhab.binding.rotel/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.rotel diff --git a/bundles/org.openhab.binding.rotel/src/main/feature/feature.xml b/bundles/org.openhab.binding.rotel/src/main/feature/feature.xml index a7e71d801a557..8be94044219db 100644 --- a/bundles/org.openhab.binding.rotel/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.rotel/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.rotel/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.rotel/${project.version} + diff --git a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelHandlerFactory.java b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelHandlerFactory.java index 161c22dd74329..d369b912df8da 100644 --- a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelHandlerFactory.java +++ b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelHandlerFactory.java @@ -28,6 +28,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.rotel.internal.handler.RotelHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -52,9 +53,16 @@ public class RotelHandlerFactory extends BaseThingHandlerFactory { THING_TYPE_RT09, THING_TYPE_RT11, THING_TYPE_RT1570, THING_TYPE_T11, THING_TYPE_T14) .collect(Collectors.toSet())); - private @NonNullByDefault({}) SerialPortManager serialPortManager; + private final SerialPortManager serialPortManager; - private @NonNullByDefault({}) RotelStateDescriptionOptionProvider stateDescriptionProvider; + private final RotelStateDescriptionOptionProvider stateDescriptionProvider; + + @Activate + public RotelHandlerFactory(final @Reference SerialPortManager serialPortManager, + final @Reference RotelStateDescriptionOptionProvider stateDescriptionProvider) { + this.serialPortManager = serialPortManager; + this.stateDescriptionProvider = stateDescriptionProvider; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -71,22 +79,4 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return null; } - - @Reference - protected void setSerialPortManager(final SerialPortManager serialPortManager) { - this.serialPortManager = serialPortManager; - } - - protected void unsetSerialPortManager(final SerialPortManager serialPortManager) { - this.serialPortManager = null; - } - - @Reference - protected void setDynamicStateDescriptionProvider(RotelStateDescriptionOptionProvider stateDescriptionProvider) { - this.stateDescriptionProvider = stateDescriptionProvider; - } - - protected void unsetDynamicStateDescriptionProvider(RotelStateDescriptionOptionProvider stateDescriptionProvider) { - this.stateDescriptionProvider = null; - } } diff --git a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelModel.java b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelModel.java index 9f85cabed9cd2..7ac39c8d75fc7 100644 --- a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelModel.java +++ b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/RotelModel.java @@ -816,5 +816,4 @@ public static RotelModel getFromName(String name) throws RotelException { } throw new RotelException("Invalid model name: " + name); } - } diff --git a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelFlagsMapping.java b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelFlagsMapping.java index 40040e6a53758..6ee44281e0101 100644 --- a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelFlagsMapping.java +++ b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelFlagsMapping.java @@ -256,5 +256,4 @@ private static void setBitFlag(byte[] flags, int flagNumber, int bitNumber, bool flags[flagNumber - 1] &= ~(1 << bitNumber); } } - } diff --git a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelMessageEvent.java b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelMessageEvent.java index a965bc5aef8af..a6f71b4ecf1e9 100644 --- a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelMessageEvent.java +++ b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelMessageEvent.java @@ -41,5 +41,4 @@ public String getKey() { public String getValue() { return value; } - } diff --git a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelMessageEventListener.java b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelMessageEventListener.java index 57093319771dc..d4727413cb683 100644 --- a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelMessageEventListener.java +++ b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelMessageEventListener.java @@ -31,5 +31,4 @@ public interface RotelMessageEventListener extends EventListener { * @param event the event object */ public void onNewMessageEvent(EventObject event); - } diff --git a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelProtocol.java b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelProtocol.java index 4b5ccd3d7a8cf..36f1799c95f5b 100644 --- a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelProtocol.java +++ b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/communication/RotelProtocol.java @@ -64,5 +64,4 @@ public static RotelProtocol getFromName(String name) throws RotelException { } throw new RotelException("Invalid protocol name: " + name); } - } diff --git a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/configuration/RotelThingConfiguration.java b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/configuration/RotelThingConfiguration.java index 91e5b20bae17e..f6591c81a4ad8 100644 --- a/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/configuration/RotelThingConfiguration.java +++ b/bundles/org.openhab.binding.rotel/src/main/java/org/openhab/binding/rotel/internal/configuration/RotelThingConfiguration.java @@ -38,5 +38,4 @@ public class RotelThingConfiguration { public @NonNullByDefault({}) String inputLabelUsb; public @NonNullByDefault({}) String inputLabelMulti; public @NonNullByDefault({}) String protocol; - } diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/binding/binding.xml index 86356b4d68f98..b7a9626e1c83f 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/binding/binding.xml @@ -4,7 +4,8 @@ xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd"> Rotel Binding - The Rotel binding controls a Rotel audio device like a surround processor, a surround receiver, a stereo preamplifier, an integrated amplifier, a CD player or a tuner. + The Rotel binding controls a Rotel audio device like a surround processor, a surround receiver, a stereo + preamplifier, an integrated amplifier, a CD player or a tuner. Laurent Garnier diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/config/config.xml index 42d836f3a14e7..a8e433f62f3c9 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/config/config.xml @@ -8,6 +8,7 @@ serial-port + false Serial port to use for connecting to the Rotel device @@ -25,17 +26,20 @@ serial-port + false Serial port to use for connecting to the Rotel device network-address - Host name or IP address of the Rotel device (IP connection) or the machine connected to the Rotel device (serial over IP) + Host name or IP address of the Rotel device (IP connection) or the machine connected to the Rotel device + (serial over IP) - Communication port (IP or serial over IP). For IP connection to the Rotel device, keep the default port 9590 + Communication port (IP or serial over IP). For IP connection to the Rotel device, keep the default port + 9590 9590 @@ -43,17 +47,20 @@ serial-port + false Serial port to use for connecting to the Rotel device network-address - Host name or IP address of the Rotel device (IP connection) or the machine connected to the Rotel device (serial over IP) + Host name or IP address of the Rotel device (IP connection) or the machine connected to the Rotel device + (serial over IP) - Communication port (IP or serial over IP). For IP connection to the Rotel device, keep the default port 9590 + Communication port (IP or serial over IP). For IP connection to the Rotel device, keep the default port + 9590 9596 @@ -61,17 +68,20 @@ serial-port + false Serial port to use for connecting to the Rotel device network-address - Host name or IP address of the Rotel device (IP connection) or the machine connected to the Rotel device (serial over IP) + Host name or IP address of the Rotel device (IP connection) or the machine connected to the Rotel device + (serial over IP) - Communication port (IP or serial over IP). For IP connection to the Rotel device, keep the default port 9590 + Communication port (IP or serial over IP). For IP connection to the Rotel device, keep the default port + 9590 9590 @@ -90,6 +100,7 @@ serial-port + false Serial port to use for connecting to the Rotel device @@ -118,6 +129,7 @@ serial-port + false Serial port to use for connecting to the Rotel device @@ -155,6 +167,7 @@ serial-port + false Serial port to use for connecting to the Rotel device @@ -204,6 +217,7 @@ serial-port + false Serial port to use for connecting to the Rotel device @@ -257,6 +271,7 @@ serial-port + false Serial port to use for connecting to the Rotel device diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a11.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a11.xml index 6c6bdfadf7871..824261a7c5248 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a11.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a11.xml @@ -10,20 +10,20 @@ Connection to the Rotel A11 integrated amplifier - - - - - - - + + + + + + + ASCII_V2 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a12.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a12.xml index f6df022f7daa6..a8aec80d67082 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a12.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a12.xml @@ -10,21 +10,21 @@ Connection to the Rotel A12 integrated amplifier - - - - - - - - + + + + + + + + ASCII_V2 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a14.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a14.xml index e622d699520ae..e69b811108b3e 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a14.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/a14.xml @@ -10,21 +10,21 @@ Connection to the Rotel A14 integrated amplifier - - - - - - - - + + + + + + + + ASCII_V2 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/cd11.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/cd11.xml index 4955adb3e56e9..6a401b1d28d7d 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/cd11.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/cd11.xml @@ -10,17 +10,17 @@ Connection to the Rotel CD11 CD player - - - - + + + + ASCII_V2 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/cd14.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/cd14.xml index 3ff5492c38ed3..fccc0d71f5651 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/cd14.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/cd14.xml @@ -10,17 +10,17 @@ Connection to the Rotel CD14 CD player - - - - + + + + ASCII_V2 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/channels.xml index 8f34460f7b55f..53ad66ed44733 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/channels.xml @@ -8,16 +8,16 @@ The controls of the main zone - - - - - - - - - - + + + + + + + + + + @@ -25,14 +25,14 @@ The controls of the main zone - - - - - - - - + + + + + + + + @@ -40,15 +40,15 @@ The controls of the main zone - - - - - - - - - + + + + + + + + + @@ -56,16 +56,16 @@ The controls of the main zone - - - - - - - - - - + + + + + + + + + + @@ -73,15 +73,15 @@ The controls of the main zone - - - - - - - - - + + + + + + + + + @@ -89,10 +89,10 @@ The controls of the zone 2 - - - - + + + + @@ -100,9 +100,9 @@ The controls of the zone 2 - - - + + + @@ -110,10 +110,10 @@ The controls of the zone 3 - - - - + + + + @@ -121,10 +121,10 @@ The controls of the zone 4 - - - - + + + + @@ -151,7 +151,7 @@ Increase or decrease the volume SoundVolume - + veto @@ -159,7 +159,7 @@ Number Adjust the bass - + veto @@ -167,7 +167,7 @@ Number Adjust the treble - + veto @@ -175,14 +175,14 @@ Number The current CD track number - + Number The current frequency (in kHz) for digital source input - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra11.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra11.xml index 57998d86cbc96..b2480d37d2f28 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra11.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra11.xml @@ -10,22 +10,22 @@ Connection to the Rotel RA-11 integrated amplifier - - - - - - - - - + + + + + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra12.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra12.xml index ef768c6a5fb91..8435e3fe5a09a 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra12.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra12.xml @@ -10,22 +10,22 @@ Connection to the Rotel RA-12 integrated amplifier - - - - - - - - - + + + + + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1570.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1570.xml index f0b3d5705f281..636b985fa36b6 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1570.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1570.xml @@ -10,22 +10,22 @@ Connection to the Rotel RA-1570 integrated amplifier - - - - - - - - - + + + + + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1572.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1572.xml index 5f04b95bc1941..d3e671a71ad0b 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1572.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1572.xml @@ -10,17 +10,17 @@ Connection to the Rotel RA-1572 integrated amplifier - - - - - - - - + + + + + + + + - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1592.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1592.xml index 94b2753838a86..437fd88619cce 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1592.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/ra1592.xml @@ -10,17 +10,17 @@ Connection to the Rotel RA-1592 integrated amplifier - - - - - - - - + + + + + + + + - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rap1580.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rap1580.xml index 987fe423c832c..c6d942947ba15 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rap1580.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rap1580.xml @@ -10,19 +10,19 @@ Connection to the Rotel RAP-1580 surround amplified processor - - - - - - + + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1570.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1570.xml index 1a5d23acf1c27..b28f8f33e8f3f 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1570.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1570.xml @@ -10,22 +10,22 @@ Connection to the Rotel RC-1570 stereo preamplifier - - - - - - - - - + + + + + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1572.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1572.xml index ae21c90783c5e..0fb3417f38e88 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1572.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1572.xml @@ -10,17 +10,17 @@ Connection to the Rotel RC-1572 stereo preamplifier - - - - - - - - + + + + + + + + - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1590.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1590.xml index 2d3160c26a803..80c0966a418a3 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1590.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rc1590.xml @@ -10,21 +10,21 @@ Connection to the Rotel RC-1590 stereo preamplifier - - - - - - - - + + + + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcd1570.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcd1570.xml index c89548d0574aa..adb291d4b33dc 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcd1570.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcd1570.xml @@ -10,16 +10,16 @@ Connection to the Rotel RCD-1570 CD player - - - + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcd1572.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcd1572.xml index 42d230cbc704c..365700812ed55 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcd1572.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcd1572.xml @@ -10,13 +10,13 @@ Connection to the Rotel RCD-1572 CD player - - - - + + + + - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcx1500.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcx1500.xml index 92a759a3171bb..3656bedaf34f7 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcx1500.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rcx1500.xml @@ -10,18 +10,18 @@ Connection to the Rotel RCX-1500 stereo receiver - - - - - + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rdd1580.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rdd1580.xml index 2b36ed42533a3..359a7fded3c88 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rdd1580.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rdd1580.xml @@ -10,17 +10,17 @@ Connection to the Rotel RDD-1580 stereo DAC - - - - + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rdg1520.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rdg1520.xml index dc3e556a5dceb..32fc5b2faf32c 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rdg1520.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rdg1520.xml @@ -10,16 +10,16 @@ Connection to the Rotel RDG-1520 tuner - - - + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1066.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1066.xml index cbc8817ec9d01..5fa1ad51fe304 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1066.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1066.xml @@ -10,15 +10,15 @@ Connection to the Rotel RSP-1066 surround processor - - + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1068.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1068.xml index 9a2145a4babf1..af0ab1a46c654 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1068.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1068.xml @@ -10,15 +10,15 @@ Connection to the Rotel RSP-1068 surround processor - - + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1069.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1069.xml index f36e15272a27f..1ac6649cc76d6 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1069.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1069.xml @@ -10,17 +10,17 @@ Connection to the Rotel RSP-1069 surround processor - - - - + + + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1098.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1098.xml index 02579824f9768..9d69277e83d73 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1098.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1098.xml @@ -10,15 +10,15 @@ Connection to the Rotel RSP-1098 surround processor - - + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1570.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1570.xml index 7f1d0cd3389ca..262f575a2d27d 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1570.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1570.xml @@ -10,17 +10,17 @@ Connection to the Rotel RSP-1570 surround processor - - - - + + + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1572.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1572.xml index c92bf9f2f0735..8c9598c989fcc 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1572.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1572.xml @@ -10,17 +10,17 @@ Connection to the Rotel RSP-1572 surround processor - - - - + + + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1576.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1576.xml index 3831d5116a239..30db04ead9036 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1576.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1576.xml @@ -10,19 +10,19 @@ Connection to the Rotel RSP-1576 surround processor - - - - - - + + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1582.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1582.xml index 2d4495c64c626..3c78565a204b5 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1582.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsp1582.xml @@ -10,19 +10,19 @@ Connection to the Rotel RSP-1582 surround processor - - - - - - + + + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1055.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1055.xml index f88bbdcd7304a..61cb89c4e1dcd 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1055.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1055.xml @@ -10,15 +10,15 @@ Connection to the Rotel RSX-1055 surround receiver - - + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1056.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1056.xml index 3342e731680d2..31bcea2667358 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1056.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1056.xml @@ -10,15 +10,15 @@ Connection to the Rotel RSX-1056 surround receiver - - + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1057.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1057.xml index 628d46f576632..8796972b2732b 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1057.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1057.xml @@ -10,15 +10,15 @@ Connection to the Rotel RSX-1057 surround receiver - - + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1058.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1058.xml index bd6160aaf6fd3..30d09677230df 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1058.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1058.xml @@ -10,17 +10,17 @@ Connection to the Rotel RSX-1058 surround receiver - - - - + + + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1065.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1065.xml index 639fe6dee8afb..74f57e63c0a49 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1065.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1065.xml @@ -10,15 +10,15 @@ Connection to the Rotel RSX-1065 surround receiver - - + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1067.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1067.xml index 4f3f70540f366..c7495fbf5108f 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1067.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1067.xml @@ -10,15 +10,15 @@ Connection to the Rotel RSX-1067 surround receiver - - + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1550.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1550.xml index f4ed54f72da4c..c47626b2e4f8a 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1550.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1550.xml @@ -10,17 +10,17 @@ Connection to the Rotel RSX-1550 surround receiver - - - - + + + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1560.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1560.xml index 8a709659da55a..a3b069cdec2aa 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1560.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1560.xml @@ -10,17 +10,17 @@ Connection to the Rotel RSX-1560 surround receiver - - - - + + + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1562.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1562.xml index 0f7ee74290163..79c5ee36af9d2 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1562.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rsx1562.xml @@ -10,17 +10,17 @@ Connection to the Rotel RSX-1562 surround receiver - - - - + + + + HEX - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt09.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt09.xml index fea122796965c..639209fcd4dc8 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt09.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt09.xml @@ -10,17 +10,17 @@ Connection to the Rotel RT-09 tuner - - - - + + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt11.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt11.xml index 09f697484fdd6..f902738f65cd8 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt11.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt11.xml @@ -10,16 +10,16 @@ Connection to the Rotel RT-11 tuner - - - + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt1570.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt1570.xml index f34e52c40735f..e35b06345d441 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt1570.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/rt1570.xml @@ -10,16 +10,16 @@ Connection to the Rotel RT-1570 tuner - - - + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/t11.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/t11.xml index 232d9f929f8ce..ed0f8e71d9000 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/t11.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/t11.xml @@ -10,16 +10,16 @@ Connection to the Rotel T11 tuner - - - + + + ASCII_V1 - + diff --git a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/t14.xml b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/t14.xml index 262586ad2acbe..3af348acb6b6b 100644 --- a/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/t14.xml +++ b/bundles/org.openhab.binding.rotel/src/main/resources/ESH-INF/thing/t14.xml @@ -10,16 +10,16 @@ Connection to the Rotel T14 tuner - - - + + + ASCII_V2 - + diff --git a/bundles/org.openhab.binding.rotelra1x/pom.xml b/bundles/org.openhab.binding.rotelra1x/pom.xml index d4f4e3609d2da..8b84e8a91f390 100644 --- a/bundles/org.openhab.binding.rotelra1x/pom.xml +++ b/bundles/org.openhab.binding.rotelra1x/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.rotelra1x diff --git a/bundles/org.openhab.binding.rotelra1x/src/main/feature/feature.xml b/bundles/org.openhab.binding.rotelra1x/src/main/feature/feature.xml index dcbc260ab1557..47b7daeb9bec8 100644 --- a/bundles/org.openhab.binding.rotelra1x/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.rotelra1x/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.rotelra1x/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.rotelra1x/${project.version} + diff --git a/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/ConfigurationError.java b/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/ConfigurationError.java index a1f641cee1d90..10732ebf11546 100644 --- a/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/ConfigurationError.java +++ b/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/ConfigurationError.java @@ -25,5 +25,4 @@ public class ConfigurationError extends Exception { public ConfigurationError(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/RotelRa1xBindingConstants.java b/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/RotelRa1xBindingConstants.java index 081a5e584611f..86198b27e8914 100644 --- a/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/RotelRa1xBindingConstants.java +++ b/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/RotelRa1xBindingConstants.java @@ -34,5 +34,4 @@ public class RotelRa1xBindingConstants { public static final String CHANNEL_BRIGHTNESS = "brightness"; public static final String CHANNEL_FREQUENCY = "frequency"; public static final String CHANNEL_SOURCE = "source"; - } diff --git a/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/handler/RotelRa1xHandler.java b/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/handler/RotelRa1xHandler.java index 98ee982937b28..895b09cbcb3cc 100644 --- a/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/handler/RotelRa1xHandler.java +++ b/bundles/org.openhab.binding.rotelra1x/src/main/java/org/openhab/binding/rotelra1x/internal/handler/RotelRa1xHandler.java @@ -381,5 +381,4 @@ private void handleSource(Command command) throws IOException { sendIfPowerOn("get_current_source!"); } } - } diff --git a/bundles/org.openhab.binding.rotelra1x/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.rotelra1x/src/main/resources/ESH-INF/binding/binding.xml index 4a7e30a431513..d7b63c48857e6 100644 --- a/bundles/org.openhab.binding.rotelra1x/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.rotelra1x/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Rotel RA1x Binding Binding for Rotal RA11 and RA12 stereo amplifiers connected via RS232. diff --git a/bundles/org.openhab.binding.rotelra1x/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.rotelra1x/src/main/resources/ESH-INF/thing/thing-types.xml index d509652e95cd6..19976b812e938 100644 --- a/bundles/org.openhab.binding.rotelra1x/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.rotelra1x/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -23,7 +23,7 @@ Select serial port (COM1, /dev/ttyS0, ...) true - diff --git a/bundles/org.openhab.binding.russound/pom.xml b/bundles/org.openhab.binding.russound/pom.xml index 2135af19c42d2..dd9d39b42305f 100644 --- a/bundles/org.openhab.binding.russound/pom.xml +++ b/bundles/org.openhab.binding.russound/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.russound diff --git a/bundles/org.openhab.binding.russound/src/main/feature/feature.xml b/bundles/org.openhab.binding.russound/src/main/feature/feature.xml index dc23cf8510191..395aa637f29cd 100644 --- a/bundles/org.openhab.binding.russound/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.russound/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.russound/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.russound/${project.version} + diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/RussoundHandlerFactory.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/RussoundHandlerFactory.java index fa68ecb06fa7e..3b69da7781e20 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/RussoundHandlerFactory.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/RussoundHandlerFactory.java @@ -87,5 +87,4 @@ private synchronized void registerThingDiscovery(RioSystemHandler bridgeHandler) bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()); discoveryService.activate(); } - } diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/discovery/RioSystemDiscovery.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/discovery/RioSystemDiscovery.java index 8adaf0e5ee446..a317b0c9b841e 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/discovery/RioSystemDiscovery.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/discovery/RioSystemDiscovery.java @@ -143,7 +143,6 @@ protected synchronized void stopScan() { } executorService.shutdown(); executorService = null; - } /** @@ -223,6 +222,5 @@ private void addResult(String ipAddress, String type) { .withLabel("Russound " + type).build(); thingDiscovered(result); } - } } diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/net/SocketSession.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/net/SocketSession.java index c01a9fd69be87..5b125aec83385 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/net/SocketSession.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/net/SocketSession.java @@ -84,5 +84,4 @@ public interface SocketSession { * @throws java.io.IOException an exception that occurred while sending */ void sendCommand(String command) throws IOException; - } diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/RioSystemFavoritesProtocol.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/RioSystemFavoritesProtocol.java index 9118e0558d166..af4ef2d856801 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/RioSystemFavoritesProtocol.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/RioSystemFavoritesProtocol.java @@ -98,7 +98,6 @@ public RioSystemFavoritesProtocol(SocketSession session, RioHandlerCallback call for (int x = 1; x <= 32; x++) { systemFavorites[x - 1] = new RioFavorite(x); } - } /** diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/StatefulHandlerCallback.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/StatefulHandlerCallback.java index 4b77eb27f8868..ae9d0c487b2bd 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/StatefulHandlerCallback.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/StatefulHandlerCallback.java @@ -78,7 +78,6 @@ public void statusChanged(ThingStatus status, ThingStatusDetail detail, String m // If we got this far - call the underlying one wrappedCallback.statusChanged(status, detail, msg); - } /** @@ -109,7 +108,6 @@ public void stateChanged(String channelId, State newState) { // Something changed - save the new state and call the underlying wrapped state.put(channelId, newState); wrappedCallback.stateChanged(channelId, newState); - } /** @@ -134,7 +132,6 @@ public void removeState(String channelId) { @Override public void setProperty(String propertyName, String propertyValue) { wrappedCallback.setProperty(propertyName, propertyValue); - } /** @@ -150,7 +147,6 @@ public State getProperty(String propertyName) { @Override public void addListener(String channelId, RioHandlerCallbackListener listener) { wrappedCallback.addListener(channelId, listener); - } @Override diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/controller/RioControllerHandler.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/controller/RioControllerHandler.java index 22a78f8c3b244..91aff9a6ffa5a 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/controller/RioControllerHandler.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/controller/RioControllerHandler.java @@ -74,7 +74,6 @@ public void stateUpdate(String channelId, State state) { */ public RioControllerHandler(Bridge bridge) { super(bridge); - } /** @@ -203,7 +202,6 @@ public void setProperty(String propertyName, String property) { getProtocolHandler().postOnline(); refreshNamedHandler(gson, RioZoneHandler.class, RioConstants.CHANNEL_CTLZONES); - } /** diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/controller/RioControllerProtocol.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/controller/RioControllerProtocol.java index 22415d4221b1e..7eb8810b68bb8 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/controller/RioControllerProtocol.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/controller/RioControllerProtocol.java @@ -146,7 +146,6 @@ private void handleControllerNotification(Matcher m, String resp) { } else { logger.debug("Invalid Controller Notification response: '{}'", resp); } - } /** diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/source/RioSourceProtocol.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/source/RioSourceProtocol.java index c0fbcf26921aa..dc7dfc249d71b 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/source/RioSourceProtocol.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/source/RioSourceProtocol.java @@ -632,7 +632,6 @@ private void handleSourceNotification(Matcher m, String resp) { } else { logger.warn("Invalid Source Notification response: '{}'", resp); } - } /** @@ -763,5 +762,4 @@ public IdValue(int id, String value) { this.value = value; } } - } diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/system/RioSystemHandler.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/system/RioSystemHandler.java index 6f0d37ed631cf..2100751c443ba 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/system/RioSystemHandler.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/system/RioSystemHandler.java @@ -297,7 +297,6 @@ public void stateChanged(String channelId, State state) { public void setProperty(String propertyName, String propertyValue) { getThing().setProperty(propertyName, propertyValue); } - }); setProtocolHandler(new RioSystemProtocol(session, callback)); @@ -503,7 +502,6 @@ private void childChanged(ThingHandler childHandler, boolean added) { } else if (childHandler instanceof RioControllerHandler) { refreshNamedHandler(gson, RioControllerHandler.class, RioConstants.CHANNEL_SYSCONTROLLERS); } - } /** diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/system/RioSystemProtocol.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/system/RioSystemProtocol.java index 89f63aeb8a35d..b9eb050be54e6 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/system/RioSystemProtocol.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/system/RioSystemProtocol.java @@ -267,7 +267,6 @@ public void responseReceived(String response) { handleFailureNotification(m, response); return; } - } /** diff --git a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/zone/RioZoneProtocol.java b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/zone/RioZoneProtocol.java index 7664986d2f1af..f6250495cb8e1 100644 --- a/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/zone/RioZoneProtocol.java +++ b/bundles/org.openhab.binding.russound/src/main/java/org/openhab/binding/russound/internal/rio/zone/RioZoneProtocol.java @@ -142,7 +142,6 @@ class RioZoneProtocol extends AbstractRioProtocol this.zoneFavorites[0] = new RioFavorite(1); this.zoneFavorites[1] = new RioFavorite(2); - } /** @@ -824,7 +823,6 @@ private void handleZoneNotification(Matcher m, String resp) { } else { logger.warn("Invalid Zone Notification response: '{}'", resp); } - } /** @@ -938,7 +936,6 @@ public void responseReceived(String response) { if (m.matches()) { handleZoneFavoriteNotification(m, response); } - } /** @@ -950,5 +947,4 @@ public void dispose() { favoritesProtocol.removeListener(this); super.dispose(); } - } diff --git a/bundles/org.openhab.binding.russound/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.russound/src/main/resources/ESH-INF/binding/binding.xml index 3958d3d119393..65a814355a24c 100644 --- a/bundles/org.openhab.binding.russound/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.russound/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Russound Binding This is the binding for Russound Whole House Audio systems (MCA and X-Systems). diff --git a/bundles/org.openhab.binding.russound/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.russound/src/main/resources/ESH-INF/thing/thing-types.xml index dd64f2e109bf8..1fe8f191dc2bf 100644 --- a/bundles/org.openhab.binding.russound/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.russound/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -499,7 +499,8 @@ String - JSON Array containing the banks ([{id: 1, name: 'xxx', presets: [{id:1 ,valid:true/false, name='xxx'}, ...], ...]) + JSON Array containing the banks ([{id: 1, name: 'xxx', presets: [{id:1 ,valid:true/false, name='xxx'}, + ...], ...]) diff --git a/bundles/org.openhab.binding.sagercaster/pom.xml b/bundles/org.openhab.binding.sagercaster/pom.xml index af806a0e57854..b2ac472971648 100644 --- a/bundles/org.openhab.binding.sagercaster/pom.xml +++ b/bundles/org.openhab.binding.sagercaster/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.sagercaster diff --git a/bundles/org.openhab.binding.sagercaster/src/main/feature/feature.xml b/bundles/org.openhab.binding.sagercaster/src/main/feature/feature.xml index 71861ff9bd62c..298850a7023d3 100644 --- a/bundles/org.openhab.binding.sagercaster/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.sagercaster/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.sagercaster/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.sagercaster/${project.version} + diff --git a/bundles/org.openhab.binding.sagercaster/src/main/java/org/openhab/binding/sagercaster/internal/handler/SagerCasterHandler.java b/bundles/org.openhab.binding.sagercaster/src/main/java/org/openhab/binding/sagercaster/internal/handler/SagerCasterHandler.java index 2eb3f11e774f7..f03fca497001f 100644 --- a/bundles/org.openhab.binding.sagercaster/src/main/java/org/openhab/binding/sagercaster/internal/handler/SagerCasterHandler.java +++ b/bundles/org.openhab.binding.sagercaster/src/main/java/org/openhab/binding/sagercaster/internal/handler/SagerCasterHandler.java @@ -283,5 +283,4 @@ protected void updateChannelDecimal(String group, String channelId, int value) { updateState(id, new DecimalType(value)); } } - } diff --git a/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/binding/binding.xml index 9a78cd6a4fe52..b3994faac7524 100644 --- a/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,7 @@ - + SagerCaster Binding The Sager Weathercaster is a scientific instrument for accurate prediction of the weather. diff --git a/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/i18n/sagercaster_de.properties b/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/i18n/sagercaster_de.properties new file mode 100644 index 0000000000000..c7981e9fcb8e5 --- /dev/null +++ b/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/i18n/sagercaster_de.properties @@ -0,0 +1,63 @@ +# binding +binding.sagercaster.name = SagerCaster Binding +binding.sagercaster.description = Die SagerCaster-Erweiterung wird zur Erstellung von Wettervorhersagen verwendet. + +# channel types +channel-type.sagercaster.forecast.state.option.0 = Warten Sie etwas lnger auf eine Vorhersage +channel-type.sagercaster.forecast.state.option.A = Gutes Wetter +channel-type.sagercaster.forecast.state.option.B = Gutes Wetter und Erwrmung +channel-type.sagercaster.forecast.state.option.C = Gutes Wetter und Abkhlung +channel-type.sagercaster.forecast.state.option.D = Instabil +channel-type.sagercaster.forecast.state.option.E = Instabil und Erwrmung +channel-type.sagercaster.forecast.state.option.F = Instabil und Abkhlung +channel-type.sagercaster.forecast.state.option.G = Zunehmende Bewlkung oder sehr bewlkt, gefolgt von Niederschlag oder Schauern / Schnee +channel-type.sagercaster.forecast.state.option.G1 = Zunehmende oder sehr trbe Bewlkung, gefolgt von Niederschlag oder Schauern +channel-type.sagercaster.forecast.state.option.G2 = Zunehmende Bewlkung oder sehr bewlkt, gefolgt von Niederschlag oder Schnee +channel-type.sagercaster.forecast.state.option.H = Zunehmende Bewlkung oder sehr bewlkt, gefolgt von Niederschlag oder Schauern und Erwrmung +channel-type.sagercaster.forecast.state.option.J = Regengsse +channel-type.sagercaster.forecast.state.option.K = Regengsse / Schnee und Erwrmung +channel-type.sagercaster.forecast.state.option.K1 = Regengsse und Erwrmung +channel-type.sagercaster.forecast.state.option.K2 = Schnee und Erwrmung +channel-type.sagercaster.forecast.state.option.L = Regengsse / Schnee und Abkhlung +channel-type.sagercaster.forecast.state.option.L1 = Regengsse und Abkhlung +channel-type.sagercaster.forecast.state.option.L2 = Regengsse und Abkhlung +channel-type.sagercaster.forecast.state.option.M = Niederschlag +channel-type.sagercaster.forecast.state.option.N = Niederschlag und Erwrmung +channel-type.sagercaster.forecast.state.option.P = Niederschlag und Abkhlung dann wahrscheinliche Besserung innerhalb von 24 Stunden +channel-type.sagercaster.forecast.state.option.R = Niederschlag oder Schauer / Schnee und Besserung innerhalb von 12 Stunden +channel-type.sagercaster.forecast.state.option.R1 = Niederschlag oder Schauer und Besserung innerhalb von 12 Stunden +channel-type.sagercaster.forecast.state.option.R2 = Niederschlag oder Schnee und Besserung innerhalb von 12 Stunden +channel-type.sagercaster.forecast.state.option.S = Niederschlag oder Schauer / Schnee und Verbesserung innerhalb von 12 Stunden und Abkhlung +channel-type.sagercaster.forecast.state.option.S1 = Niederschlag oder Regengsse und Besserung innerhalb von 12 Stunden und Erfrischung +channel-type.sagercaster.forecast.state.option.S2 = Niederschlag oder Schnee und Verbesserung innerhalb von 12 Stunden und Abkhlung +channel-type.sagercaster.forecast.state.option.T = Niederschlag oder Schauer / Schnee und schnelle Besserung innerhalb von 6 Stunden +channel-type.sagercaster.forecast.state.option.T1 = Niederschlag oder Schauer und schnelle Besserung innerhalb von 6 Stunden +channel-type.sagercaster.forecast.state.option.T2 = Niederschlag oder Schnee und schnelle Besserung innerhalb von 6 Stunden +channel-type.sagercaster.forecast.state.option.U = Niederschlag oder Schauer / Schnee und schnelle Besserung innerhalb von 6 Stunden, dann Abkhlung +channel-type.sagercaster.forecast.state.option.U1 = Niederschlag oder Schauer und schnelle Besserung innerhalb von 6 Stunden, dann Abkhlung +channel-type.sagercaster.forecast.state.option.U2 = Niederschlag oder Schnee und schnelle Besserung innerhalb von 6 Stunden, dann Abkhlung +channel-type.sagercaster.forecast.state.option.W = Niederschlag oder Schauer / Schnee, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung +channel-type.sagercaster.forecast.state.option.W1 = Niederschlag oder Schauer, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung +channel-type.sagercaster.forecast.state.option.W2 = Niederschlag oder Schnee, gefolgt von gutem Wetter innerhalb von 6 Stunden und Abkhlung +channel-type.sagercaster.forecast.state.option.X = Instabil, gefolgt von gutem Wetter +channel-type.sagercaster.forecast.state.option.Y = Instabil, gefolgt von gutem Wetter innerhalb von 6 Stunden und Erfrischung + +channel-type.sagercaster.velocity.state.option.N = Wahrscheinlich steigend +channel-type.sagercaster.velocity.state.option.F = Mig bis frisch +channel-type.sagercaster.velocity.state.option.S = Starke Winde knnen dem Sturm im offenen Raum vorausgehen +channel-type.sagercaster.velocity.state.option.G = Sturm +channel-type.sagercaster.velocity.state.option.W = Gefhrlicher Sturm +channel-type.sagercaster.velocity.state.option.H = Orkan +channel-type.sagercaster.velocity.state.option.D = Abkhlend oder moderat, wenn die aktuellen Winde khl oder stark sind +channel-type.sagercaster.velocity.state.option.U = Keine wesentliche nderung. Tendenz zur Zunahme whrend des Tages, Abnahme am Abend. + +channel-type.sagercaster.wind-evolution.state.option.1 = Stabil +channel-type.sagercaster.wind-evolution.state.option.2 = Sttig +channel-type.sagercaster.wind-evolution.state.option.3 = Variabel + +channel-type.sagercaster.trend.state.option.1 = Schneller Anstieg +channel-type.sagercaster.trend.state.option.2 = Langsamer Anstieg +channel-type.sagercaster.trend.state.option.3 = Stabil +channel-type.sagercaster.trend.state.option.4 = Miger Rckgang +channel-type.sagercaster.trend.state.option.5 = Schneller Rckgang + diff --git a/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/i18n/sagercaster_fr.properties b/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/i18n/sagercaster_fr.properties index 89f78cacb0f5b..95f24796ba411 100644 --- a/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/i18n/sagercaster_fr.properties +++ b/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/i18n/sagercaster_fr.properties @@ -1,5 +1,5 @@ # binding -binding.sagercaster.name = SagerCaster Binding +binding.sagercaster.name = Extension SagerCaster binding.sagercaster.description = L'extension SagerCaster permet d'tablir des prvisions mto. # channel types @@ -10,35 +10,35 @@ channel-type.sagercaster.forecast.state.option.C = Beau-temps et rafraichissemen channel-type.sagercaster.forecast.state.option.D = Instable channel-type.sagercaster.forecast.state.option.E = Instable et rchauffement channel-type.sagercaster.forecast.state.option.F = Instable et rafraichissement -channel-type.sagercaster.forecast.state.option.G = Nbulosit croissante ou trs nuageux suivi de prcititations ou averses/neige +channel-type.sagercaster.forecast.state.option.G = Nbulosit croissante ou trs nuageux suivi de prcititations ou averses / neige channel-type.sagercaster.forecast.state.option.G1 = Nbulosit croissante ou trs nuageux suivi de prcititations ou averses channel-type.sagercaster.forecast.state.option.G2 = Nbulosit croissante ou trs nuageux suivi de prcititations ou neige channel-type.sagercaster.forecast.state.option.H = Nbulosit croissante ou trs nuageux suivi de prcititations ou averses et rchauffement channel-type.sagercaster.forecast.state.option.J = Averses -channel-type.sagercaster.forecast.state.option.K = Averses/neige et rchauffement +channel-type.sagercaster.forecast.state.option.K = Averses / neige et rchauffement channel-type.sagercaster.forecast.state.option.K1 = Averses et rchauffement channel-type.sagercaster.forecast.state.option.K2 = Neige et rchauffement -channel-type.sagercaster.forecast.state.option.L = Averses/neige et rafraichissement +channel-type.sagercaster.forecast.state.option.L = Averses / neige et rafraichissement channel-type.sagercaster.forecast.state.option.L1 = Averses et rafraichissement channel-type.sagercaster.forecast.state.option.L2 = Neige et rafraichissement channel-type.sagercaster.forecast.state.option.M = Prcipitations channel-type.sagercaster.forecast.state.option.N = Prcipitations et rchauffement channel-type.sagercaster.forecast.state.option.P = Prcipitations et rafraichissement puis amlioration probable dans les 24 heures -channel-type.sagercaster.forecast.state.option.R = Prcipitations ou averses/neige et amlioration dans les 12 heures +channel-type.sagercaster.forecast.state.option.R = Prcipitations ou averses / neige et amlioration dans les 12 heures channel-type.sagercaster.forecast.state.option.R1 = Prcipitations ou averses et amlioration dans les 12 heures channel-type.sagercaster.forecast.state.option.R2 = Prcipitations ou neige et amlioration dans les 12 heures -channel-type.sagercaster.forecast.state.option.S = Prcipitations ou averses/neige et amlioration dans les 12 heures et rafraichissement +channel-type.sagercaster.forecast.state.option.S = Prcipitations ou averses / neige et amlioration dans les 12 heures et rafraichissement channel-type.sagercaster.forecast.state.option.S1 = Prcipitations ou averses et amlioration dans les 12 heures et rafraichissement channel-type.sagercaster.forecast.state.option.S2 = Prcipitations ou neige et amlioration dans les 12 heures et rafraichissement -channel-type.sagercaster.forecast.state.option.T = Prcipitations ou averses/neige et amlioration rapide dans les 6 heures +channel-type.sagercaster.forecast.state.option.T = Prcipitations ou averses / neige et amlioration rapide dans les 6 heures channel-type.sagercaster.forecast.state.option.T1 = Prcipitations ou averses et amlioration rapide dans les 6 heures channel-type.sagercaster.forecast.state.option.T2 = Prcipitations ou neige et amlioration rapide dans les 6 heures -channel-type.sagercaster.forecast.state.option.U = Prcipitations ou averses/neige et amlioration rapide dans les 6 heures puis rafraichissement +channel-type.sagercaster.forecast.state.option.U = Prcipitations ou averses / neige et amlioration rapide dans les 6 heures puis rafraichissement channel-type.sagercaster.forecast.state.option.U1 = Prcipitations ou averses et amlioration rapide dans les 6 heures puis rafraichissement channel-type.sagercaster.forecast.state.option.U2 = Prcipitations ou neige et amlioration rapide dans les 6 heures puis rafraichissement -channel-type.sagercaster.forecast.state.option.W = Prcipitations ou averses/neige suivi de beau temps rapide dans les 6 heures et rafraichissement -channel-type.sagercaster.forecast.state.option.W = Prcipitations ou averses suivi de beau temps rapide dans les 6 heures et rafraichissement -channel-type.sagercaster.forecast.state.option.W = Prcipitations ou neige suivi de beau temps rapide dans les 6 heures et rafraichissement +channel-type.sagercaster.forecast.state.option.W = Prcipitations ou averses / neige suivi de beau temps rapide dans les 6 heures et rafraichissement +channel-type.sagercaster.forecast.state.option.W1 = Prcipitations ou averses suivi de beau temps rapide dans les 6 heures et rafraichissement +channel-type.sagercaster.forecast.state.option.W2 = Prcipitations ou neige suivi de beau temps rapide dans les 6 heures et rafraichissement channel-type.sagercaster.forecast.state.option.X = Instable suivi de beau temps channel-type.sagercaster.forecast.state.option.Y = Instable suivi de beau temps rapide dans les 6 heures et rafraichissement diff --git a/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/thing/thing-types.xml index a80d4061eaf30..dcebb004ee516 100644 --- a/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.sagercaster/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,18 +1,21 @@ - + This thing represents a forecast for a given location - - + + - - + + location - + @@ -20,37 +23,38 @@ location Your geo coordinates separated with comma (e.g. "37.8,-122.4"). - + - SagerWeatherCaster needs a minimum representative period of time to produce meaningfull results. Defaults to 6 hours + SagerWeatherCaster needs a minimum representative period of time to produce meaningfull results. + Defaults to 6 hours 6 - + - - + + The channels used to build the forecast results - - - - - - + + + + + + - + Results of the Sager Weathercaster algorithm - - + + @@ -59,19 +63,19 @@ - - + + Pressure Evolution trend over observation delay - + Temperature Evolution trend over observation delay - - + + String @@ -107,10 +111,12 @@ - + - + @@ -118,7 +124,7 @@ - + String @@ -131,11 +137,12 @@ - + - + String @@ -143,7 +150,7 @@ Wind - + Number:Angle @@ -164,7 +171,7 @@ - + String @@ -179,7 +186,7 @@ - + DateTime @@ -187,21 +194,21 @@ Observation time - + Number:Dimensionless Current cloudiness. Clouds - + - + Number - + Current rain quantity Rain - + @@ -210,28 +217,28 @@ Is it currently raining ? Rain - + Number Wind speed using Beaufort Scale Wind - + - + Number:Pressure Sea Level Pressure Pressure - + - + Number:Temperature Current temperature Temperature - + diff --git a/bundles/org.openhab.binding.samsungtv/.classpath b/bundles/org.openhab.binding.samsungtv/.classpath index 5580c803476a0..66499b2691224 100644 --- a/bundles/org.openhab.binding.samsungtv/.classpath +++ b/bundles/org.openhab.binding.samsungtv/.classpath @@ -1,43 +1,43 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.samsungtv/README.md b/bundles/org.openhab.binding.samsungtv/README.md index a1fff5a8fe91e..37b7dda87e587 100644 --- a/bundles/org.openhab.binding.samsungtv/README.md +++ b/bundles/org.openhab.binding.samsungtv/README.md @@ -21,7 +21,9 @@ Tested TV models: | LE40D579 | PARTIAL | Supported channels: `volume`, `mute`, `channel`, `keyCode`, `sourceName`, `programTitle`, `channelName`, `power` | | LE40C650 | PARTIAL | Supported channels: `volume`, `mute`, `channel`, `keyCode`, `brightness`, `contrast`, `colorTemperature`, `power` (only power off, unable to power on) | | UE55LS003 | PARTIAL | Supported channels: `volume`, `mute`, `sourceApp`, `url`, `keyCode`, `power`, `artMode` | +| UE50MU6179 | PARTIAL | Supported channels: `volume`, `mute`, `power`, `keyCode`, `channel`, `sourceApp`, `url` | | UE43MU6199 | PARTIAL | Supported channels: `volume`, `mute`, `power` (at least) | +| UE46F6510SS | PARTIAL | Supported channels: `volume`, `mute`, `channel` (at least) | ## Discovery @@ -43,6 +45,7 @@ E.g. ``` Thing samsungtv:tv:livingroom [ hostName="192.168.1.10", port=55000, macAddress="78:bd:bc:9f:12:34", refreshInterval=1000 ] ``` + Different ports are used in different models. It may be 55000, 8001 or 8002. Try to scan for new Things in Paper UI to find TV easily. @@ -84,3 +87,19 @@ String TV_KeyCode "Key Code" (gLivingRoomTV) Switch TV_Power "Power" (gLivingRoomTV) { channel="samsungtv:tv:livingroom:power" } Switch TV_ArtMode "Art Mode" (gLivingRoomTV) { channel="samsungtv:tv:livingroom:artMode" } ``` + +### Apps + +List of known apps and the respective name that can be passed on to the `sourceApp` channel. +Values are confirmed to work on UE50MU6179. + +| App | Value in sourceApp | Description | +|---------------|--------------------|-----------------------------------| +| ARD Mediathek | `ARD Mediathek` | German public TV broadcasting app | +| Browser | `Internet` | Built-in WWW browser | +| Netflix | `Netflix` | Netflix App | +| Prime Video | `Prime Video` | Prime Video App | +| YouTube | `YouTube` | Prime Video App | +| ZDF Mediathek | `ZDF mediathek` | German public TV broadcasting app | + +As part of discovery, log file `/var/log/openhab2/openhab.log` will contain a debug line with installed apps. diff --git a/bundles/org.openhab.binding.samsungtv/pom.xml b/bundles/org.openhab.binding.samsungtv/pom.xml index 372cce546eb7f..75cdacf1b5df1 100644 --- a/bundles/org.openhab.binding.samsungtv/pom.xml +++ b/bundles/org.openhab.binding.samsungtv/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.samsungtv diff --git a/bundles/org.openhab.binding.samsungtv/src/main/feature/feature.xml b/bundles/org.openhab.binding.samsungtv/src/main/feature/feature.xml index be1d6fcf97d37..5356d10eb82e9 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.samsungtv/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.samsungtv/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.samsungtv/${project.version} + diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/SamsungTvTlsTrustManagerProvider.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/SamsungTvTlsTrustManagerProvider.java index c933cf42c6a31..506629d74543f 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/SamsungTvTlsTrustManagerProvider.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/SamsungTvTlsTrustManagerProvider.java @@ -1,40 +1,40 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.samsungtv.internal; - -import javax.net.ssl.X509ExtendedTrustManager; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.smarthome.io.net.http.TlsTrustManagerProvider; -import org.eclipse.smarthome.io.net.http.TrustAllTrustMananger; -import org.osgi.service.component.annotations.Component; - -/** - * Provides a TrustManager to allow secure websocket connections to any TV (=server) - * - * @author Arjan Mels - Initial Contribution - */ -@Component -@NonNullByDefault -public class SamsungTvTlsTrustManagerProvider implements TlsTrustManagerProvider { - - @Override - public String getHostName() { - return "SmartViewSDK"; - } - - @Override - public X509ExtendedTrustManager getTrustManager() { - return TrustAllTrustMananger.getInstance(); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.samsungtv.internal; + +import javax.net.ssl.X509ExtendedTrustManager; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.io.net.http.TlsTrustManagerProvider; +import org.eclipse.smarthome.io.net.http.TrustAllTrustMananger; +import org.osgi.service.component.annotations.Component; + +/** + * Provides a TrustManager to allow secure websocket connections to any TV (=server) + * + * @author Arjan Mels - Initial Contribution + */ +@Component +@NonNullByDefault +public class SamsungTvTlsTrustManagerProvider implements TlsTrustManagerProvider { + + @Override + public String getHostName() { + return "SmartViewSDK"; + } + + @Override + public X509ExtendedTrustManager getTrustManager() { + return TrustAllTrustMananger.getInstance(); + } +} diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/WakeOnLanUtility.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/WakeOnLanUtility.java index 48e9425709242..af63d6e190cc8 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/WakeOnLanUtility.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/WakeOnLanUtility.java @@ -12,18 +12,19 @@ */ package org.openhab.binding.samsungtv.internal; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.util.Enumeration; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.io.net.exec.ExecUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,38 +32,67 @@ * Class with utility functions to support Wake On Lan (WOL) * * @author Arjan Mels - Initial contribution + * @author Laurent Garnier - Use improvements from the LG webOS binding * */ @NonNullByDefault public class WakeOnLanUtility { - private static final Logger logger = LoggerFactory.getLogger(WakeOnLanUtility.class); + private static final Logger LOGGER = LoggerFactory.getLogger(WakeOnLanUtility.class); + private static final Pattern MAC_REGEX = Pattern.compile("(([0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2})"); + private static final int CMD_TIMEOUT_MS = 1000; + + private static final String COMMAND; + static { + String os = System.getProperty("os.name").toLowerCase(); + LOGGER.debug("os: {}", os); + if ((os.indexOf("win") >= 0)) { + COMMAND = "arp -a %s"; + } else if ((os.indexOf("mac") >= 0)) { + COMMAND = "arp %s"; + } else { // linux + if (checkIfLinuxCommandExists("arp")) { + COMMAND = "arp %s"; + } else if (checkIfLinuxCommandExists("arping")) { // typically OH provided docker image + COMMAND = "arping -r -c 1 -C 1 %s"; + } else { + COMMAND = ""; + } + } + } /** * Get MAC address for host - * uses "arping" tool * * @param hostName Host Name (or IP address) of host to retrieve MAC address for * @return MAC address */ public static @Nullable String getMACAddress(String hostName) { - try { - Process proc = Runtime.getRuntime().exec("arping -r -c 1 -C 1 " + hostName); - proc.waitFor(); - BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); - String macAddress = stdInput.readLine(); - if (macAddress != null) { - logger.info("MAC address of host {} is {}", hostName, macAddress); - return macAddress; - } else { - BufferedReader stdErr = new BufferedReader(new InputStreamReader(proc.getErrorStream())); - String error = stdErr.readLine(); - logger.warn("Cannot get MAC addres of host {}: {}", hostName, error); + if (COMMAND.isEmpty()) { + LOGGER.debug("MAC address detection not possible. No command to identify MAC found."); + return null; + } + + String cmd = String.format(COMMAND, hostName); + String response = ExecUtil.executeCommandLineAndWaitResponse(cmd, CMD_TIMEOUT_MS); + Matcher matcher = MAC_REGEX.matcher(response); + String macAddress = null; + + while (matcher.find()) { + String group = matcher.group(); + + if (group.length() == 17) { + macAddress = group; + break; } - } catch (IOException | InterruptedException e) { - logger.debug("Problem getting MAC address: {}", e.getMessage()); } - return null; + + if (macAddress != null) { + LOGGER.debug("MAC address of host {} is {}", hostName, macAddress); + } else { + LOGGER.debug("Problem executing command {} to retrieve MAC address for {}: {}", cmd, hostName, response); + } + return macAddress; } /** @@ -86,25 +116,23 @@ public static void sendWOLPacket(String macAddress) { continue; } - try { - DatagramPacket packet = new DatagramPacket(bytes, bytes.length, broadcast, 9); - DatagramSocket socket = new DatagramSocket(); + DatagramPacket packet = new DatagramPacket(bytes, bytes.length, broadcast, 9); + try (DatagramSocket socket = new DatagramSocket()) { socket.send(packet); - socket.close(); - logger.trace("Sent WOL packet to {} {}", broadcast, macAddress); + LOGGER.trace("Sent WOL packet to {} {}", broadcast, macAddress); } catch (IOException e) { - logger.warn("Problem sending WOL packet to {} {}", broadcast, macAddress); + LOGGER.warn("Problem sending WOL packet to {} {}", broadcast, macAddress); } } } } catch (IOException e) { - logger.warn("Problem with interface while sending WOL packet to {}", macAddress); + LOGGER.warn("Problem with interface while sending WOL packet to {}", macAddress); } } /** - * Create WOL UDP package: 6 bytes 0xff and then 6 times the 6 byte mac address repeated + * Create WOL UDP package: 6 bytes 0xff and then 16 times the 6 byte mac address repeated * * @param macStr String representation of teh MAC address (either with : or -) * @return byte array with the WOL package @@ -135,4 +163,12 @@ private static byte[] getWOLPackage(String macStr) throws IllegalArgumentExcepti return bytes; } + private static boolean checkIfLinuxCommandExists(String cmd) { + try { + return 0 == Runtime.getRuntime().exec(String.format("which %s", cmd)).waitFor(); + } catch (InterruptedException | IOException e) { + LOGGER.debug("Error trying to check if command {} exists: {}", cmd, e.getMessage()); + } + return false; + } } diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/handler/SamsungTvHandler.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/handler/SamsungTvHandler.java index ffe2cf848ab53..def7c02c692d4 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/handler/SamsungTvHandler.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/handler/SamsungTvHandler.java @@ -19,10 +19,9 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.DiscoveryListener; @@ -39,6 +38,7 @@ import org.eclipse.smarthome.core.thing.ThingUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.io.net.http.WebSocketFactory; import org.eclipse.smarthome.io.transport.upnp.UpnpIOService; @@ -71,10 +71,12 @@ public class SamsungTvHandler extends BaseThingHandler implements DiscoveryListe private final Logger logger = LoggerFactory.getLogger(SamsungTvHandler.class); - private UpnpIOService upnpIOService; - private DiscoveryServiceRegistry discoveryServiceRegistry; - private UpnpService upnpService; - private WebSocketFactory webSocketFactory; + private final UpnpIOService upnpIOService; + private final DiscoveryServiceRegistry discoveryServiceRegistry; + private final UpnpService upnpService; + private final WebSocketFactory webSocketFactory; + + private SamsungTvConfiguration configuration; private @Nullable ThingUID upnpThingUID = null; @@ -87,6 +89,8 @@ public class SamsungTvHandler extends BaseThingHandler implements DiscoveryListe /* Store if art mode is supported to be able to skip switching power state to ON during initialization */ boolean artModeIsSupported = false; + private @Nullable ScheduledFuture pollingJob; + public SamsungTvHandler(Thing thing, UpnpIOService upnpIOService, DiscoveryServiceRegistry discoveryServiceRegistry, UpnpService upnpService, WebSocketFactory webSocketFactory) { super(thing); @@ -97,6 +101,7 @@ public SamsungTvHandler(Thing thing, UpnpIOService upnpIOService, DiscoveryServi this.upnpService = upnpService; this.discoveryServiceRegistry = discoveryServiceRegistry; this.webSocketFactory = webSocketFactory; + this.configuration = getConfigAs(SamsungTvConfiguration.class); } @Override @@ -148,15 +153,28 @@ public void initialize() { logger.debug("Initializing Samsung TV handler for uid '{}'", getThing().getUID()); + configuration = getConfigAs(SamsungTvConfiguration.class); + discoveryServiceRegistry.addDiscoveryListener(this); checkAndCreateServices(); + + logger.debug("Start refresh task, interval={}", configuration.refreshInterval); + pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, configuration.refreshInterval, + TimeUnit.MILLISECONDS); } @Override public void dispose() { logger.debug("Disposing SamsungTvHandler"); + if (pollingJob != null) { + if (!pollingJob.isCancelled()) { + pollingJob.cancel(true); + } + pollingJob = null; + } + discoveryServiceRegistry.removeDiscoveryListener(this); shutdown(); putOffline(); @@ -187,6 +205,21 @@ private synchronized void putOffline() { updateState(SOURCE_APP, new StringType("")); } + private void poll() { + for (SamsungTvService service : services) { + for (String channel : service.getSupportedChannelNames()) { + if (isLinked(channel)) { + // Avoid redundant REFRESH commands when 2 channels are linked to the same UPnP action request + if ((channel.equals(SOURCE_ID) && isLinked(SOURCE_NAME)) + || (channel.equals(CHANNEL_NAME) && isLinked(PROGRAM_TITLE))) { + continue; + } + service.handleCommand(channel, RefreshType.REFRESH); + } + } + } + } + @Override public synchronized void valueReceived(String variable, State value) { logger.debug("Received value '{}':'{}' for thing '{}'", variable, value, this.getThing().getUID()); @@ -200,7 +233,7 @@ public synchronized void valueReceived(String variable, State value) { } @Override - public void reportError(@NonNull ThingStatusDetail statusDetail, @Nullable String message, @Nullable Throwable e) { + public void reportError(ThingStatusDetail statusDetail, @Nullable String message, @Nullable Throwable e) { logger.debug("Error was reported: {}", message, e); updateStatus(ThingStatus.OFFLINE, statusDetail, message); } @@ -221,7 +254,6 @@ private void checkAndCreateServices() { } private synchronized void createService(RemoteDevice device) { - SamsungTvConfiguration configuration = getConfigAs(SamsungTvConfiguration.class); if (configuration.hostName != null && configuration.hostName.equals(device.getIdentity().getDescriptorURL().getHost())) { String modelName = device.getDetails().getModelDetails().getModelName(); @@ -232,7 +264,7 @@ private synchronized void createService(RemoteDevice device) { if (existingService == null || !existingService.isUpnp()) { SamsungTvService newService = ServiceFactory.createService(type, upnpIOService, udn, - configuration.refreshInterval, configuration.hostName, configuration.port); + configuration.hostName, configuration.port); if (newService != null) { if (existingService != null) { @@ -272,7 +304,6 @@ private synchronized void checkCreateManualConnection() { RemoteControllerService service = (RemoteControllerService) findServiceInstance( RemoteControllerService.SERVICE_NAME); if (service == null) { - SamsungTvConfiguration configuration = getConfigAs(SamsungTvConfiguration.class); service = RemoteControllerService.createNonUpnpService(configuration.hostName, configuration.port); startService(service); } else { @@ -300,25 +331,23 @@ private synchronized void stopService(SamsungTvService service) { @Override public void thingDiscovered(DiscoveryService source, DiscoveryResult result) { - SamsungTvConfiguration configuration = getConfigAs(SamsungTvConfiguration.class); - if (configuration.hostName != null && configuration.hostName.equals(result.getProperties().get(SamsungTvConfiguration.HOST_NAME))) { logger.debug("thingDiscovered: {}, {}", result.getProperties().get(SamsungTvConfiguration.HOST_NAME), result); /* Check if configuration should be updated */ - if (StringUtils.isEmpty(configuration.macAddress)) { + if (configuration.macAddress == null || configuration.macAddress.trim().isEmpty()) { String macAddress = WakeOnLanUtility.getMACAddress(configuration.hostName); if (macAddress != null) { - getConfig().put(SamsungTvConfiguration.MAC_ADDRESS, macAddress); + putConfig(SamsungTvConfiguration.MAC_ADDRESS, macAddress); logger.debug("thingDiscovered, macAddress: {}", macAddress); } } if (SamsungTvConfiguration.PROTOCOL_NONE.equals(configuration.protocol)) { Map properties = RemoteControllerService.discover(configuration.hostName); for (Map.Entry property : properties.entrySet()) { - getConfig().put(property.getKey(), property.getValue()); + putConfig(property.getKey(), property.getValue()); logger.debug("thingDiscovered, {}: {}", property.getKey(), property.getValue()); } } @@ -356,8 +385,6 @@ public void thingRemoved(DiscoveryService source, ThingUID thingUID) { * @param command Command to resend */ private void sendWOLandResendCommand(String channel, Command command) { - SamsungTvConfiguration configuration = getConfigAs(SamsungTvConfiguration.class); - if (configuration.macAddress == null || configuration.macAddress.isEmpty()) { logger.warn("Cannot send WOL packet to {} MAC address unknown", configuration.hostName); return; @@ -399,7 +426,6 @@ public void run() { logger.info("Service NOT found after {} attempts", count); } } - }, 1000, TimeUnit.MILLISECONDS); } } @@ -407,6 +433,7 @@ public void run() { @Override public void putConfig(@Nullable String key, @Nullable Object value) { getConfig().put(key, value); + configuration = getConfigAs(SamsungTvConfiguration.class); } @Override diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteController.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteController.java index 645125708de8b..da105524ce80b 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteController.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteController.java @@ -46,5 +46,4 @@ public RemoteController(String host, int port, @Nullable String appName, @Nullab @Override public abstract void close() throws RemoteControllerException; - } diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerException.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerException.java index 61a6b6400ec17..bbe5607e36131 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerException.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerException.java @@ -35,5 +35,4 @@ public RemoteControllerException(String message, Throwable cause) { public RemoteControllerException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerWebSocket.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerWebSocket.java index 3646f62afa78b..f9e9f8be6a9f2 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerWebSocket.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/RemoteControllerWebSocket.java @@ -379,5 +379,4 @@ public void lifeCycleStopped(@Nullable LifeCycle arg0) { public void lifeCycleStopping(@Nullable LifeCycle arg0) { logger.trace("WebSocketClient stopping"); } - } diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketArt.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketArt.java index 6b4a4a02c6120..caa35debe7a78 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketArt.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketArt.java @@ -155,7 +155,6 @@ class Data { String method = "ms.channel.emit"; Params params = new Params(); - } void getArtmodeStatus() { diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketBase.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketBase.java index 6a9f436f82419..726fa73a17725 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketBase.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketBase.java @@ -117,5 +117,4 @@ void sendCommand(String cmd) { public void onWebSocketText(@Nullable String str) { logger.trace("{}: onWebSocketText: {}", this.getClass().getSimpleName(), str); } - } diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketRemote.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketRemote.java index 297f70e1c6e39..ea3a8d30fa8d0 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketRemote.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketRemote.java @@ -157,7 +157,6 @@ static class Params { String method = "ms.channel.emit"; Params params = new Params(); - } void getApps() { @@ -188,7 +187,6 @@ static class Data { String event = "ed.apps.launch"; String to = "host"; Data data = new Data(); - } String method = "ms.channel.emit"; @@ -225,5 +223,4 @@ static class Params { void sendKeyData(boolean press, String key) { sendCommand(remoteControllerWebSocket.gson.toJson(new JSONRemoteControl(press, key))); } - } diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketV2.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketV2.java index 2bea304f412fd..b919f2ccc166c 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketV2.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/protocol/WebSocketV2.java @@ -12,7 +12,6 @@ */ package org.openhab.binding.samsungtv.internal.protocol; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.slf4j.Logger; @@ -109,14 +108,17 @@ public void onWebSocketText(@Nullable String msgarg) { } private void handleResult(JSONMessage jsonMsg) { - if (StringUtils.isBlank(remoteControllerWebSocket.currentSourceApp) && "true".equals(jsonMsg.result.visible)) { + if ((remoteControllerWebSocket.currentSourceApp == null + || remoteControllerWebSocket.currentSourceApp.trim().isEmpty()) + && "true".equals(jsonMsg.result.visible)) { logger.debug("Running app: {} = {}", jsonMsg.result.id, jsonMsg.result.name); remoteControllerWebSocket.currentSourceApp = jsonMsg.result.name; remoteControllerWebSocket.callback.currentAppUpdated(remoteControllerWebSocket.currentSourceApp); } if (remoteControllerWebSocket.lastApp != null && remoteControllerWebSocket.lastApp.equals(jsonMsg.result.id)) { - if (StringUtils.isBlank(remoteControllerWebSocket.currentSourceApp)) { + if (remoteControllerWebSocket.currentSourceApp == null + || remoteControllerWebSocket.currentSourceApp.trim().isEmpty()) { remoteControllerWebSocket.callback.currentAppUpdated(""); } remoteControllerWebSocket.lastApp = null; diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/MainTVServerService.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/MainTVServerService.java index 4a90a19988b5a..d5ad695855254 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/MainTVServerService.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/MainTVServerService.java @@ -21,17 +21,13 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.UnDefType; import org.eclipse.smarthome.io.transport.upnp.UpnpIOParticipant; import org.eclipse.smarthome.io.transport.upnp.UpnpIOService; @@ -53,36 +49,30 @@ public class MainTVServerService implements UpnpIOParticipant, SamsungTvService { public static final String SERVICE_NAME = "MainTVServer2"; - private static final List SUPPORTEDCOMMANDS = Arrays.asList(SOURCE_NAME, BROWSER_URL, STOP_BROWSER); + private static final List SUPPORTED_CHANNELS = Arrays.asList(CHANNEL_NAME, CHANNEL, SOURCE_NAME, SOURCE_ID, + PROGRAM_TITLE, BROWSER_URL, STOP_BROWSER); private final Logger logger = LoggerFactory.getLogger(MainTVServerService.class); - private UpnpIOService service; + private final UpnpIOService service; - private ScheduledExecutorService scheduler; - private @Nullable ScheduledFuture pollingJob; - - private String udn; - private int pollingInterval; + private final String udn; private Map stateMap = Collections.synchronizedMap(new HashMap<>()); private Set listeners = new CopyOnWriteArraySet<>(); - public MainTVServerService(UpnpIOService upnpIOService, String udn, int pollingInterval) { - logger.debug("Creating a Samsung TV MainTVServer service"); - - service = upnpIOService; + private boolean started; + public MainTVServerService(UpnpIOService upnpIOService, String udn) { + logger.debug("Creating a Samsung TV MainTVServer service"); + this.service = upnpIOService; this.udn = udn; - this.pollingInterval = pollingInterval; - - scheduler = Executors.newScheduledThreadPool(1); } @Override public List getSupportedChannelNames() { - return SUPPORTEDCOMMANDS; + return SUPPORTED_CHANNELS; } @Override @@ -97,18 +87,14 @@ public void removeEventListener(EventListener listener) { @Override public void start() { - if (pollingJob == null || pollingJob.isCancelled()) { - logger.debug("Start refresh task, interval={}", pollingInterval); - pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 0, pollingInterval, TimeUnit.MILLISECONDS); - } + service.registerParticipant(this); + started = true; } @Override public void stop() { - if (pollingJob != null && !pollingJob.isCancelled()) { - pollingJob.cancel(true); - pollingJob = null; - } + service.unregisterParticipant(this); + started = false; } @Override @@ -121,19 +107,38 @@ public boolean isUpnp() { return true; } - private Runnable pollingRunnable = () -> { - if (isRegistered()) { - updateResourceState("MainTVAgent2", "GetCurrentMainTVChannel", null); - updateResourceState("MainTVAgent2", "GetCurrentExternalSource", null); - updateResourceState("MainTVAgent2", "GetCurrentContentRecognition", null); - updateResourceState("MainTVAgent2", "GetCurrentBrowserURL", null); - } - }; - @Override public void handleCommand(String channel, Command command) { logger.debug("Received channel: {}, command: {}", channel, command); + if (!started) { + return; + } + + if (command == RefreshType.REFRESH) { + if (isRegistered()) { + switch (channel) { + case CHANNEL: + updateResourceState("MainTVAgent2", "GetCurrentMainTVChannel", null); + break; + case SOURCE_NAME: + case SOURCE_ID: + updateResourceState("MainTVAgent2", "GetCurrentExternalSource", null); + break; + case PROGRAM_TITLE: + case CHANNEL_NAME: + updateResourceState("MainTVAgent2", "GetCurrentContentRecognition", null); + break; + case BROWSER_URL: + updateResourceState("MainTVAgent2", "GetCurrentBrowserURL", null); + break; + default: + break; + } + } + return; + } + switch (channel) { case SOURCE_NAME: setSourceName(command); @@ -326,10 +331,4 @@ private Map parseSourceList(String xml) { public void onStatusChanged(boolean status) { logger.debug("onStatusChanged: status={}", status); } - - private void reportError(String message, Throwable e) { - for (EventListener listener : listeners) { - listener.reportError(ThingStatusDetail.COMMUNICATION_ERROR, message, e); - } - } } diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/MediaRendererService.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/MediaRendererService.java index 8115d0c015f31..e5e97997d0434 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/MediaRendererService.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/MediaRendererService.java @@ -21,18 +21,14 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; import org.eclipse.smarthome.io.transport.upnp.UpnpIOParticipant; @@ -52,41 +48,30 @@ public class MediaRendererService implements UpnpIOParticipant, SamsungTvService { public static final String SERVICE_NAME = "MediaRenderer"; - private final List supportedCommands = Arrays.asList(VOLUME, MUTE, BRIGHTNESS, CONTRAST, SHARPNESS, + private static final List SUPPORTED_CHANNELS = Arrays.asList(VOLUME, MUTE, BRIGHTNESS, CONTRAST, SHARPNESS, COLOR_TEMPERATURE); private final Logger logger = LoggerFactory.getLogger(MediaRendererService.class); - private @Nullable UpnpIOService service; + private final UpnpIOService service; - private ScheduledExecutorService scheduler; - private @Nullable ScheduledFuture pollingJob; - - private String udn; - private int pollingInterval; + private final String udn; private Map stateMap = Collections.synchronizedMap(new HashMap<>()); private Set listeners = new CopyOnWriteArraySet<>(); - public MediaRendererService(@Nullable UpnpIOService upnpIOService, String udn, int pollingInterval) { - logger.debug("Creating a Samsung TV MediaRenderer service"); - - if (upnpIOService != null) { - service = upnpIOService; - } else { - logger.debug("upnpIOService not set."); - } + private boolean started; + public MediaRendererService(UpnpIOService upnpIOService, String udn) { + logger.debug("Creating a Samsung TV MediaRenderer service"); + this.service = upnpIOService; this.udn = udn; - this.pollingInterval = pollingInterval; - - scheduler = Executors.newScheduledThreadPool(1); } @Override public List getSupportedChannelNames() { - return supportedCommands; + return SUPPORTED_CHANNELS; } @Override @@ -101,18 +86,14 @@ public void removeEventListener(EventListener listener) { @Override public void start() { - if (pollingJob == null || pollingJob.isCancelled()) { - logger.debug("Start refresh task, interval={}", pollingInterval); - pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 0, pollingInterval, TimeUnit.MILLISECONDS); - } + service.registerParticipant(this); + started = true; } @Override public void stop() { - if (pollingJob != null && !pollingJob.isCancelled()) { - pollingJob.cancel(true); - pollingJob = null; - } + service.unregisterParticipant(this); + started = false; } @Override @@ -125,24 +106,48 @@ public boolean isUpnp() { return true; } - private Runnable pollingRunnable = () -> { - if (isRegistered()) { - updateResourceState("RenderingControl", "GetVolume", - SamsungTvUtils.buildHashMap("InstanceID", "0", "Channel", "Master")); - updateResourceState("RenderingControl", "GetMute", - SamsungTvUtils.buildHashMap("InstanceID", "0", "Channel", "Master")); - updateResourceState("RenderingControl", "GetBrightness", SamsungTvUtils.buildHashMap("InstanceID", "0")); - updateResourceState("RenderingControl", "GetContrast", SamsungTvUtils.buildHashMap("InstanceID", "0")); - updateResourceState("RenderingControl", "GetSharpness", SamsungTvUtils.buildHashMap("InstanceID", "0")); - updateResourceState("RenderingControl", "GetColorTemperature", - SamsungTvUtils.buildHashMap("InstanceID", "0")); - } - }; - @Override public void handleCommand(String channel, Command command) { logger.debug("Received channel: {}, command: {}", channel, command); + if (!started) { + return; + } + + if (command == RefreshType.REFRESH) { + if (isRegistered()) { + switch (channel) { + case VOLUME: + updateResourceState("RenderingControl", "GetVolume", + SamsungTvUtils.buildHashMap("InstanceID", "0", "Channel", "Master")); + break; + case MUTE: + updateResourceState("RenderingControl", "GetMute", + SamsungTvUtils.buildHashMap("InstanceID", "0", "Channel", "Master")); + break; + case BRIGHTNESS: + updateResourceState("RenderingControl", "GetBrightness", + SamsungTvUtils.buildHashMap("InstanceID", "0")); + break; + case CONTRAST: + updateResourceState("RenderingControl", "GetContrast", + SamsungTvUtils.buildHashMap("InstanceID", "0")); + break; + case SHARPNESS: + updateResourceState("RenderingControl", "GetSharpness", + SamsungTvUtils.buildHashMap("InstanceID", "0")); + break; + case COLOR_TEMPERATURE: + updateResourceState("RenderingControl", "GetColorTemperature", + SamsungTvUtils.buildHashMap("InstanceID", "0")); + break; + default: + break; + } + } + return; + } + switch (channel) { case VOLUME: setVolume(command); @@ -269,7 +274,6 @@ private void setMute(Command command) { updateResourceState("RenderingControl", "GetMute", SamsungTvUtils.buildHashMap("InstanceID", "0", "Channel", "Master")); - } private void setBrightness(Command command) { @@ -338,12 +342,6 @@ private void setColorTemperature(Command command) { @Override public void onStatusChanged(boolean status) { - // do nothing - } - - private void reportError(String message, Throwable e) { - for (EventListener listener : listeners) { - listener.reportError(ThingStatusDetail.COMMUNICATION_ERROR, message, e); - } + logger.debug("onStatusChanged: status={}", status); } } diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/RemoteControllerService.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/RemoteControllerService.java index 55e9cb0263473..2bed6a00178ba 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/RemoteControllerService.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/RemoteControllerService.java @@ -34,6 +34,7 @@ import org.eclipse.smarthome.core.library.types.UpDownType; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.io.net.http.WebSocketFactory; import org.openhab.binding.samsungtv.internal.config.SamsungTvConfiguration; import org.openhab.binding.samsungtv.internal.protocol.KeyCode; @@ -254,6 +255,9 @@ public boolean isUpnp() { @Override public void handleCommand(String channel, Command command) { logger.debug("Received channel: {}, command: {}", channel, command); + if (command == RefreshType.REFRESH) { + return; + } if (remoteController == null) { return; @@ -411,7 +415,6 @@ private void sendKeyCode(KeyCode key) { } catch (RemoteControllerException e) { reportError(String.format("Could not send command to device on %s:%d", host, port), e); } - } private void sendKeyCodePress(KeyCode key) { @@ -422,7 +425,6 @@ private void sendKeyCodePress(KeyCode key) { } catch (RemoteControllerException e) { reportError(String.format("Could not send command to device on %s:%d", host, port), e); } - } /** @@ -502,7 +504,6 @@ public void putConfig(String key, Object value) { for (EventListener listener : listeners) { listener.putConfig(key, value); } - } @Override diff --git a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/ServiceFactory.java b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/ServiceFactory.java index 64e727ae7c036..a46c79705af99 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/ServiceFactory.java +++ b/bundles/org.openhab.binding.samsungtv/src/main/java/org/openhab/binding/samsungtv/internal/service/ServiceFactory.java @@ -46,21 +46,20 @@ public class ServiceFactory { * @param type * @param upnpIOService * @param udn - * @param pollingInterval * @param host * @param port * @return */ public static @Nullable SamsungTvService createService(String type, UpnpIOService upnpIOService, String udn, - int pollingInterval, String host, int port) { + String host, int port) { SamsungTvService service = null; switch (type) { case MainTVServerService.SERVICE_NAME: - service = new MainTVServerService(upnpIOService, udn, pollingInterval); + service = new MainTVServerService(upnpIOService, udn); break; case MediaRendererService.SERVICE_NAME: - service = new MediaRendererService(upnpIOService, udn, pollingInterval); + service = new MediaRendererService(upnpIOService, udn); break; // will not be created automatically case RemoteControllerService.SERVICE_NAME: diff --git a/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/binding/binding.xml index fef0a88e2f900..99bf292294f67 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/binding/binding.xml @@ -4,7 +4,8 @@ xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd"> Samsung TV Binding - This is the binding for Samsung TV. Binding should support all Samsung TV C (2010), D (2011) and E (2012) models + This is the binding for Samsung TV. Binding should support all Samsung TV C (2010), D (2011) and E (2012) + models Pauli Anttila diff --git a/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/config/config.xml index ae3387065b182..d122cd5fb1839 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/config/config.xml @@ -17,7 +17,7 @@ - MAC Address of the Samsung TV. + MAC Address of the Samsung TV. diff --git a/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/thing/channel-types.xml b/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/thing/channel-types.xml index b62371f2bf2de..08b8b4b567538 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/thing/channel-types.xml +++ b/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/thing/channel-types.xml @@ -41,7 +41,7 @@ Color temperature of the TV picture. Minimum value is 0 and maximum 4. - + @@ -54,7 +54,7 @@ Number Id of the current source. - + @@ -67,14 +67,14 @@ String Program title of the current channel. - + String Name of the current TV channel. - + diff --git a/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/thing/thing-types.xml index b7b0b96fc3652..34ced773ef24e 100644 --- a/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.samsungtv/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,26 +9,26 @@ Allows to control Samsung TV - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.satel/README.md b/bundles/org.openhab.binding.satel/README.md index e9f09ea7ae5d5..2282d4b3e4e84 100644 --- a/bundles/org.openhab.binding.satel/README.md +++ b/bundles/org.openhab.binding.satel/README.md @@ -41,13 +41,14 @@ You can configure the following settings for this bridge: | Name | Required | Description | |---------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| host | yes | Host name or IP addres of ETHM-1 module | -| port | no | TCP port for the integration protocol, defaults to 7094 | -| timeout | no | Timeout value in milliseconds for connect, read and write operations, defaults to 5000 (5secs) | +| host | yes | Host name or IP addres of ETHM-1 module. | +| port | no | TCP port for the integration protocol, defaults to 7094. | +| timeout | no | Timeout value in milliseconds for connect, read and write operations, defaults to 5000 (5secs). | | refresh | no | Polling interval in milliseconds, defaults to 5000 (5secs). As of version 2.03 ETHM-1 Plus firmware the module disconnects after 25 seconds of inactivity. Setting this parameter to value greater than 25000 will cause inability to correctly communicate with the module. | -| userCode | no | Security code of the user in behalf of all operations will be executed. If empty, only read operations are allowed | -| encryptionKey | no | Encryption key used to encrypt data sent and received, if empty communication is not encrypted | -| encoding | no | Encoding for all the texts received from the module | +| userCode | no | Security code of the user in behalf of all operations will be executed. If empty, only read operations are allowed. | +| encryptionKey | no | Encryption key used to encrypt data sent and received. If empty, communication is not encrypted. | +| encoding | no | Encoding for all the texts received from the module. | +| extCommands | no | Check this option to enable extended commands, supported by ETHM-1 Plus and newer versions of ETHM-1. Enabled by default, turn off in case of communication timeouts. | Example: @@ -63,13 +64,14 @@ In case you have troubles connecting to the system using this module, please mak You can configure the following settings for this bridge: -| Name | Required | Description | -|----------|----------|--------------------------------------------------------------------------------------------------------------------| -| port | yes | Serial port connected to the module | -| timeout | no | Timeout value in milliseconds for connect, read and write operations, defaults to 5000 (5secs) | -| refresh | no | Polling interval in milliseconds, defaults to 5000 (5secs) | -| userCode | no | Security code of the user in behalf of all operations will be executed. If empty, only read operations are allowed | -| encoding | no | Encoding for all the texts received from the module | +| Name | Required | Description | +|-------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------| +| port | yes | Serial port connected to the module. | +| timeout | no | Timeout value in milliseconds for connect, read and write operations, defaults to 5000 (5secs). | +| refresh | no | Polling interval in milliseconds, defaults to 5000 (5secs). | +| userCode | no | Security code of the user in behalf of all operations will be executed. If empty, only read operations are allowed. | +| encoding | no | Encoding for all the texts received from the module. | +| extCommands | no | Check this option to enable extended commands, supported by version 2.xx of INT-RS. Enabled by default, turn off in case of communication timeouts. | Example: diff --git a/bundles/org.openhab.binding.satel/pom.xml b/bundles/org.openhab.binding.satel/pom.xml index 25368e465f0ef..a20f9832c482e 100644 --- a/bundles/org.openhab.binding.satel/pom.xml +++ b/bundles/org.openhab.binding.satel/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.satel diff --git a/bundles/org.openhab.binding.satel/src/main/feature/feature.xml b/bundles/org.openhab.binding.satel/src/main/feature/feature.xml index b731d17b82644..a50dbce8686b8 100644 --- a/bundles/org.openhab.binding.satel/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.satel/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.satel/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.satel/${project.version} + diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/action/SatelEventLogActions.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/action/SatelEventLogActions.java index 63077c95de61f..68d37af94cf05 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/action/SatelEventLogActions.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/action/SatelEventLogActions.java @@ -78,5 +78,4 @@ public static Map readEvent(@Nullable ThingActions actions, @Nul throw new IllegalArgumentException("Instance is not a SatelEventLogActions class."); } } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/SatelBindingConstants.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/SatelBindingConstants.java index b2d53d498e0aa..a9a2ab4ecf9ba 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/SatelBindingConstants.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/SatelBindingConstants.java @@ -74,5 +74,4 @@ public class SatelBindingConstants { public static final String CHANNEL_DESCRIPTION = "description"; public static final String CHANNEL_DETAILS = "details"; public static final String CHANNEL_TEMPERATURE = "temperature"; - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ClearTroublesCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ClearTroublesCommand.java index 0f33615799702..58ad69535553e 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ClearTroublesCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ClearTroublesCommand.java @@ -32,5 +32,4 @@ public class ClearTroublesCommand extends ControlCommand { public ClearTroublesCommand(String userCode) { super(COMMAND_CODE, userCodeToBytes(userCode)); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ControlCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ControlCommand.java index 45087bbd71896..54beef732f61d 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ControlCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ControlCommand.java @@ -28,7 +28,7 @@ public abstract class ControlCommand extends SatelCommandBase { * Creates new command class instance. * * @param commandCode command code - * @param payload command bytes + * @param payload command bytes */ public ControlCommand(byte commandCode, byte[] payload) { super(commandCode, payload); @@ -68,5 +68,4 @@ protected static byte[] userCodeToBytes(String userCode) { return bytes; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ControlObjectCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ControlObjectCommand.java index 7b9ce608a6eff..bdb1a15969a16 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ControlObjectCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ControlObjectCommand.java @@ -41,9 +41,9 @@ public class ControlObjectCommand extends ControlCommand { * Creates new command class instance for specified type of control. * * @param controlType type of controlled objects - * @param objects bits that represents objects to control - * @param userCode code of the user on behalf the control is made - * @param scheduler scheduler object for scheduling refreshes + * @param objects bits that represents objects to control + * @param userCode code of the user on behalf the control is made + * @param scheduler scheduler object for scheduling refreshes */ public ControlObjectCommand(ControlType controlType, byte[] objects, String userCode, ScheduledExecutorService scheduler) { @@ -62,5 +62,4 @@ protected void handleResponseInternal(final EventDispatcher eventDispatcher) { TimeUnit.MILLISECONDS); } } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraStateCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraStateCommand.java index d1fe094b493b0..9725a8404388e 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraStateCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraStateCommand.java @@ -40,7 +40,7 @@ public class IntegraStateCommand extends SatelCommandBase { * Constructs new command instance for specified type of state. * * @param stateType type of state - * @param extended if true command will be sent as extended (256 zones or outputs) + * @param extended if true command will be sent as extended (256 zones or outputs) */ public IntegraStateCommand(StateType stateType, boolean extended) { super(stateType.getRefreshCommand(), extended); @@ -70,5 +70,4 @@ protected void handleResponseInternal(final EventDispatcher eventDispatcher) { eventDispatcher.dispatchEvent( new IntegraStateEvent(getResponse().getCommand(), getResponse().getPayload(), isExtended())); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraStatusCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraStatusCommand.java index ba711713e630e..595fdda8dfe41 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraStatusCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraStatusCommand.java @@ -12,7 +12,9 @@ */ package org.openhab.binding.satel.internal.command; +import java.time.DateTimeException; import java.time.LocalDateTime; +import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.satel.internal.event.EventDispatcher; @@ -43,11 +45,17 @@ public IntegraStatusCommand() { /** * @return date and time */ - public LocalDateTime getIntegraTime() { + public Optional getIntegraTime() { // parse current date and time - final byte[] payload = getResponse().getPayload(); - return LocalDateTime.of(bcdToInt(payload, 0, 2), bcdToInt(payload, 2, 1), bcdToInt(payload, 3, 1), - bcdToInt(payload, 4, 1), bcdToInt(payload, 5, 1), bcdToInt(payload, 6, 1)); + try { + final byte[] payload = getResponse().getPayload(); + return Optional + .of(LocalDateTime.of(bcdToInt(payload, 0, 2), bcdToInt(payload, 2, 1), bcdToInt(payload, 3, 1), + bcdToInt(payload, 4, 1), bcdToInt(payload, 5, 1), bcdToInt(payload, 6, 1))); + } catch (DateTimeException e) { + logger.debug("Invalid date/time set in the system", e); + return Optional.empty(); + } } /** @@ -78,5 +86,4 @@ protected void handleResponseInternal(final EventDispatcher eventDispatcher) { // dispatch version event eventDispatcher.dispatchEvent(new IntegraStatusEvent(getIntegraTime(), getStatusByte1(), getStatusByte2())); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraVersionCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraVersionCommand.java index 7741526e2cb48..59d507a58876a 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraVersionCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/IntegraVersionCommand.java @@ -82,5 +82,4 @@ protected void handleResponseInternal(final EventDispatcher eventDispatcher) { eventDispatcher .dispatchEvent(new IntegraVersionEvent(getType(), getVersion(), getLanguage(), areSettingsInFlash())); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ModuleVersionCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ModuleVersionCommand.java index 18bc65170d301..238383adff4e2 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ModuleVersionCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ModuleVersionCommand.java @@ -67,5 +67,4 @@ protected void handleResponseInternal(final EventDispatcher eventDispatcher) { // dispatch version event eventDispatcher.dispatchEvent(new ModuleVersionEvent(getVersion(), hasExtPayloadSupport())); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/NewStatesCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/NewStatesCommand.java index 0b5d40318abe9..bb35ee7dd0eda 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/NewStatesCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/NewStatesCommand.java @@ -55,5 +55,4 @@ protected void handleResponseInternal(final EventDispatcher eventDispatcher) { // dispatch event eventDispatcher.dispatchEvent(new NewStatesEvent(getResponse().getPayload())); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadDeviceInfoCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadDeviceInfoCommand.java index ca33d8345a5ea..ce14eca7f6895 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadDeviceInfoCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadDeviceInfoCommand.java @@ -76,7 +76,7 @@ boolean hasAdditionalInfo() { * Creates new command class instance to read description for given * parameters. * - * @param deviceType type of the device + * @param deviceType type of the device * @param deviceNumber device number */ public ReadDeviceInfoCommand(DeviceType deviceType, int deviceNumber) { @@ -153,5 +153,4 @@ protected boolean isResponseValid(SatelMessage response) { } return true; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventCommand.java index c7236efc848f6..df601d3624326 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventCommand.java @@ -218,5 +218,4 @@ protected boolean isResponseValid(SatelMessage response) { } return true; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventDescCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventDescCommand.java index a02db088dfcfc..03c364ee3193c 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventDescCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadEventDescCommand.java @@ -34,8 +34,8 @@ public class ReadEventDescCommand extends SatelCommandBase { /** * Creates new command class instance to read description for given parameters. * - * @param eventCode event code - * @param restore true if this is restoration + * @param eventCode event code + * @param restore true if this is restoration * @param longDescription true for long description, false for short one */ public ReadEventDescCommand(int eventCode, boolean restore, boolean longDescription) { @@ -99,5 +99,4 @@ protected boolean isResponseValid(SatelMessage response) { } return true; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadZoneTemperature.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadZoneTemperature.java index e4cd6e2b2263d..ddbfc681882a1 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadZoneTemperature.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/ReadZoneTemperature.java @@ -67,5 +67,4 @@ protected void handleResponseInternal(final EventDispatcher eventDispatcher) { int zoneNbr = getResponse().getPayload()[0]; eventDispatcher.dispatchEvent(new ZoneTemperatureEvent(zoneNbr == 0 ? 256 : zoneNbr, getTemperature())); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SatelCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SatelCommand.java index e926d4914c543..89353be670f04 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SatelCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SatelCommand.java @@ -38,11 +38,11 @@ public interface SatelCommand { * */ public enum State { - NEW, - ENQUEUED, - SENT, - SUCCEEDED, - FAILED + NEW, + ENQUEUED, + SENT, + SUCCEEDED, + FAILED } /** @@ -78,9 +78,8 @@ public enum State { * Handles response received for the command. Usually generates an event with received data. * * @param eventDispatcher event dispatcher - * @param response response to handle + * @param response response to handle * @return true if response has been successfully handled */ boolean handleResponse(EventDispatcher eventDispatcher, SatelMessage response); - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SatelCommandBase.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SatelCommandBase.java index 6bc74859cf3fa..4acaf558219d7 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SatelCommandBase.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SatelCommandBase.java @@ -46,7 +46,7 @@ public abstract class SatelCommandBase extends SatelMessage implements SatelComm * Creates new command basing on command code and extended command flag. * * @param commandCode command code - * @param extended if true command will be sent as extended (256 zones or outputs) + * @param extended if true command will be sent as extended (256 zones or outputs) */ public SatelCommandBase(byte commandCode, boolean extended) { this(commandCode, extended ? EXTENDED_CMD_PAYLOAD : EMPTY_PAYLOAD); @@ -229,5 +229,4 @@ public String getVersion(int offset) { + new String(payload, offset + 9, 2); return verStr; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SetClockCommand.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SetClockCommand.java index d558d44a97943..5ac1cda03f0d6 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SetClockCommand.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/command/SetClockCommand.java @@ -43,5 +43,4 @@ public SetClockCommand(LocalDateTime dateTime, String userCode) { private static byte[] getDateTimeBytes(LocalDateTime dateTime) { return DATETIME_FORMAT.format(dateTime).getBytes(); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/Atd100Config.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/Atd100Config.java index df7485d70054c..b98bf81af1a0c 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/Atd100Config.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/Atd100Config.java @@ -38,5 +38,4 @@ public int getId() { public int getRefresh() { return refresh; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/Ethm1Config.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/Ethm1Config.java index 70692cc887d90..c1a6faa50019b 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/Ethm1Config.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/Ethm1Config.java @@ -51,5 +51,4 @@ public String getEncryptionKey() { final String encryptionKey = this.encryptionKey; return encryptionKey == null ? "" : encryptionKey; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/IntRSConfig.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/IntRSConfig.java index 4dbca8e010b69..f265650dc5a13 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/IntRSConfig.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/IntRSConfig.java @@ -33,5 +33,4 @@ public class IntRSConfig extends SatelBridgeConfig { public @Nullable String getPort() { return port; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/SatelBridgeConfig.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/SatelBridgeConfig.java index 0685a81b1726a..c1b1d0c72f9ed 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/SatelBridgeConfig.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/SatelBridgeConfig.java @@ -29,6 +29,7 @@ public class SatelBridgeConfig { private int refresh; private @Nullable String userCode; private @Nullable String encoding; + private boolean extCommands; /** * @return value of timeout in milliseconds @@ -60,4 +61,10 @@ public Charset getEncoding() { return encoding == null ? Charset.defaultCharset() : Charset.forName(encoding); } + /** + * @return true if the module supports extended commands + */ + public boolean hasExtCommandsSupport() { + return extCommands; + } } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/SatelThingConfig.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/SatelThingConfig.java index 404a190404503..d7f97881077d0 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/SatelThingConfig.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/config/SatelThingConfig.java @@ -82,5 +82,4 @@ public boolean isCommandOnly() { public boolean isWireless() { return wireless; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryService.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryService.java index 0b9d3eeef527e..a29b1ed1f3a1a 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryService.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/discovery/SatelDeviceDiscoveryService.java @@ -193,5 +193,4 @@ private static boolean isDeviceAvailable(DeviceType deviceType, int deviceKind) return false; } } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ConnectionStatusEvent.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ConnectionStatusEvent.java index 35943b75b60db..909c9d156d226 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ConnectionStatusEvent.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ConnectionStatusEvent.java @@ -40,7 +40,7 @@ public ConnectionStatusEvent(boolean connected) { * Constructs event class with given connection status and disconnection reason. * * @param connected value describing connection status - * @param reason disconnection reason + * @param reason disconnection reason */ public ConnectionStatusEvent(boolean connected, @Nullable String reason) { this.connected = connected; diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/EventDispatcher.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/EventDispatcher.java index 3a74f46cffa32..58e5fa2de0aa8 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/EventDispatcher.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/EventDispatcher.java @@ -82,5 +82,4 @@ public void dispatchEvent(SatelEvent event) { }); } } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraStateEvent.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraStateEvent.java index 51a7e453f6a76..963f2bd42b3e7 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraStateEvent.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraStateEvent.java @@ -35,8 +35,8 @@ public class IntegraStateEvent implements SatelEvent { /** * Constructs new event instance from given state type and state bits. * - * @param command the command byte - * @param stateBits state bits as byte array + * @param command the command byte + * @param stateBits state bits as byte array * @param extendedData whether state bits are for extended command */ public IntegraStateEvent(byte command, byte[] stateBits, boolean extendedData) { @@ -81,7 +81,7 @@ public BitSet getStateBits(StateType stateType) { * Returns true if specified state bit is set for given state. * * @param stateType type of state - * @param nbr state bit number + * @param nbr state bit number * @return true if state bit is set */ public boolean isSet(StateType stateType, int nbr) { diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraStatusEvent.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraStatusEvent.java index 41139c7ad9191..82ea130759e17 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraStatusEvent.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraStatusEvent.java @@ -13,6 +13,7 @@ package org.openhab.binding.satel.internal.event; import java.time.LocalDateTime; +import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -24,7 +25,7 @@ @NonNullByDefault public class IntegraStatusEvent implements SatelEvent { - private LocalDateTime integraTime; + private Optional integraTime; private boolean serviceMode; private boolean troubles; private boolean acu100Present; @@ -40,7 +41,7 @@ public class IntegraStatusEvent implements SatelEvent { * @param statusByte1 status bits, byte #1 * @param statusByte2 status bits, byte #2 */ - public IntegraStatusEvent(LocalDateTime integraTime, byte statusByte1, byte statusByte2) { + public IntegraStatusEvent(Optional integraTime, byte statusByte1, byte statusByte2) { this.integraTime = integraTime; this.serviceMode = (statusByte1 & 0x80) != 0; this.troubles = (statusByte1 & 0x40) != 0; @@ -52,9 +53,10 @@ public IntegraStatusEvent(LocalDateTime integraTime, byte statusByte1, byte stat } /** - * @return current date and time on connected Integra + * @return current date and time on connected Integra or Optional.empty() if date/time set in the + * system is incorrect */ - public LocalDateTime getIntegraTime() { + public Optional getIntegraTime() { return integraTime; } @@ -111,7 +113,7 @@ public int getIntegraType() { public String toString() { return String.format( "IntegraStatusEvent: type = %d, time = %s, service mode = %b, troubles = %b, troubles memory = %b, ACU-100 = %b, INT-RX = %b, grade 2/3 = %b", - this.integraType, this.integraTime, this.serviceMode, this.troubles, this.troublesMemory, - this.acu100Present, this.intRxPresent, this.grade23Set); + this.integraType, this.integraTime.map(LocalDateTime::toString).orElse("N/A"), this.serviceMode, + this.troubles, this.troublesMemory, this.acu100Present, this.intRxPresent, this.grade23Set); } } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraVersionEvent.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraVersionEvent.java index 070096e681e4b..239b5f394fa81 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraVersionEvent.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/IntegraVersionEvent.java @@ -31,9 +31,9 @@ public class IntegraVersionEvent implements SatelEvent { /** * Constructs new event class. * - * @param type Integra type - * @param version string describing version number and firmware revision - * @param language firmware language: 1 - english + * @param type Integra type + * @param version string describing version number and firmware revision + * @param language firmware language: 1 - english * @param settingsInFlash settings stored in flash memory */ public IntegraVersionEvent(byte type, String version, byte language, boolean settingsInFlash) { diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ModuleVersionEvent.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ModuleVersionEvent.java index ab3718bad458e..bedac5f124c14 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ModuleVersionEvent.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ModuleVersionEvent.java @@ -28,7 +28,7 @@ public class ModuleVersionEvent implements SatelEvent { /** * Constructs new event class. * - * @param version string describing version number and firmware revision + * @param version string describing version number and firmware revision * @param extPayloadSupport the module supports extended (32-bit) payload for zones/outputs */ public ModuleVersionEvent(String version, boolean extPayloadSupport) { diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/SatelEventListener.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/SatelEventListener.java index 4d100b9dbade5..bb176001961c1 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/SatelEventListener.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/SatelEventListener.java @@ -78,5 +78,4 @@ default void incomingEvent(NewStatesEvent event) { */ default void incomingEvent(ZoneTemperatureEvent event) { } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ZoneTemperatureEvent.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ZoneTemperatureEvent.java index a017b478b9ac7..0d2b5f11b6a14 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ZoneTemperatureEvent.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/event/ZoneTemperatureEvent.java @@ -28,7 +28,7 @@ public class ZoneTemperatureEvent implements SatelEvent { /** * Constructs new event class. * - * @param zoneNbr zone number + * @param zoneNbr zone number * @param temperature current temperature in the zone */ public ZoneTemperatureEvent(int zoneNbr, float temperature) { diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/Atd100Handler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/Atd100Handler.java index 9bb0b30bb58eb..d67e182915cf4 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/Atd100Handler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/Atd100Handler.java @@ -119,5 +119,4 @@ protected Optional convertCommand(@Nullable ChannelUID channel, @N // no commands supported return Optional.empty(); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/Ethm1BridgeHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/Ethm1BridgeHandler.java index 7cda85c599709..dd98c4d0fd54e 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/Ethm1BridgeHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/Ethm1BridgeHandler.java @@ -56,7 +56,7 @@ public void initialize() { Ethm1Config config = getConfigAs(Ethm1Config.class); if (StringUtils.isNotBlank(config.getHost())) { SatelModule satelModule = new Ethm1Module(config.getHost(), config.getPort(), config.getTimeout(), - config.getEncryptionKey()); + config.getEncryptionKey(), config.hasExtCommandsSupport()); super.initialize(satelModule); } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, @@ -80,5 +80,4 @@ public Collection getConfigStatus() { return configStatusMessages; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/IntRSBridgeHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/IntRSBridgeHandler.java index 354d33539883b..d56a047c1333f 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/IntRSBridgeHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/IntRSBridgeHandler.java @@ -60,7 +60,8 @@ public void initialize() { final IntRSConfig config = getConfigAs(IntRSConfig.class); final String port = config.getPort(); if (port != null && StringUtils.isNotBlank(port)) { - SatelModule satelModule = new IntRSModule(port, serialPortManager, config.getTimeout()); + SatelModule satelModule = new IntRSModule(port, serialPortManager, config.getTimeout(), + config.hasExtCommandsSupport()); super.initialize(satelModule); } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, @@ -84,5 +85,4 @@ public Collection getConfigStatus() { return configStatusMessages; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelBridgeHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelBridgeHandler.java index 4af2bbcbd1cfd..0bccde5a989be 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelBridgeHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelBridgeHandler.java @@ -201,7 +201,7 @@ public ZoneId getZoneId() { * Sends given command to communication module. * * @param command a command to send - * @param async if false method waits for the response + * @param async if false method waits for the response * @return true if send succeeded */ public boolean sendCommand(SatelCommand command, boolean async) { @@ -238,5 +238,4 @@ public boolean sendCommand(SatelCommand command, boolean async) { } return false; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelEventLogHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelEventLogHandler.java index 233fd535ddcdb..1e674017eb7a9 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelEventLogHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelEventLogHandler.java @@ -129,7 +129,6 @@ public String toString() { return "EventLogEntry [index=" + index + ", prevIndex=" + prevIndex + ", timestamp=" + timestamp + ", description=" + description + ", details=" + details + "]"; } - } public SatelEventLogHandler(Thing thing) { @@ -334,7 +333,6 @@ String getText() { int getKind() { return descKind; } - } private static class EventDescription extends EventDescriptionCacheEntry { @@ -344,7 +342,6 @@ private static class EventDescription extends EventDescriptionCacheEntry { super(eventText, descKind); this.readEventCmd = readEventCmd; } - } private EventDescription readEventDescription(ReadEventCommand readEventCmd) { @@ -418,5 +415,4 @@ private String readDeviceName(DeviceType deviceType, int deviceNumber) { }); return result == null ? NOT_AVAILABLE_TEXT : result; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelOutputHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelOutputHandler.java index 4f044c073703d..ec4e7b11233de 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelOutputHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelOutputHandler.java @@ -68,5 +68,4 @@ protected StateType getStateType(String channelId) { } return result; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelPartitionHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelPartitionHandler.java index 1453c3cabefa4..c01d564f75296 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelPartitionHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelPartitionHandler.java @@ -101,5 +101,4 @@ protected Optional convertCommand(ChannelUID channel, Command comm return Optional.empty(); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelShutterHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelShutterHandler.java index 73964a9a8d6a6..b860877521ba2 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelShutterHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelShutterHandler.java @@ -97,5 +97,4 @@ protected Optional convertCommand(ChannelUID channel, Command comm return result == null ? Optional.empty() : Optional.of(result); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelStateThingHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelStateThingHandler.java index 145e12166917c..490db5fdebc6b 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelStateThingHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelStateThingHandler.java @@ -187,5 +187,4 @@ protected Collection getRefreshCommands(NewStatesEvent event) { protected boolean requiresRefresh() { return requiresRefresh.getAndSet(false); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelSystemHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelSystemHandler.java index 1fcfba21f507d..816d84ec4fc28 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelSystemHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelSystemHandler.java @@ -30,6 +30,8 @@ import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.satel.internal.command.ClearTroublesCommand; import org.openhab.binding.satel.internal.command.IntegraStatusCommand; import org.openhab.binding.satel.internal.command.SatelCommand; @@ -79,7 +81,9 @@ public void incomingEvent(IntegraStatusEvent event) { if (getThingConfig().isCommandOnly()) { return; } - updateState(CHANNEL_DATE_TIME, new DateTimeType(event.getIntegraTime().atZone(getBridgeHandler().getZoneId()))); + updateState(CHANNEL_DATE_TIME, + event.getIntegraTime().map(dt -> (State) new DateTimeType(dt.atZone(getBridgeHandler().getZoneId()))) + .orElse(UnDefType.UNDEF)); updateSwitch(CHANNEL_SERVICE_MODE, event.inServiceMode()); updateSwitch(CHANNEL_TROUBLES, event.troublesPresent()); updateSwitch(CHANNEL_TROUBLES_MEMORY, event.troublesMemory()); @@ -139,5 +143,4 @@ protected Collection getRefreshCommands(NewStatesEvent event) { return result; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelThingHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelThingHandler.java index 5fdc77a71eb9c..80d655bb0c0d6 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelThingHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelThingHandler.java @@ -94,7 +94,7 @@ protected SatelBridgeHandler getBridgeHandler() { * Updates switch channel with given state. * * @param channelID channel ID - * @param switchOn if true the channel is updated with ON state, with OFF state otherwise + * @param switchOn if true the channel is updated with ON state, with OFF state otherwise */ protected void updateSwitch(String channelID, boolean switchOn) { ChannelUID channelUID = new ChannelUID(this.getThing().getUID(), channelID); @@ -105,7 +105,7 @@ protected void updateSwitch(String channelID, boolean switchOn) { * Updates switch channel with given state. * * @param channelUID channel UID - * @param switchOn if true the channel is updated with ON state, with OFF state otherwise + * @param switchOn if true the channel is updated with ON state, with OFF state otherwise */ protected void updateSwitch(ChannelUID channelUID, boolean switchOn) { State state = switchOn ? OnOffType.ON : OnOffType.OFF; @@ -116,7 +116,7 @@ protected void updateSwitch(ChannelUID channelUID, boolean switchOn) { * Creates bitset of given size with particular bits set to 1. * * @param size bitset size in bytes - * @param ids bits to set, first bit is 1 + * @param ids bits to set, first bit is 1 * @return bitset as array of bytes */ protected byte[] getObjectBitset(int size, int... ids) { @@ -127,5 +127,4 @@ protected byte[] getObjectBitset(int size, int... ids) { } return bitset; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelZoneHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelZoneHandler.java index b742c6704aeae..1c39720d1e5ee 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelZoneHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/SatelZoneHandler.java @@ -82,5 +82,4 @@ protected StateType getStateType(String channelId) { } return result; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/WirelessChannelsHandler.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/WirelessChannelsHandler.java index 803a6fdb6a657..18e258b02c545 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/WirelessChannelsHandler.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/handler/WirelessChannelsHandler.java @@ -125,5 +125,4 @@ private ChannelUID getChannelUID(StateType stateType) { String channelId = stateType.toString().toLowerCase(); return new ChannelUID(getThing().getUID(), channelId); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/EncryptionHelper.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/EncryptionHelper.java index 7e0f8c070b713..1027e28e01e96 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/EncryptionHelper.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/EncryptionHelper.java @@ -63,9 +63,9 @@ public EncryptionHelper(String keyString) throws GeneralSecurityException { * Decrypts given buffer of bytes in place. * * @param buffer - * bytes to decrypt + * bytes to decrypt * @throws GeneralSecurityException - * on decryption errors + * on decryption errors */ public void decrypt(byte buffer[]) throws GeneralSecurityException { byte[] cv = new byte[16]; @@ -132,5 +132,4 @@ public void encrypt(byte buffer[]) throws GeneralSecurityException { } } } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/Ethm1Module.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/Ethm1Module.java index c09251624ffbc..274c1d6aec9e8 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/Ethm1Module.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/Ethm1Module.java @@ -50,13 +50,15 @@ public class Ethm1Module extends SatelModule { * Creates new instance with host, port, timeout and encryption key set to * specified values. * - * @param host host name or IP of ETHM-1 module - * @param port TCP port the module listens on - * @param timeout timeout value in milliseconds for connect/read/write operations + * @param host host name or IP of ETHM-1 module + * @param port TCP port the module listens on + * @param timeout timeout value in milliseconds for connect/read/write operations * @param encryptionKey encryption key for encrypted communication + * @param extPayloadSupport if true, the module supports extended command payload for reading + * INTEGRA 256 state */ - public Ethm1Module(String host, int port, int timeout, String encryptionKey) { - super(timeout); + public Ethm1Module(String host, int port, int timeout, String encryptionKey, boolean extPayloadSupport) { + super(timeout, extPayloadSupport); this.host = host; this.port = port; @@ -254,5 +256,4 @@ private synchronized void writeMessage(byte[] message, OutputStream os) throws I os.flush(); } } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/IntRSModule.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/IntRSModule.java index b2cd7c843ca6f..f4fdefe93674b 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/IntRSModule.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/IntRSModule.java @@ -46,12 +46,14 @@ public class IntRSModule extends SatelModule { /** * Creates new instance with port and timeout set to specified values. * - * @param port serial port the module is connected to + * @param port serial port the module is connected to * @param serialPortManager serial port manager object - * @param timeout timeout value in milliseconds for connect/read/write operations + * @param timeout timeout value in milliseconds for connect/read/write operations + * @param extPayloadSupport if true, the module supports extended command payload for reading + * INTEGRA 256 state */ - public IntRSModule(String port, SerialPortManager serialPortManager, int timeout) { - super(timeout); + public IntRSModule(String port, SerialPortManager serialPortManager, int timeout, boolean extPayloadSupport) { + super(timeout, extPayloadSupport); this.port = port; this.serialPortManager = serialPortManager; diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/SatelMessage.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/SatelMessage.java index 885321d2eaa20..604cbd167b82c 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/SatelMessage.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/SatelMessage.java @@ -42,9 +42,9 @@ public class SatelMessage { * Creates new instance with specified command code and payload. * * @param command - * command code + * command code * @param payload - * command payload + * command payload */ public SatelMessage(byte command, byte[] payload) { this.command = command; @@ -193,5 +193,4 @@ public int hashCode() { result = prime * result + Arrays.hashCode(payload); return result; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/SatelModule.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/SatelModule.java index ae6a860407332..224b8adc35848 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/SatelModule.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/protocol/SatelModule.java @@ -24,13 +24,11 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.satel.internal.command.IntegraVersionCommand; -import org.openhab.binding.satel.internal.command.ModuleVersionCommand; import org.openhab.binding.satel.internal.command.SatelCommand; import org.openhab.binding.satel.internal.command.SatelCommand.State; import org.openhab.binding.satel.internal.event.ConnectionStatusEvent; import org.openhab.binding.satel.internal.event.EventDispatcher; import org.openhab.binding.satel.internal.event.IntegraVersionEvent; -import org.openhab.binding.satel.internal.event.ModuleVersionEvent; import org.openhab.binding.satel.internal.event.SatelEventListener; import org.openhab.binding.satel.internal.types.IntegraType; import org.slf4j.Logger; @@ -59,7 +57,7 @@ public abstract class SatelModule extends EventDispatcher implements SatelEventL private final int timeout; private volatile IntegraType integraType; private volatile String integraVersion; - private volatile boolean extPayloadSupport; + private final boolean extPayloadSupport; private @Nullable CommunicationChannel channel; private @Nullable CommunicationWatchdog communicationWatchdog; @@ -107,12 +105,14 @@ public ConnectionFailureException(String message, Throwable cause) { * Creates new instance of the class. * * @param timeout timeout value in milliseconds for connect/read/write operations + * @param extPayloadSupport if true, the module supports extended command payload for reading + * INTEGRA256 state */ - public SatelModule(int timeout) { + public SatelModule(int timeout, boolean extPayloadSupport) { this.timeout = timeout; this.integraType = IntegraType.UNKNOWN; this.integraVersion = ""; - this.extPayloadSupport = false; + this.extPayloadSupport = extPayloadSupport; addEventListener(this); } @@ -229,13 +229,6 @@ public boolean sendCommand(SatelCommand cmd, boolean force) { } } - @Override - public void incomingEvent(ModuleVersionEvent event) { - ModuleVersionEvent versionEvent = event; - this.extPayloadSupport = versionEvent.hasExtPayloadSupport(); - logger.info("Module version: {}.", versionEvent.getVersion()); - } - @Override public void incomingEvent(IntegraVersionEvent event) { IntegraVersionEvent versionEvent = event; @@ -527,7 +520,6 @@ public void run() { this.thread.start(); // if module is not initialized yet, send version command if (!SatelModule.this.isInitialized()) { - SatelModule.this.sendCommand(new ModuleVersionCommand()); SatelModule.this.sendCommand(new IntegraVersionCommand()); } } @@ -556,5 +548,4 @@ private void checkThread() { } } } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ControlType.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ControlType.java index 3c4223da7d11a..207161d398c94 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ControlType.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ControlType.java @@ -44,5 +44,4 @@ public interface ControlType { * @return command identifier */ BitSet getControlledStates(); - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/DoorControl.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/DoorControl.java index 4146a593b412c..55b01b94932d6 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/DoorControl.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/DoorControl.java @@ -44,5 +44,4 @@ public ObjectType getObjectType() { public BitSet getControlledStates() { return stateBits; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/DoorState.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/DoorState.java index 82b81cb86174a..3ecd0e088a617 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/DoorState.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/DoorState.java @@ -51,5 +51,4 @@ public int getStartByte() { public int getBytesCount(boolean extendedCmd) { return getPayloadLength(extendedCmd); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/OutputControl.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/OutputControl.java index 501dc80cd8f79..dbd3f9bb35bcf 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/OutputControl.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/OutputControl.java @@ -51,5 +51,4 @@ public ObjectType getObjectType() { public BitSet getControlledStates() { return stateBits; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/OutputState.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/OutputState.java index 79594748027c6..a244de8207cc8 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/OutputState.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/OutputState.java @@ -50,5 +50,4 @@ public int getStartByte() { public int getBytesCount(boolean extendedCmd) { return getPayloadLength(extendedCmd); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/PartitionControl.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/PartitionControl.java index ec3ab4919bd08..8a7925137a511 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/PartitionControl.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/PartitionControl.java @@ -54,5 +54,4 @@ public ObjectType getObjectType() { public BitSet getControlledStates() { return stateBits; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/PartitionState.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/PartitionState.java index 5042966e2cc51..6e0d6247dc1ce 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/PartitionState.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/PartitionState.java @@ -67,5 +67,4 @@ public int getStartByte() { public int getBytesCount(boolean extendedCmd) { return getPayloadLength(extendedCmd); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/StateType.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/StateType.java index 5f8701088057d..e7a74dc271f2d 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/StateType.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/StateType.java @@ -104,7 +104,5 @@ public int getStartByte() { public int getBytesCount(boolean extendedCmd) { throw new UnsupportedOperationException("Illegal use of NONE state type"); } - }; - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/TroubleMemoryState.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/TroubleMemoryState.java index d6ab396a22515..0f495959c2809 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/TroubleMemoryState.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/TroubleMemoryState.java @@ -100,5 +100,4 @@ public int getStartByte() { public int getBytesCount(boolean isExtended) { return bytesCount; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/TroubleState.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/TroubleState.java index ee6615c4853e1..2a7a400127440 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/TroubleState.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/TroubleState.java @@ -93,5 +93,4 @@ public int getStartByte() { public int getBytesCount(boolean isExtended) { return bytesCount; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ZoneControl.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ZoneControl.java index 1cd43525f18cc..4d7e89625e8e2 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ZoneControl.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ZoneControl.java @@ -46,5 +46,4 @@ public ObjectType getObjectType() { public BitSet getControlledStates() { return stateBits; } - } diff --git a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ZoneState.java b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ZoneState.java index bb057dc268a65..1cf602cef0e0f 100644 --- a/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ZoneState.java +++ b/bundles/org.openhab.binding.satel/src/main/java/org/openhab/binding/satel/internal/types/ZoneState.java @@ -61,5 +61,4 @@ public int getStartByte() { public int getBytesCount(boolean extendedCmd) { return getPayloadLength(extendedCmd); } - } diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/binding/binding.xml index 5cd27355b0d49..a859cea3e0228 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Satel Binding diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/atd-100.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/atd-100.xml index 5f61fb7533878..e11bd4e13cf1b 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/atd-100.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/atd-100.xml @@ -7,8 +7,8 @@ - - + + @@ -16,9 +16,9 @@ Sensor - - - + + + @@ -41,7 +41,7 @@ Current temperature in the zone Temperature - + diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/common.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/common.xml index d8c63baadf09c..4bbc6ab6f565d 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/common.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/common.xml @@ -8,7 +8,7 @@ Switch Indicates communication troubles with the wireless device - + diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/ethm-1.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/ethm-1.xml index 2e735dd1d32b7..e78e13e720980 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/ethm-1.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/ethm-1.xml @@ -1,5 +1,6 @@ - @@ -32,7 +33,8 @@ - Security code of the user in behalf of all operations will be executed. If empty, only read operations are allowed. + Security code of the user in behalf of all operations will be executed. If empty, only read operations + are allowed. password @@ -45,6 +47,12 @@ Encoding used for all the texts received from the module. windows-1250 + + + Check this option to enable extended commands supported only by ETHM-1 Plus and newer versions of + ETHM-1. Turn off in case of communication timeouts. + true + diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/event-log.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/event-log.xml index 2a2c14d676e7c..f5ba5d5a2a062 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/event-log.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/event-log.xml @@ -7,8 +7,8 @@ - - + + @@ -16,11 +16,11 @@ Event log must read sequentially starting from the most recent record.]]> - - - - - + + + + + @@ -35,28 +35,28 @@ Number Index of the previous record in the event log. Use this value to iterate over the log. - + DateTime Date and time when the event happened. - + String Textual description of the event. - + String Additional details about the event, like names of partitions, zones, users, etc. - + diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/int-rs.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/int-rs.xml index dbfd5254ba522..a61ddabe099a5 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/int-rs.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/int-rs.xml @@ -1,5 +1,6 @@ - @@ -12,6 +13,7 @@ Serial port connected to the module. serial-port + false @@ -35,6 +37,12 @@ Encoding for all the texts received from the module. windows-1250 + + + Check this option to enable extended commands supported only by version 2.xx of INT-RS. Turn off in + case of communication timeouts. + true + diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/output.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/output.xml index f35989db6972b..d6716bd82438c 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/output.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/output.xml @@ -7,8 +7,8 @@ - - + + @@ -19,7 +19,7 @@ - + diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/partition.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/partition.xml index 02f793aae6b6f..b8d1262bb47bd 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/partition.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/partition.xml @@ -1,40 +1,41 @@ - - - + + -The subdivision into partitions enables arming/disarming the system only in part of the protected area, as well as limiting +The subdivision into partitions enables arming/disarming the system only in part of the protected area, as well as limiting access to some portion of the premises to selected users.]]> - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -84,42 +85,42 @@ access to some portion of the premises to selected users.]]> Switch Active when first code of required two codes has been entered - + Switch Active in entry time - + Switch Active when arming is in progress and time to exit is greater than ten seconds - + Switch Active when arming is in progress and time to exit is less than ten seconds - + Switch Active when the partition is blocked after arming - + Switch Active when the partition is blocked for guard round - + @@ -162,7 +163,7 @@ access to some portion of the premises to selected users.]]> Switch Active when there are violated zones in the partition - + diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/shutter.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/shutter.xml index 72dc638476661..0fd414c92568b 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/shutter.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/shutter.xml @@ -1,20 +1,21 @@ - - - + + A roller shutter connected to two subsequent outputs. - + diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/system.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/system.xml index 1d98842c56647..63385c804fc06 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/system.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/system.xml @@ -1,27 +1,28 @@ - - - + + A virtual thing describing general status of the alarm system. - - - - - - - - + + + + + + + + @@ -48,34 +49,35 @@ Switch Active when the system is in service mode - + Switch Active when there is an ACU-100 module installed in the system - + Switch Active when there is an INT-RX module installed in the system - + Switch Active when Grade2/Grade3 option is set in the system - + String - Accepts string commands that override configured user code. Send empty string to revert user code to the one in the binding configuration. + Accepts string commands that override configured user code. Send empty string to revert user code to the + one in the binding configuration. diff --git a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/zone.xml b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/zone.xml index 6075c870ba2ff..e563e4ef30364 100644 --- a/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/zone.xml +++ b/bundles/org.openhab.binding.satel/src/main/resources/ESH-INF/thing/zone.xml @@ -7,8 +7,8 @@ - - + + @@ -18,18 +18,18 @@
  • virtual - zones which physically do not exist, but have been programmed as FOLLOW OUTPUT or are controlled by means of a keyfob.
]]> - - - - - - - - - - - - + + + + + + + + + + + + @@ -53,42 +53,42 @@ Switch Active when violation is detected in the zone - +
Switch Active when detector in the zone is tampered - + Switch Active when violation is detected in the zone and zone is armed - + Switch Active when detector in the zone is tampered and zone is armed - + Switch Memorized alarm state for the zone - + Switch Memorized tamper alarm state for the zone - + @@ -101,14 +101,14 @@ Switch Active when no violation has been detected in the zone for configured time - + Switch Active when violation in the zone lasts longer than configured time - + @@ -121,14 +121,14 @@ Switch Active when zone is masked - + Switch Memorized masked state for the zone - + diff --git a/bundles/org.openhab.binding.seneye/pom.xml b/bundles/org.openhab.binding.seneye/pom.xml index a024a239dc549..954610f025f66 100644 --- a/bundles/org.openhab.binding.seneye/pom.xml +++ b/bundles/org.openhab.binding.seneye/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.seneye diff --git a/bundles/org.openhab.binding.seneye/src/main/feature/feature.xml b/bundles/org.openhab.binding.seneye/src/main/feature/feature.xml index 04d91def1dee1..03dcdee76ddb6 100644 --- a/bundles/org.openhab.binding.seneye/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.seneye/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.seneye/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.seneye/${project.version} + diff --git a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeBindingConstants.java b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeBindingConstants.java index d7de071b34e1b..e90043222c284 100644 --- a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeBindingConstants.java +++ b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeBindingConstants.java @@ -55,5 +55,4 @@ public class SeneyeBindingConstants { public static final String PARAMETER_POLLTIME = "polltime"; public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_SENEYE); - } diff --git a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingNh4.java b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingNh4.java index da3b213a99a9d..4665748db117b 100644 --- a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingNh4.java +++ b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingNh4.java @@ -25,5 +25,4 @@ public class SeneyeDeviceReadingNh4 { public boolean status; public double curr; public SeneyeDeviceReadingAdvice[] advices; - } diff --git a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingO2.java b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingO2.java index 66c0dc306bf2e..8e15bfdeea33c 100644 --- a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingO2.java +++ b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingO2.java @@ -25,5 +25,4 @@ public class SeneyeDeviceReadingO2 { public boolean status; public double curr; public SeneyeDeviceReadingAdvice[] advices; - } diff --git a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingPh.java b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingPh.java index eb0e684a125c4..22a919328c60a 100644 --- a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingPh.java +++ b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingPh.java @@ -25,5 +25,4 @@ public class SeneyeDeviceReadingPh { public boolean status; public double curr; public SeneyeDeviceReadingAdvice[] advices; - } diff --git a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingTemperature.java b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingTemperature.java index 4d13f22319045..8a376c5421ffa 100644 --- a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingTemperature.java +++ b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeDeviceReadingTemperature.java @@ -25,5 +25,4 @@ public class SeneyeDeviceReadingTemperature { public boolean status; public double curr; public SeneyeDeviceReadingAdvice[] advices; - } diff --git a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeStatus.java b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeStatus.java index 94c5c83c11e64..270e194bf2155 100644 --- a/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeStatus.java +++ b/bundles/org.openhab.binding.seneye/src/main/java/org/openhab/binding/seneye/internal/SeneyeStatus.java @@ -57,5 +57,4 @@ public String getOut_of_waterString() { public String getDisconnectedString() { return disconnected; } - } diff --git a/bundles/org.openhab.binding.seneye/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.seneye/src/main/resources/ESH-INF/binding/binding.xml index d354603fbb97b..a321ab584f424 100644 --- a/bundles/org.openhab.binding.seneye/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.seneye/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Seneye Binding The seneye binding polls the seneye API for your aquarium readings. diff --git a/bundles/org.openhab.binding.seneye/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.seneye/src/main/resources/ESH-INF/thing/thing-types.xml index b28f61ffd0efa..cbb2a353e2aa0 100644 --- a/bundles/org.openhab.binding.seneye/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.seneye/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -21,8 +21,8 @@ - - + + @@ -55,84 +55,84 @@ Number The water temperature - +
Number The PH Level - + Number The NH3 Level - + Number The NH4 Level - + Number The O2 Level - + Number The LUX Light Level - + Number The PAR Light Level - + Number The Kelvin Light Level - + DateTime The last time your seneye is checked - + DateTime The time your slide expires - + String The Wrong Slide is in use (becomes 1 when the slide has expired) - + String The serial Number of the currently installed slide - + String The Sensor is reporting being out of the water - + String No readings have been uploaded for a while, check connection - + diff --git a/bundles/org.openhab.binding.sensebox/pom.xml b/bundles/org.openhab.binding.sensebox/pom.xml index 4f56f1a842c85..7b51bf991b376 100644 --- a/bundles/org.openhab.binding.sensebox/pom.xml +++ b/bundles/org.openhab.binding.sensebox/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.sensebox diff --git a/bundles/org.openhab.binding.sensebox/src/main/feature/feature.xml b/bundles/org.openhab.binding.sensebox/src/main/feature/feature.xml index b4d2066e7bd90..21c57f9e8c0ed 100644 --- a/bundles/org.openhab.binding.sensebox/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.sensebox/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.sensebox/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.sensebox/${project.version} + diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxData.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxData.java index 8d1473a4d73c3..7f8886c0377fb 100644 --- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxData.java +++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxData.java @@ -14,9 +14,10 @@ import java.util.List; +import org.eclipse.smarthome.core.thing.ThingStatus; + import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; -import org.eclipse.smarthome.core.thing.ThingStatus; /** * The {@link SenseBoxData} holds a de-serialized representation @@ -194,13 +195,11 @@ public void setParticulateMatter2dot5(SenseBoxSensor particulateMatter2dot5) { this.particulateMatter2dot5 = particulateMatter2dot5; } - public SenseBoxSensor getParticulateMatter10() - { + public SenseBoxSensor getParticulateMatter10() { return particulateMatter10; } - public void setParticulateMatter10(SenseBoxSensor particulateMatter10) - { + public void setParticulateMatter10(SenseBoxSensor particulateMatter10) { this.particulateMatter10 = particulateMatter10; } } diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLoc.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLoc.java index 6937d5412c1e1..d68f32f6a11dd 100644 --- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLoc.java +++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxLoc.java @@ -32,5 +32,4 @@ public SenseBoxGeometry getGeometry() { public void setGeometry(SenseBoxGeometry geometry) { this.geometry = geometry; } - } diff --git a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxMeasurement.java b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxMeasurement.java index bff0cf19e341e..7b0390465260c 100644 --- a/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxMeasurement.java +++ b/bundles/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/internal/model/SenseBoxMeasurement.java @@ -43,5 +43,4 @@ public String getCreatedAt() { public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } - } diff --git a/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/box.xml b/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/box.xml index f1ba9d12535ea..749873fe8410e 100644 --- a/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/box.xml +++ b/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/box.xml @@ -10,14 +10,14 @@ This is a senseBox sensor. - - - + + + senseBoxId - + diff --git a/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/channels.xml index 6bc6f5fe9b64a..302d919ea7254 100644 --- a/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.sensebox/src/main/resources/ESH-INF/thing/channels.xml @@ -9,7 +9,7 @@ Box descriptors like Location, description, etc. - + @@ -17,13 +17,13 @@ Measurements as fetched from the API. - - - - - - - + + + + + + + @@ -31,13 +31,13 @@ Timestamps when a measurement was last reported. - - - - - - - + + + + + + + @@ -58,7 +58,7 @@ DateTime Timestamp when data was measured. - +
@@ -31,8 +31,8 @@ The vendor selling the WiFi socket. - - + + diff --git a/bundles/org.openhab.binding.sinope/pom.xml b/bundles/org.openhab.binding.sinope/pom.xml index a0715ef1bf2f9..69c4e2641ace6 100644 --- a/bundles/org.openhab.binding.sinope/pom.xml +++ b/bundles/org.openhab.binding.sinope/pom.xml @@ -1,15 +1,17 @@ - + + - 4.0.0 + 4.0.0 - - org.openhab.addons.bundles - org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT - + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + - org.openhab.binding.sinope + org.openhab.binding.sinope - openHAB Add-ons :: Bundles :: Sinope Binding + openHAB Add-ons :: Bundles :: Sinope Binding diff --git a/bundles/org.openhab.binding.sinope/src/main/feature/feature.xml b/bundles/org.openhab.binding.sinope/src/main/feature/feature.xml index 9ed99009ca7cf..914ba50ab6d39 100644 --- a/bundles/org.openhab.binding.sinope/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.sinope/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.sinope/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.sinope/${project.version} + diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/SinopeBindingConstants.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/SinopeBindingConstants.java index fec6d4f06542e..963ad02d52072 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/SinopeBindingConstants.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/SinopeBindingConstants.java @@ -53,5 +53,4 @@ public class SinopeBindingConstants { SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_GATEWAY); SUPPORTED_THING_TYPES_UIDS.add(THING_TYPE_THERMO); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeApiLoginRequest.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeApiLoginRequest.java index ad6d2f0f82bb6..403a645e2b310 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeApiLoginRequest.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeApiLoginRequest.java @@ -83,5 +83,4 @@ public byte[] getId() { public SinopeApiLoginAnswer getReplyAnswer(InputStream r) throws IOException { return new SinopeApiLoginAnswer(r); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeAuthenticationKeyAnswer.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeAuthenticationKeyAnswer.java index b9b4f0679edfc..0cf7526db2573 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeAuthenticationKeyAnswer.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeAuthenticationKeyAnswer.java @@ -98,5 +98,4 @@ public String toString() { sb.append(String.format("\n\tBackoff: %s", ByteUtil.toString(getBackoff()))); return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeAuthenticationKeyRequest.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeAuthenticationKeyRequest.java index b335bd7e6ff0d..f66ad8a8bc867 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeAuthenticationKeyRequest.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeAuthenticationKeyRequest.java @@ -69,5 +69,4 @@ public SinopeAuthenticationKeyAnswer getReplyAnswer(InputStream r) throws IOExce public byte[] getId() { return id; } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataReadAnswer.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataReadAnswer.java index ff59134e68bf7..c362ca166703e 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataReadAnswer.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataReadAnswer.java @@ -43,5 +43,4 @@ public SinopeDataReadAnswer(InputStream r, SinopeAppData appData) throws IOExcep protected byte[] getCommand() { return new byte[] { 0x02, 0x41 }; } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataReadRequest.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataReadRequest.java index be61796889a71..b8f045ecc40c3 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataReadRequest.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataReadRequest.java @@ -53,5 +53,4 @@ protected byte[] getCommand() { public SinopeDataReadAnswer getReplyAnswer(InputStream r) throws IOException { return new SinopeDataReadAnswer(r, this.getAppData()); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataWriteAnswer.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataWriteAnswer.java index 653b6f7c6ccc7..8df9d2e14864c 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataWriteAnswer.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataWriteAnswer.java @@ -43,5 +43,4 @@ public SinopeDataWriteAnswer(InputStream r, SinopeAppData appData) throws IOExce protected byte[] getCommand() { return new byte[] { 0x02, 0x45 }; } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataWriteRequest.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataWriteRequest.java index 00cb12f3344c2..1771c39bd400c 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataWriteRequest.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDataWriteRequest.java @@ -51,5 +51,4 @@ protected byte[] getCommand() { public SinopeDataReadAnswer getReplyAnswer(InputStream r) throws IOException { return new SinopeDataReadAnswer(r, this.getAppData()); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDeviceReportAnswer.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDeviceReportAnswer.java index 072e9b6ad0b28..dae194703dfdb 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDeviceReportAnswer.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopeDeviceReportAnswer.java @@ -82,5 +82,4 @@ public String toString() { sb.append(String.format("\n\tDeviceId: %s", ByteUtil.toString(getDeviceId()))); return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopePingAnswer.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopePingAnswer.java index 86d178560c51c..da599f19d41a1 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopePingAnswer.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopePingAnswer.java @@ -41,5 +41,4 @@ public SinopePingAnswer(InputStream r) throws IOException { protected byte[] getCommand() { return new byte[] { 0x00, 0x13 }; } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopePingRequest.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopePingRequest.java index a4113629ebdd5..fa6a7ac5fa258 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopePingRequest.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/SinopePingRequest.java @@ -47,5 +47,4 @@ protected byte[] getFrameData() { public SinopePingAnswer getReplyAnswer(InputStream r) throws IOException { return new SinopePingAnswer(r); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeAppData.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeAppData.java index 58c4fc0f0c7ce..a44c2a3afce40 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeAppData.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeAppData.java @@ -132,5 +132,4 @@ public String toString() { public void cleanData() { this.data = null; } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeHeatLevelData.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeHeatLevelData.java index fd341343c5f2c..bd1234e3e11e1 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeHeatLevelData.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeHeatLevelData.java @@ -50,5 +50,4 @@ public String toString() { } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeLocalTimeData.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeLocalTimeData.java index bd0079fb96a2c..c77680dba8e20 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeLocalTimeData.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeLocalTimeData.java @@ -25,5 +25,4 @@ public class SinopeLocalTimeData extends SinopeAppData { public SinopeLocalTimeData() { super(new byte[] { 0x00, 0x00, 0x06, 0x00 }, new byte[] { 0, 0, 0 }); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeOutTempData.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeOutTempData.java index e8af95fc37cd8..8981653f9e4ed 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeOutTempData.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeOutTempData.java @@ -55,5 +55,4 @@ public String toString() { } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeRoomTempData.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeRoomTempData.java index 0e6c4a20d1ecd..d7abecbc90ea7 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeRoomTempData.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeRoomTempData.java @@ -55,5 +55,4 @@ public String toString() { } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeSetPointModeData.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeSetPointModeData.java index 2e3443b92eebd..3df4a200f7b25 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeSetPointModeData.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeSetPointModeData.java @@ -54,5 +54,4 @@ public String toString() { public void setSetPointMode(byte mode) { getData()[0] = mode; } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeSetPointTempData.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeSetPointTempData.java index 90a6994dfaa17..5ce3c0cb526a3 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeSetPointTempData.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/appdata/SinopeSetPointTempData.java @@ -61,5 +61,4 @@ public void setSetPointTemp(int newTemp) { bb.order(ByteOrder.LITTLE_ENDIAN); bb.putShort((short) newTemp); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/NotSupportedException.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/NotSupportedException.java index 94c17077e9bc2..61a1ed216c9d7 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/NotSupportedException.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/NotSupportedException.java @@ -21,5 +21,4 @@ public class NotSupportedException extends RuntimeException { /** The Constant serialVersionUID. */ private static final long serialVersionUID = 1L; - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeAnswer.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeAnswer.java index 0e41290bb8995..81bbc31af5d3d 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeAnswer.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeAnswer.java @@ -114,5 +114,4 @@ protected void setInternal_payload(byte[] internal_payload) { logger.debug("Answer Frame: {}", ByteUtil.toString(internal_payload)); super.setInternal_payload(internal_payload); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeDataAnswer.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeDataAnswer.java index 5bed6404e37ba..088d6e3ae4a61 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeDataAnswer.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeDataAnswer.java @@ -158,5 +158,4 @@ public String toString() { return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeFrame.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeFrame.java index 33dc5289905d6..3ccf78c8eeea5 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeFrame.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/core/base/SinopeFrame.java @@ -124,5 +124,4 @@ protected byte[] getInternal_payload() { protected void setInternal_payload(byte[] internal_payload) { this.internal_payload = internal_payload; } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/util/ByteUtil.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/util/ByteUtil.java index 8b6f58521d49d..804a1303bf59f 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/util/ByteUtil.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/util/ByteUtil.java @@ -58,5 +58,4 @@ public static String toString(byte[] buf) { } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/util/CRC8.java b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/util/CRC8.java index 52f42644e79d1..deb5210c43c83 100644 --- a/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/util/CRC8.java +++ b/bundles/org.openhab.binding.sinope/src/main/java/org/openhab/binding/sinope/internal/util/CRC8.java @@ -94,5 +94,4 @@ public long getValue() { public void reset() { value = init; } - } diff --git a/bundles/org.openhab.binding.sinope/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.sinope/src/main/resources/ESH-INF/binding/binding.xml index f1f7ea0df56b2..7e549d9846115 100644 --- a/bundles/org.openhab.binding.sinope/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.sinope/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,11 @@ - Sinopé Binding - This is the binding for Sinopé. Sinopé provides high-quality, energy-efficient products and with innovative technology solutions that will meet customer's current and future needs: - low and high voltage thermostats, light switches, water leak detectors and load controllers. + This is the binding for Sinopé. Sinopé provides high-quality, energy-efficient products and with + innovative technology solutions that will meet customer's current and future needs: + low and high voltage thermostats, + light switches, water leak detectors and load controllers. Pascal Larin diff --git a/bundles/org.openhab.binding.sinope/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.sinope/src/main/resources/ESH-INF/thing/thing-types.xml index 6d23464a94bad..335430d822eee 100644 --- a/bundles/org.openhab.binding.sinope/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.sinope/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -38,16 +39,16 @@ - + Sinopé Thermostat control - - - - - + + + + + @@ -62,7 +63,7 @@ Current inside temperature Temperature - +
@@ -70,7 +71,7 @@ Current outside temperature Temperature - + @@ -78,7 +79,7 @@ Setpoint temperature Temperature - + @@ -105,6 +106,6 @@ Heating Level Heating - + diff --git a/bundles/org.openhab.binding.sleepiq/.classpath b/bundles/org.openhab.binding.sleepiq/.classpath index a5d95095ccaaf..9465c8288ee24 100644 --- a/bundles/org.openhab.binding.sleepiq/.classpath +++ b/bundles/org.openhab.binding.sleepiq/.classpath @@ -11,11 +11,13 @@ - + + + + - diff --git a/bundles/org.openhab.binding.sleepiq/NOTICE b/bundles/org.openhab.binding.sleepiq/NOTICE index 2713faafa7fb6..75446268e8643 100644 --- a/bundles/org.openhab.binding.sleepiq/NOTICE +++ b/bundles/org.openhab.binding.sleepiq/NOTICE @@ -14,12 +14,11 @@ https://github.com/openhab/openhab-addons == Third-party Content -libsleepiq-java +The sources of libsleepiq-java are included in src/3rdparty/java and have been slightly adapted. * License: Apache 2.0 License * Project: https://github.com/syphr42/libsleepiq-java * Source: https://github.com/syphr42/libsleepiq-java -provider-gson -* License: EPL 1.0 License -* Project: https://github.com/hstaudacher/osgi-jax-rs-connector -* Source: https://github.com/hstaudacher/osgi-jax-rs-connector +This binding includes a class from Jersey in the src/3rdparty/java folder. +* License: CDDL License +* Project: https://eclipse-ee4j.github.io/jersey/ diff --git a/bundles/org.openhab.binding.sleepiq/pom.xml b/bundles/org.openhab.binding.sleepiq/pom.xml index 917ea85e403e2..6cff18e971fe3 100644 --- a/bundles/org.openhab.binding.sleepiq/pom.xml +++ b/bundles/org.openhab.binding.sleepiq/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.sleepiq @@ -18,17 +20,45 @@ - org.syphr - sleepiq-api - 0.3.0 - compile - - - com.eclipsesource.jaxrs - provider-gson - 2.3 - compile + junit + junit + 4.12 + test + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + add-source + + generate-sources + + + src/3rdparty/java + + + + + add-test-source + generate-sources + + add-test-source + + + + src/3rdparty/test + + + + + + + + diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/BedNotFoundException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/BedNotFoundException.java new file mode 100644 index 0000000000000..3eba856849511 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/BedNotFoundException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api; + +import org.openhab.binding.sleepiq.api.model.Failure; + +public class BedNotFoundException extends SleepIQException +{ + private static final long serialVersionUID = 1L; + + public BedNotFoundException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java new file mode 100644 index 0000000000000..cb0fd28ba4a7d --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java @@ -0,0 +1,180 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api; + +import java.net.URI; +import java.util.logging.Level; + +/** + * This class represents configuration parameters for using {@link SleepIQ}. + * + * @author Gregory Moyer + */ +public class Configuration +{ + private String username; + private String password; + + private URI baseUri = URI.create("https://api.sleepiq.sleepnumber.com/rest"); + + private boolean logging = false; + + /** + * Get the username on the account. + * + * @return the username + */ + public String getUsername() + { + return username; + } + + /** + * Set the username on the account. This should be the username used to + * register with SleepIQ. + * + * @param username + * the value to set + */ + public void setUsername(String username) + { + this.username = username; + } + + /** + * Set the username on the account. This should be the username used to + * register with SleepIQ. + * + * @param username + * the value to set + * @return this configuration instance + */ + public Configuration withUsername(String username) + { + setUsername(username); + return this; + } + + /** + * Get the password on the account. + * + * @return the password + */ + public String getPassword() + { + return password; + } + + /** + * Set the password on the account. This should be the password used to + * register with SleepIQ. + * + * @param password + * the value to set + */ + public void setPassword(String password) + { + this.password = password; + } + + /** + * Set the password on the account. This should be the password used to + * register with SleepIQ. + * + * @param password + * the value to set + * @return this configuration instance + */ + public Configuration withPassword(String password) + { + setPassword(password); + return this; + } + + /** + * Get the base URI of the SleepIQ cloud service. + * + * @return the base URI + */ + public URI getBaseUri() + { + return baseUri; + } + + /** + * Set the base URI of the SleepIQ cloud service. It is unlikely that this + * will need to be changed from its default value. + * + * @param baseUri + * the value to set + */ + public void setBaseUri(URI baseUri) + { + this.baseUri = baseUri; + } + + /** + * Set the base URI of the SleepIQ cloud service. It is unlikely that this + * will need to be changed from its default value. + * + * @param baseUri + * the value to set + * @return this configuration instance + */ + public Configuration withBaseUri(URI baseUri) + { + setBaseUri(baseUri); + return this; + } + + /** + * Get the logging flag. + * + * @return the logging flag + */ + public boolean isLogging() + { + return logging; + } + + /** + * Set the logging flag. When this is set to true, all requests + * and responses will be logged at the {@link Level#INFO} level. This + * includes usernames and passwords! + * + * @param logging + * the value to set + */ + public void setLogging(boolean logging) + { + this.logging = logging; + } + + /** + * Set the logging flag. When this is set to true, all requests + * and responses will be logged at the {@link Level#INFO} level. This + * includes usernames and passwords! + * + * @param logging + * the value to set + * @return this configuration instance + */ + public Configuration withLogging(boolean logging) + { + setLogging(logging); + return this; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java new file mode 100644 index 0000000000000..6480ae4ffd083 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api; + +import org.openhab.binding.sleepiq.api.model.Failure; + +public class LoginException extends SleepIQException +{ + private static final long serialVersionUID = 1L; + + public LoginException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQ.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQ.java new file mode 100644 index 0000000000000..dcb01b80f7040 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQ.java @@ -0,0 +1,101 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api; + +import java.util.List; + +import org.openhab.binding.sleepiq.api.impl.SleepIQImpl; +import org.openhab.binding.sleepiq.api.model.Bed; +import org.openhab.binding.sleepiq.api.model.FamilyStatus; +import org.openhab.binding.sleepiq.api.model.LoginInfo; +import org.openhab.binding.sleepiq.api.model.PauseMode; +import org.openhab.binding.sleepiq.api.model.Sleeper; + +/** + * This interface is the main API to access the SleepIQ system. + * + * @author Gregory Moyer + */ +public interface SleepIQ +{ + /** + * Login to the {@link Configuration configured} account. This method is not + * required to be called before other methods because all methods must + * ensure login before acting. However, when the only desired action is to + * login and not retrieve other data, this method is the most efficient + * option. + * + * @return basic information about the logged in user + * @throws UnauthorizedException + * if the credentials provided are not valid + * @throws LoginException + * if the login request fails for any reason other than bad + * credentials (including missing credentials) + */ + public LoginInfo login() throws LoginException; + + /** + * Get a list of beds connected to the account. + * + * @return the list of beds + */ + public List getBeds(); + + /** + * Get a list of people registered to this account for beds or bed positions + * (left or right side). + * + * @return the list of sleepers + */ + public List getSleepers(); + + /** + * Get the status of all beds and all air chambers registered to this + * account. + * + * @return the complete status of beds on the account + */ + public FamilyStatus getFamilyStatus(); + + /** + * Get the status of "pause mode" (disabling SleepIQ data upload) for a + * specific bed. A bed in pause mode will send no information to the SleepIQ + * cloud services. For example, if a sleeper is in bed and disables SleepIQ + * (enables pause mode), the service will continue to report that the bed is + * occupied even after the sleeper exits the bed until pause mode is + * disabled. + * + * @param bedId + * the unique identifier of the bed to query + * @return the status of pause mode for the specified bed + * @throws BedNotFoundException + * if the bed identifier was not found on the account + */ + public PauseMode getPauseMode(String bedId) throws BedNotFoundException; + + /** + * Create a default implementation instance of this interface. Each call to + * this method will create a new object. + * + * @param config + * the configuration to use for the new instance + * @return a concrete implementation of this interface + */ + public static SleepIQ create(Configuration config) + { + return new SleepIQImpl(config); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQException.java new file mode 100644 index 0000000000000..55935c1f7d2e5 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQException.java @@ -0,0 +1,36 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api; + +import org.openhab.binding.sleepiq.api.model.Failure; + +public class SleepIQException extends Exception +{ + private static final long serialVersionUID = 1L; + + private final Failure failure; + + public SleepIQException(Failure failure) + { + super(failure.getError().getMessage()); + this.failure = failure; + } + + public Failure getFailure() + { + return failure; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/UnauthorizedException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/UnauthorizedException.java new file mode 100644 index 0000000000000..5a809005fa785 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/UnauthorizedException.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api; + +import org.openhab.binding.sleepiq.api.model.Failure; + +public class UnauthorizedException extends LoginException +{ + private static final long serialVersionUID = 1L; + + public UnauthorizedException(Failure failure) + { + super(failure); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/filter/LoggingFilter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/filter/LoggingFilter.java new file mode 100644 index 0000000000000..5ce38e5ef3903 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/filter/LoggingFilter.java @@ -0,0 +1,355 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2011-2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package org.openhab.binding.sleepiq.api.filter; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Logger; + +import javax.annotation.Priority; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; + +/** + * Universal logging filter. + *

+ * Can be used on client or server side. Has the highest priority. + * + * @author Pavel Bucek (pavel.bucek at oracle.com) + * @author Martin Matula + */ +@PreMatching +@Priority(Integer.MIN_VALUE) +public final class LoggingFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, + ClientResponseFilter, WriterInterceptor { + + public static final Charset UTF8 = Charset.forName("UTF-8"); + + private static final Logger LOGGER = Logger.getLogger(LoggingFilter.class.getName()); + private static final String NOTIFICATION_PREFIX = "* "; + private static final String REQUEST_PREFIX = "> "; + private static final String RESPONSE_PREFIX = "< "; + private static final String ENTITY_LOGGER_PROPERTY = LoggingFilter.class.getName() + ".entityLogger"; + private static final String LOGGING_ID_PROPERTY = LoggingFilter.class.getName() + ".id"; + + private static final Comparator>> COMPARATOR = new Comparator>>() { + + @Override + public int compare(final Map.Entry> o1, final Map.Entry> o2) { + return o1.getKey().compareToIgnoreCase(o2.getKey()); + } + }; + + private static final int DEFAULT_MAX_ENTITY_SIZE = 8 * 1024; + + // + private final Logger logger; + private final AtomicLong _id = new AtomicLong(0); + private final boolean printEntity; + private final int maxEntitySize; + + /** + * Create a logging filter logging the request and response to a default JDK + * logger, named as the fully qualified class name of this class. Entity + * logging is turned off by default. + */ + public LoggingFilter() { + this(LOGGER, false); + } + + /** + * Create a logging filter with custom logger and custom settings of entity + * logging. + * + * @param logger the logger to log requests and responses. + * @param printEntity if true, entity will be logged as well up to the default maxEntitySize, which is 8KB + */ + public LoggingFilter(final Logger logger, final boolean printEntity) { + this.logger = logger; + this.printEntity = printEntity; + this.maxEntitySize = DEFAULT_MAX_ENTITY_SIZE; + } + + /** + * Creates a logging filter with custom logger and entity logging turned on, but potentially limiting the size + * of entity to be buffered and logged. + * + * @param logger the logger to log requests and responses. + * @param maxEntitySize maximum number of entity bytes to be logged (and buffered) - if the entity is larger, + * logging filter will print (and buffer in memory) only the specified number of bytes + * and print "...more..." string at the end. Negative values are interpreted as zero. + */ + public LoggingFilter(final Logger logger, final int maxEntitySize) { + this.logger = logger; + this.printEntity = true; + this.maxEntitySize = Math.max(0, maxEntitySize); + } + + private void log(final StringBuilder b) { + if (logger != null) { + logger.info(b.toString()); + } + } + + private StringBuilder prefixId(final StringBuilder b, final long id) { + b.append(Long.toString(id)).append(" "); + return b; + } + + private void printRequestLine(final StringBuilder b, final String note, final long id, final String method, + final URI uri) { + prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") + .append(Thread.currentThread().getName()).append("\n"); + prefixId(b, id).append(REQUEST_PREFIX).append(method).append(" ").append(uri.toASCIIString()).append("\n"); + } + + private void printResponseLine(final StringBuilder b, final String note, final long id, final int status) { + prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") + .append(Thread.currentThread().getName()).append("\n"); + prefixId(b, id).append(RESPONSE_PREFIX).append(Integer.toString(status)).append("\n"); + } + + private void printPrefixedHeaders(final StringBuilder b, final long id, final String prefix, + final MultivaluedMap headers) { + for (final Map.Entry> headerEntry : getSortedHeaders(headers.entrySet())) { + final List val = headerEntry.getValue(); + final String header = headerEntry.getKey(); + + if (val.size() == 1) { + prefixId(b, id).append(prefix).append(header).append(": ").append(val.get(0)).append("\n"); + } else { + final StringBuilder sb = new StringBuilder(); + boolean add = false; + for (final Object s : val) { + if (add) { + sb.append(','); + } + add = true; + sb.append(s); + } + prefixId(b, id).append(prefix).append(header).append(": ").append(sb.toString()).append("\n"); + } + } + } + + private Set>> getSortedHeaders(final Set>> headers) { + final TreeSet>> sortedHeaders = new TreeSet>>( + COMPARATOR); + sortedHeaders.addAll(headers); + return sortedHeaders; + } + + private InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) + throws IOException { + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + stream.mark(maxEntitySize + 1); + final byte[] entity = new byte[maxEntitySize + 1]; + final int entitySize = stream.read(entity); + b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); + if (entitySize > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + stream.reset(); + return stream; + } + + @Override + public void filter(final ClientRequestContext context) throws IOException { + final long id = _id.incrementAndGet(); + context.setProperty(LOGGING_ID_PROPERTY, id); + + final StringBuilder b = new StringBuilder(); + + printRequestLine(b, "Sending client request", id, context.getMethod(), context.getUri()); + printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getStringHeaders()); + + if (printEntity && context.hasEntity()) { + final OutputStream stream = new LoggingStream(b, context.getEntityStream()); + context.setEntityStream(stream); + context.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) + throws IOException { + final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); + final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); + + final StringBuilder b = new StringBuilder(); + + printResponseLine(b, "Client response received", id, responseContext.getStatus()); + printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getHeaders()); + + if (printEntity && responseContext.hasEntity()) { + responseContext.setEntityStream( + logInboundEntity(b, responseContext.getEntityStream(), getCharset(responseContext.getMediaType()))); + } + + log(b); + } + + @Override + public void filter(final ContainerRequestContext context) throws IOException { + final long id = _id.incrementAndGet(); + context.setProperty(LOGGING_ID_PROPERTY, id); + + final StringBuilder b = new StringBuilder(); + + printRequestLine(b, "Server has received a request", id, context.getMethod(), + context.getUriInfo().getRequestUri()); + printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getHeaders()); + + if (printEntity && context.hasEntity()) { + context.setEntityStream(logInboundEntity(b, context.getEntityStream(), getCharset(context.getMediaType()))); + } + + log(b); + } + + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) + throws IOException { + final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); + final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); + + final StringBuilder b = new StringBuilder(); + + printResponseLine(b, "Server responded with a response", id, responseContext.getStatus()); + printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getStringHeaders()); + + if (printEntity && responseContext.hasEntity()) { + final OutputStream stream = new LoggingStream(b, responseContext.getEntityStream()); + responseContext.setEntityStream(stream); + requestContext.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void aroundWriteTo(final WriterInterceptorContext writerInterceptorContext) + throws IOException, WebApplicationException { + final LoggingStream stream = (LoggingStream) writerInterceptorContext.getProperty(ENTITY_LOGGER_PROPERTY); + writerInterceptorContext.proceed(); + if (stream != null) { + log(stream.getStringBuilder(getCharset(writerInterceptorContext.getMediaType()))); + } + } + + private class LoggingStream extends FilterOutputStream { + + private final StringBuilder b; + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + LoggingStream(final StringBuilder b, final OutputStream inner) { + super(inner); + + this.b = b; + } + + StringBuilder getStringBuilder(final Charset charset) { + // write entity to the builder + final byte[] entity = baos.toByteArray(); + + b.append(new String(entity, 0, Math.min(entity.length, maxEntitySize), charset)); + if (entity.length > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + + return b; + } + + @Override + public void write(final int i) throws IOException { + if (baos.size() <= maxEntitySize) { + baos.write(i); + } + out.write(i); + } + } + + /** + * Get the character set from a media type. + *

+ * The character set is obtained from the media type parameter "charset". + * If the parameter is not present the {@link #UTF8} charset is utilized. + * + * @param m the media type. + * @return the character set. + */ + public static Charset getCharset(MediaType m) { + String name = (m == null) ? null : m.getParameters().get(MediaType.CHARSET_PARAMETER); + return (name == null) ? UTF8 : Charset.forName(name); + } + +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/AbstractClient.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/AbstractClient.java new file mode 100644 index 0000000000000..7f5e3cbce948b --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/AbstractClient.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.impl; + +import javax.ws.rs.client.Client; + +import com.google.gson.Gson; + +public abstract class AbstractClient +{ + private volatile Client client; + private volatile Gson gson; + + protected Client getClient() + { + if (client == null) + { + synchronized (this) + { + if (client == null) + { + client = createClient(); + } + } + } + + return client; + } + + protected Gson getGson() + { + if (gson == null) + { + synchronized (this) + { + if (gson == null) + { + gson = createGson(); + } + } + } + + return gson; + } + + protected abstract Client createClient(); + + protected Gson createGson() + { + return GsonGenerator.create(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/Endpoints.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/Endpoints.java new file mode 100644 index 0000000000000..a1e8f348e4c3b --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/Endpoints.java @@ -0,0 +1,54 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.impl; + +public class Endpoints +{ + private static final String LOGIN = "login"; + private static final String BED = "bed"; + private static final String SLEEPER = "sleeper"; + private static final String FAMILY_STATUS = "familyStatus"; + private static final String PAUSE_MODE = "pauseMode"; + + public static String login() + { + return LOGIN; + } + + public static String bed() + { + return BED; + } + + public static String sleeper() + { + return SLEEPER; + } + + public static String familyStatus() + { + return FAMILY_STATUS; + } + + public static String pauseMode() + { + return PAUSE_MODE; + } + + // @formatter:off + private Endpoints() {} + // @formatter:on +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/GsonGenerator.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/GsonGenerator.java new file mode 100644 index 0000000000000..fb67e9b0ac83f --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/GsonGenerator.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.impl; + +import org.openhab.binding.sleepiq.api.impl.typeadapters.JSR310TypeAdapters; +import org.openhab.binding.sleepiq.api.impl.typeadapters.TimeSinceTypeAdapter; +import org.openhab.binding.sleepiq.api.model.TimeSince; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class GsonGenerator +{ + public static Gson create() + { + return create(false); + } + + public static Gson create(boolean prettyPrint) + { + GsonBuilder builder = new GsonBuilder(); + + // add Java 8 Time API support + JSR310TypeAdapters.registerJSR310TypeAdapters(builder); + + builder.registerTypeAdapter(TimeSince.class, new TimeSinceTypeAdapter()); + + if (prettyPrint) + { + builder.setPrettyPrinting(); + } + + return builder.create(); + } + + // @formatter:off + private GsonGenerator() {} + // @formatter:on +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/SleepIQImpl.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/SleepIQImpl.java new file mode 100644 index 0000000000000..666eb93388d92 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/SleepIQImpl.java @@ -0,0 +1,254 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.impl; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.openhab.binding.sleepiq.api.BedNotFoundException; +import org.openhab.binding.sleepiq.api.Configuration; +import org.openhab.binding.sleepiq.api.LoginException; +import org.openhab.binding.sleepiq.api.SleepIQ; +import org.openhab.binding.sleepiq.api.UnauthorizedException; +import org.openhab.binding.sleepiq.api.filter.LoggingFilter; +import org.openhab.binding.sleepiq.api.model.Bed; +import org.openhab.binding.sleepiq.api.model.BedsResponse; +import org.openhab.binding.sleepiq.api.model.Failure; +import org.openhab.binding.sleepiq.api.model.FamilyStatus; +import org.openhab.binding.sleepiq.api.model.LoginInfo; +import org.openhab.binding.sleepiq.api.model.LoginRequest; +import org.openhab.binding.sleepiq.api.model.PauseMode; +import org.openhab.binding.sleepiq.api.model.Sleeper; +import org.openhab.binding.sleepiq.api.model.SleepersResponse; +import org.openhab.binding.sleepiq.internal.GsonProvider; + +public class SleepIQImpl extends AbstractClient implements SleepIQ +{ + protected static final String PARAM_KEY = "_k"; + + protected static final String DATA_BED_ID = "bedId"; + + protected final Configuration config; + + private volatile LoginInfo loginInfo; + + public SleepIQImpl(Configuration config) + { + this.config = config; + } + + @Override + public LoginInfo login() throws LoginException + { + if (loginInfo == null) + { + synchronized (this) + { + if (loginInfo == null) + { + Response response = getClient().target(config.getBaseUri()) + .path(Endpoints.login()) + .request(MediaType.APPLICATION_JSON_TYPE) + .put(Entity.json(new LoginRequest().withLogin(config.getUsername()) + .withPassword(config.getPassword()))); + + if (isUnauthorized(response)) + { + throw new UnauthorizedException(response.readEntity(Failure.class)); + } + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) + { + throw new LoginException(response.readEntity(Failure.class)); + } + + // add the received cookies to all future requests + getClient().register(new ClientRequestFilter() + { + @Override + public void filter(ClientRequestContext requestContext) throws IOException + { + List cookies = response.getCookies() + .values() + .stream() + .map(newCookie -> newCookie.toCookie()) + .collect(Collectors.toList()); + requestContext.getHeaders().put("Cookie", cookies); + } + }); + + loginInfo = response.readEntity(LoginInfo.class); + } + } + } + + return loginInfo; + } + + @Override + public List getBeds() + { + return getSessionResponse(this::getBedsResponse).readEntity(BedsResponse.class).getBeds(); + } + + protected Response getBedsResponse(Map data) throws LoginException + { + LoginInfo login = login(); + return getClient().target(config.getBaseUri()) + .path(Endpoints.bed()) + .queryParam(PARAM_KEY, login.getKey()) + .request(MediaType.APPLICATION_JSON_TYPE) + .get(); + } + + @Override + public List getSleepers() + { + return getSessionResponse(this::getSleepersResponse).readEntity(SleepersResponse.class) + .getSleepers(); + } + + protected Response getSleepersResponse(Map data) throws LoginException + { + LoginInfo login = login(); + return getClient().target(config.getBaseUri()) + .path(Endpoints.sleeper()) + .queryParam(PARAM_KEY, login.getKey()) + .request(MediaType.APPLICATION_JSON_TYPE) + .get(); + } + + @Override + public FamilyStatus getFamilyStatus() + { + return getSessionResponse(this::getFamilyStatusResponse).readEntity(FamilyStatus.class); + } + + protected Response getFamilyStatusResponse(Map data) throws LoginException + { + LoginInfo login = login(); + return getClient().target(config.getBaseUri()) + .path(Endpoints.bed()) + .path(Endpoints.familyStatus()) + .queryParam(PARAM_KEY, login.getKey()) + .request(MediaType.APPLICATION_JSON_TYPE) + .get(); + } + + @Override + public PauseMode getPauseMode(String bedId) throws BedNotFoundException + { + Map data = new HashMap<>(); + data.put(DATA_BED_ID, bedId); + + Response response = getSessionResponse(this::getPauseModeResponse, data); + + if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) + { + throw new BedNotFoundException(response.readEntity(Failure.class)); + } + + return response.readEntity(PauseMode.class); + } + + protected Response getPauseModeResponse(Map data) throws LoginException + { + LoginInfo login = login(); + return getClient().target(config.getBaseUri()) + .path(Endpoints.bed()) + .path(data.get(DATA_BED_ID).toString()) + .path(Endpoints.pauseMode()) + .queryParam(PARAM_KEY, login.getKey()) + .request(MediaType.APPLICATION_JSON_TYPE) + .get(); + } + + protected boolean isUnauthorized(Response response) + { + return Status.UNAUTHORIZED.getStatusCode() == response.getStatusInfo().getStatusCode(); + } + + protected synchronized void resetLogin() + { + loginInfo = null; + } + + protected Response getSessionResponse(Request request) + { + return getSessionResponse(request, Collections.emptyMap()); + } + + protected Response getSessionResponse(Request request, Map data) + { + try + { + Response response = request.execute(data); + + if (isUnauthorized(response)) + { + // session timed out + response.close(); + resetLogin(); + response = request.execute(data); + } + + return response; + } + catch (LoginException e) + { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + protected Client createClient() + { + ClientBuilder builder = ClientBuilder.newBuilder(); + + // setup Gson (de)serialization + GsonProvider gsonProvider = new GsonProvider<>(getGson()); + builder.register(gsonProvider); + + // turn on logging if requested + if (config.isLogging()) + { + builder.register(new LoggingFilter(Logger.getLogger(SleepIQImpl.class.getName()), + true)); + } + + return builder.build(); + } + + @FunctionalInterface + public static interface Request + { + public Response execute(Map data) throws LoginException; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DateTimeTypeAdapter.java new file mode 100644 index 0000000000000..e148736f36537 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DateTimeTypeAdapter.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.util.function.Function; + +/** + * Abstract type adapter for jsr310 date-time types. + * + * @author Christophe Bornet + */ +abstract class DateTimeTypeAdapter extends TemporalTypeAdapter { + + DateTimeTypeAdapter(Function parseFunction) { + super(parseFunction); + } + + @Override + public String preProcess(String in) { + if (in.endsWith("+0000")) { + return in.substring(0, in.length()-5) + "Z"; + } + return in; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DurationTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DurationTypeAdapter.java new file mode 100644 index 0000000000000..7651064f6a66a --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DurationTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.Duration; + +/** + * Type adapter for jsr310 {@link Duration} class. + * + * @author Christophe Bornet + */ +public class DurationTypeAdapter extends TemporalTypeAdapter { + + public DurationTypeAdapter() { + super(Duration::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/InstantTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/InstantTypeAdapter.java new file mode 100644 index 0000000000000..5f4b4f4d0c377 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/InstantTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.Instant; + +/** + * Type adapter for jsr310 {@link Instant} class. + * + * @author Christophe Bornet + */ +public class InstantTypeAdapter extends DateTimeTypeAdapter { + + public InstantTypeAdapter() { + super(Instant::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/JSR310TypeAdapters.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/JSR310TypeAdapters.java new file mode 100644 index 0000000000000..4de838cf870c1 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/JSR310TypeAdapters.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import com.google.gson.GsonBuilder; + +import java.time.*; + +/** + * Helper methods to register JSR310 type adapters. + * + * @author Christophe Bornet + */ +public class JSR310TypeAdapters { + + private JSR310TypeAdapters() { + } + + public static GsonBuilder registerDurationTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(Duration.class, new DurationTypeAdapter()); + } + + public static GsonBuilder registerInstantTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(Instant.class, new InstantTypeAdapter()); + } + + public static GsonBuilder registerLocalDateTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter()); + } + + public static GsonBuilder registerLocalDateTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()); + } + + public static GsonBuilder registerLocalTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(LocalTime.class, new LocalTimeTypeAdapter()); + } + + public static GsonBuilder registerMonthDayTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(MonthDay.class, new MonthDayTypeAdapter()); + } + + public static GsonBuilder registerOffsetDateTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()); + } + + public static GsonBuilder registerOffsetTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(OffsetTime.class, new OffsetTimeTypeAdapter()); + } + + public static GsonBuilder registerPeriodTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(Period.class, new PeriodTypeAdapter()); + } + + public static GsonBuilder registerYearMonthTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(YearMonth.class, new YearMonthTypeAdapter()); + } + + public static GsonBuilder registerYearTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(Year.class, new YearTypeAdapter()); + } + + public static GsonBuilder registerZonedDateTimeTypeAdapter(GsonBuilder gsonBuilder) { + return gsonBuilder.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeTypeAdapter()); + } + + + /** + * Helper method to register all the available JSR310 adapters at once. + * @param gsonBuilder the gsonBuilder on which all the JSR310 adapters must be registered. + * @return the gsonBuilder with the JSR310 adapters registered. + */ + public static GsonBuilder registerJSR310TypeAdapters(GsonBuilder gsonBuilder) { + registerDurationTypeAdapter(gsonBuilder); + registerInstantTypeAdapter(gsonBuilder); + registerLocalDateTimeTypeAdapter(gsonBuilder); + registerLocalDateTypeAdapter(gsonBuilder); + registerLocalTimeTypeAdapter(gsonBuilder); + registerMonthDayTypeAdapter(gsonBuilder); + registerOffsetDateTimeTypeAdapter(gsonBuilder); + registerOffsetTimeTypeAdapter(gsonBuilder); + registerPeriodTypeAdapter(gsonBuilder); + registerYearMonthTypeAdapter(gsonBuilder); + registerYearTypeAdapter(gsonBuilder); + registerZonedDateTimeTypeAdapter(gsonBuilder); + + return gsonBuilder; + } + + +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTimeTypeAdapter.java new file mode 100644 index 0000000000000..10360c9ae6373 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTimeTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.LocalDateTime; + +/** + * Type adapter for jsr310 {@link LocalDateTime} class. + * + * @author Christophe Bornet + */ +public class LocalDateTimeTypeAdapter extends DateTimeTypeAdapter { + + public LocalDateTimeTypeAdapter() { + super(LocalDateTime::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTypeAdapter.java new file mode 100644 index 0000000000000..3ac2762dbad0e --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.LocalDate; + +/** + * Type adapter for jsr310 {@link LocalDate} class. + * + * @author Christophe Bornet + */ +public class LocalDateTypeAdapter extends TemporalTypeAdapter { + + public LocalDateTypeAdapter() { + super(LocalDate::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalTimeTypeAdapter.java new file mode 100644 index 0000000000000..15210c1ebae9e --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalTimeTypeAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; + +/** + * Type adapter for jsr310 {@link LocalTime} class. + * + * @author Christophe Bornet + */ +public class LocalTimeTypeAdapter extends TemporalTypeAdapter { + + public LocalTimeTypeAdapter() { + super(LocalTime::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/MonthDayTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/MonthDayTypeAdapter.java new file mode 100644 index 0000000000000..5a1ab7fe71aa8 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/MonthDayTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.MonthDay; + +/** + * Type adapter for jsr310 {@link MonthDay} class. + * + * @author Christophe Bornet + */ +public class MonthDayTypeAdapter extends TemporalTypeAdapter { + + public MonthDayTypeAdapter() { + super(MonthDay::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetDateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetDateTimeTypeAdapter.java new file mode 100644 index 0000000000000..7272f675096b5 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetDateTimeTypeAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Type adapter for jsr310 {@link OffsetDateTime} class. + * + * @author Christophe Bornet + */ +public class OffsetDateTimeTypeAdapter extends DateTimeTypeAdapter { + + public OffsetDateTimeTypeAdapter() { + super(OffsetDateTime::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetTimeTypeAdapter.java new file mode 100644 index 0000000000000..cba1326e8517c --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetTimeTypeAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.OffsetTime; +import java.time.format.DateTimeFormatter; + +/** + * Type adapter for jsr310 {@link OffsetTime} class. + * + * @author Christophe Bornet + */ +public class OffsetTimeTypeAdapter extends TemporalTypeAdapter { + + public OffsetTimeTypeAdapter() { + super(OffsetTime::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/PeriodTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/PeriodTypeAdapter.java new file mode 100644 index 0000000000000..74ade1885ab86 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/PeriodTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.Period; + +/** + * Type adapter for jsr310 {@link Period} class. + * + * @author Christophe Bornet + */ +public class PeriodTypeAdapter extends TemporalTypeAdapter { + + public PeriodTypeAdapter() { + super(Period::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java new file mode 100644 index 0000000000000..c241e090944a8 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.time.temporal.TemporalAccessor; +import java.util.Objects; +import java.util.function.Function; + +/** + * Abstract type adapter for jsr310 date-time types. + * + * @author Christophe Bornet + */ +abstract class TemporalTypeAdapter extends TypeAdapter { + + Function parseFunction; + + TemporalTypeAdapter(Function parseFunction) { + Objects.requireNonNull(parseFunction); + this.parseFunction = parseFunction; + } + + @Override + public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(value.toString()); + } + } + + @Override + public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + String temporalString = preProcess(in.nextString()); + return parseFunction.apply(temporalString); + } + + public String preProcess(String in) { + return in; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java new file mode 100644 index 0000000000000..3504e1bfba468 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java @@ -0,0 +1,26 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import org.openhab.binding.sleepiq.api.model.TimeSince; + +public class TimeSinceTypeAdapter extends TemporalTypeAdapter +{ + public TimeSinceTypeAdapter() + { + super(TimeSince::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearMonthTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearMonthTypeAdapter.java new file mode 100644 index 0000000000000..5fe0a6e97a384 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearMonthTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.YearMonth; + +/** + * Type adapter for jsr310 {@link YearMonth} class. + * + * @author Christophe Bornet + */ +public class YearMonthTypeAdapter extends TemporalTypeAdapter { + + public YearMonthTypeAdapter() { + super(YearMonth::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearTypeAdapter.java new file mode 100644 index 0000000000000..37f2153a1e99d --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearTypeAdapter.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.Year; + +/** + * Type adapter for jsr310 {@link Year} class. + * + * @author Christophe Bornet + */ +public class YearTypeAdapter extends TemporalTypeAdapter { + + public YearTypeAdapter() { + super(Year::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java new file mode 100644 index 0000000000000..53402b560f49a --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Gson Type Adapter Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src + * and repackaged to avoid the default package. + */ +package org.openhab.binding.sleepiq.api.impl.typeadapters; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +/** + * Type adapter for jsr310 {@link ZonedDateTime} class. + * + * @author Christophe Bornet + */ +public class ZonedDateTimeTypeAdapter extends DateTimeTypeAdapter { + + public ZonedDateTimeTypeAdapter() { + super(ZonedDateTime::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java new file mode 100644 index 0000000000000..6bfa86db0ecaa --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java @@ -0,0 +1,472 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import java.time.ZonedDateTime; + +import com.google.gson.annotations.SerializedName; + +public class Bed +{ + private ZonedDateTime registrationDate; + private String sleeperRightId; + private String base; + private Long returnRequestStatus; + private String size; + private String name; + private String serial; + @SerializedName("isKidsBed") + private Boolean kidsBed; + private Boolean dualSleep; + private String bedId; + private Long status; + private String sleeperLeftId; + private String version; + private String accountId; + private String timezone; + private String model; + private ZonedDateTime purchaseDate; + private String macAddress; + private String sku; + @SerializedName("zipcode") + private String zipCode; + private String reference; + + public ZonedDateTime getRegistrationDate() + { + return registrationDate; + } + + public void setRegistrationDate(ZonedDateTime registrationDate) + { + this.registrationDate = registrationDate; + } + + public Bed withRegistrationDate(ZonedDateTime registrationDate) + { + setRegistrationDate(registrationDate); + return this; + } + + public String getSleeperRightId() + { + return sleeperRightId; + } + + public void setSleeperRightId(String sleeperRightId) + { + this.sleeperRightId = sleeperRightId; + } + + public Bed withSleeperRightId(String sleeperRightId) + { + setSleeperRightId(sleeperRightId); + return this; + } + + public String getBase() + { + return base; + } + + public void setBase(String base) + { + this.base = base; + } + + public Bed withBase(String base) + { + setBase(base); + return this; + } + + public Long getReturnRequestStatus() + { + return returnRequestStatus; + } + + public void setReturnRequestStatus(Long returnRequestStatus) + { + this.returnRequestStatus = returnRequestStatus; + } + + public Bed withReturnRequestStatus(Long returnRequestStatus) + { + setReturnRequestStatus(returnRequestStatus); + return this; + } + + public String getSize() + { + return size; + } + + public void setSize(String size) + { + this.size = size; + } + + public Bed withSize(String size) + { + setSize(size); + return this; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public Bed withName(String name) + { + setName(name); + return this; + } + + public String getSerial() + { + return serial; + } + + public void setSerial(String serial) + { + this.serial = serial; + } + + public Bed withSerial(String serial) + { + setSerial(serial); + return this; + } + + public Boolean isKidsBed() + { + return kidsBed; + } + + public void setKidsBed(Boolean kidsBed) + { + this.kidsBed = kidsBed; + } + + public Bed withKidsBed(Boolean kidsBed) + { + setKidsBed(kidsBed); + return this; + } + + public Boolean isDualSleep() + { + return dualSleep; + } + + public void setDualSleep(Boolean dualSleep) + { + this.dualSleep = dualSleep; + } + + public Bed withDualSleep(Boolean dualSleep) + { + setDualSleep(dualSleep); + return this; + } + + public String getBedId() + { + return bedId; + } + + public void setBedId(String bedId) + { + this.bedId = bedId; + } + + public Bed withBedId(String bedId) + { + setBedId(bedId); + return this; + } + + public Long getStatus() + { + return status; + } + + public void setStatus(Long status) + { + this.status = status; + } + + public Bed withStatus(Long status) + { + setStatus(status); + return this; + } + + public String getSleeperLeftId() + { + return sleeperLeftId; + } + + public void setSleeperLeftId(String sleeperLeftId) + { + this.sleeperLeftId = sleeperLeftId; + } + + public Bed withSleeperLeftId(String sleeperLeftId) + { + setSleeperLeftId(sleeperLeftId); + return this; + } + + public String getVersion() + { + return version; + } + + public void setVersion(String version) + { + this.version = version; + } + + public Bed withVersion(String version) + { + setVersion(version); + return this; + } + + public String getAccountId() + { + return accountId; + } + + public void setAccountId(String accountId) + { + this.accountId = accountId; + } + + public Bed withAccountId(String accountId) + { + setAccountId(accountId); + return this; + } + + public String getTimezone() + { + return timezone; + } + + public void setTimezone(String timezone) + { + this.timezone = timezone; + } + + public Bed withTimezone(String timezone) + { + setTimezone(timezone); + return this; + } + + public String getModel() + { + return model; + } + + public void setModel(String model) + { + this.model = model; + } + + public Bed withModel(String model) + { + setModel(model); + return this; + } + + public ZonedDateTime getPurchaseDate() + { + return purchaseDate; + } + + public void setPurchaseDate(ZonedDateTime purchaseDate) + { + this.purchaseDate = purchaseDate; + } + + public Bed withPurchaseDate(ZonedDateTime purchaseDate) + { + setPurchaseDate(purchaseDate); + return this; + } + + public String getMacAddress() + { + return macAddress; + } + + public void setMacAddress(String macAddress) + { + this.macAddress = macAddress; + } + + public Bed withMacAddress(String macAddress) + { + setMacAddress(macAddress); + return this; + } + + public String getSku() + { + return sku; + } + + public void setSku(String sku) + { + this.sku = sku; + } + + public Bed withSku(String sku) + { + setSku(sku); + return this; + } + + public String getZipCode() + { + return zipCode; + } + + public void setZipCode(String zipCode) + { + this.zipCode = zipCode; + } + + public Bed withZipCode(String zipCode) + { + setZipCode(zipCode); + return this; + } + + public String getReference() + { + return reference; + } + + public void setReference(String reference) + { + this.reference = reference; + } + + public Bed withReference(String reference) + { + setReference(reference); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof Bed)) + { + return false; + } + Bed other = (Bed)obj; + if (bedId == null) + { + if (other.bedId != null) + { + return false; + } + } + else if (!bedId.equals(other.bedId)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Bed [registrationDate="); + builder.append(registrationDate); + builder.append(", sleeperRightId="); + builder.append(sleeperRightId); + builder.append(", base="); + builder.append(base); + builder.append(", returnRequestStatus="); + builder.append(returnRequestStatus); + builder.append(", size="); + builder.append(size); + builder.append(", name="); + builder.append(name); + builder.append(", serial="); + builder.append(serial); + builder.append(", kidsBed="); + builder.append(kidsBed); + builder.append(", dualSleep="); + builder.append(dualSleep); + builder.append(", bedId="); + builder.append(bedId); + builder.append(", status="); + builder.append(status); + builder.append(", sleeperLeftId="); + builder.append(sleeperLeftId); + builder.append(", version="); + builder.append(version); + builder.append(", accountId="); + builder.append(accountId); + builder.append(", timezone="); + builder.append(timezone); + builder.append(", model="); + builder.append(model); + builder.append(", purchaseDate="); + builder.append(purchaseDate); + builder.append(", macAddress="); + builder.append(macAddress); + builder.append(", sku="); + builder.append(sku); + builder.append(", zipCode="); + builder.append(zipCode); + builder.append(", reference="); + builder.append(reference); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java new file mode 100644 index 0000000000000..b7e994b2bd6bb --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java @@ -0,0 +1,245 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import com.google.gson.annotations.SerializedName; + +public class BedSideStatus +{ + @SerializedName("isInBed") + private Boolean inBed; + private String alertDetailedMessage; + private Integer sleepNumber; + private Long alertId; + private TimeSince lastLink; + private Integer pressure; // appears to be in kPa + + public Boolean isInBed() + { + return inBed; + } + + public void setInBed(Boolean inBed) + { + this.inBed = inBed; + } + + public BedSideStatus withInBed(Boolean inBed) + { + setInBed(inBed); + return this; + } + + public String getAlertDetailedMessage() + { + return alertDetailedMessage; + } + + public void setAlertDetailedMessage(String alertDetailedMessage) + { + this.alertDetailedMessage = alertDetailedMessage; + } + + public BedSideStatus withAlertDetailedMessage(String alertDetailedMessage) + { + setAlertDetailedMessage(alertDetailedMessage); + return this; + } + + public Integer getSleepNumber() + { + return sleepNumber; + } + + public void setSleepNumber(Integer sleepNumber) + { + this.sleepNumber = sleepNumber; + } + + public BedSideStatus withSleepNumber(Integer sleepNumber) + { + setSleepNumber(sleepNumber); + return this; + } + + public Long getAlertId() + { + return alertId; + } + + public void setAlertId(Long alertId) + { + this.alertId = alertId; + } + + public BedSideStatus withAlertId(Long alertId) + { + setAlertId(alertId); + return this; + } + + public TimeSince getLastLink() + { + return lastLink; + } + + public void setLastLink(TimeSince lastLink) + { + this.lastLink = lastLink; + } + + public BedSideStatus withLastLink(TimeSince lastLink) + { + setLastLink(lastLink); + return this; + } + + public Integer getPressure() + { + return pressure; + } + + public void setPressure(Integer pressure) + { + this.pressure = pressure; + } + + public BedSideStatus withPressure(Integer pressure) + { + setPressure(pressure); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + + ((alertDetailedMessage == null) ? 0 : alertDetailedMessage.hashCode()); + result = prime * result + ((alertId == null) ? 0 : alertId.hashCode()); + result = prime * result + ((inBed == null) ? 0 : inBed.hashCode()); + result = prime * result + ((lastLink == null) ? 0 : lastLink.hashCode()); + result = prime * result + ((pressure == null) ? 0 : pressure.hashCode()); + result = prime * result + ((sleepNumber == null) ? 0 : sleepNumber.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof BedSideStatus)) + { + return false; + } + BedSideStatus other = (BedSideStatus)obj; + if (alertDetailedMessage == null) + { + if (other.alertDetailedMessage != null) + { + return false; + } + } + else if (!alertDetailedMessage.equals(other.alertDetailedMessage)) + { + return false; + } + if (alertId == null) + { + if (other.alertId != null) + { + return false; + } + } + else if (!alertId.equals(other.alertId)) + { + return false; + } + if (inBed == null) + { + if (other.inBed != null) + { + return false; + } + } + else if (!inBed.equals(other.inBed)) + { + return false; + } + if (lastLink == null) + { + if (other.lastLink != null) + { + return false; + } + } + else if (!lastLink.equals(other.lastLink)) + { + return false; + } + if (pressure == null) + { + if (other.pressure != null) + { + return false; + } + } + else if (!pressure.equals(other.pressure)) + { + return false; + } + if (sleepNumber == null) + { + if (other.sleepNumber != null) + { + return false; + } + } + else if (!sleepNumber.equals(other.sleepNumber)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BedSideStatus [inBed="); + builder.append(inBed); + builder.append(", alertDetailedMessage="); + builder.append(alertDetailedMessage); + builder.append(", sleepNumber="); + builder.append(sleepNumber); + builder.append(", alertId="); + builder.append(alertId); + builder.append(", lastLink="); + builder.append(lastLink); + builder.append(", pressure="); + builder.append(pressure); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java new file mode 100644 index 0000000000000..c07fbd8d88ef8 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java @@ -0,0 +1,143 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +public class BedStatus +{ + private Long status; + private String bedId; + private BedSideStatus leftSide; + private BedSideStatus rightSide; + + public Long getStatus() + { + return status; + } + + public void setStatus(Long status) + { + this.status = status; + } + + public BedStatus withStatus(Long status) + { + setStatus(status); + return this; + } + + public String getBedId() + { + return bedId; + } + + public void setBedId(String bedId) + { + this.bedId = bedId; + } + + public BedStatus withBedId(String bedId) + { + setBedId(bedId); + return this; + } + + public BedSideStatus getLeftSide() + { + return leftSide; + } + + public void setLeftSide(BedSideStatus leftSide) + { + this.leftSide = leftSide; + } + + public BedStatus withLeftSide(BedSideStatus leftSide) + { + setLeftSide(leftSide); + return this; + } + + public BedSideStatus getRightSide() + { + return rightSide; + } + + public void setRightSide(BedSideStatus rightSide) + { + this.rightSide = rightSide; + } + + public BedStatus withRightSide(BedSideStatus rightSide) + { + setRightSide(rightSide); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof BedStatus)) + { + return false; + } + BedStatus other = (BedStatus)obj; + if (bedId == null) + { + if (other.bedId != null) + { + return false; + } + } + else if (!bedId.equals(other.bedId)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BedStatus [status="); + builder.append(status); + builder.append(", bedId="); + builder.append(bedId); + builder.append(", leftSide="); + builder.append(leftSide); + builder.append(", rightSide="); + builder.append(rightSide); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedsResponse.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedsResponse.java new file mode 100644 index 0000000000000..3b3deeea0c7f5 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedsResponse.java @@ -0,0 +1,88 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import java.util.List; + +public class BedsResponse +{ + private List beds; + + public List getBeds() + { + return beds; + } + + public void setBeds(List beds) + { + this.beds = beds; + } + + public BedsResponse withBeds(List beds) + { + setBeds(beds); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((beds == null) ? 0 : beds.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof BedsResponse)) + { + return false; + } + BedsResponse other = (BedsResponse)obj; + if (beds == null) + { + if (other.beds != null) + { + return false; + } + } + else if (!beds.equals(other.beds)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("BedsResponse [beds="); + builder.append(beds); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Error.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Error.java new file mode 100644 index 0000000000000..5593b59fe42d1 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Error.java @@ -0,0 +1,109 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import com.google.gson.annotations.SerializedName; + +public class Error +{ + @SerializedName("Code") + private Long code; + @SerializedName("Message") + private String message; + + public Long getCode() + { + return code; + } + + public void setCode(Long code) + { + this.code = code; + } + + public Error withCode(Long code) + { + setCode(code); + return this; + } + + public String getMessage() + { + return message; + } + + public void setMessage(String message) + { + this.message = message; + } + + public Error withMessage(String message) + { + setMessage(message); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((code == null) ? 0 : code.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof Error)) + { + return false; + } + Error other = (Error)obj; + if (code == null) + { + if (other.code != null) + { + return false; + } + } + else if (!code.equals(other.code)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Error [code="); + builder.append(code); + builder.append(", message="); + builder.append(message); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Failure.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Failure.java new file mode 100644 index 0000000000000..4ab0481e8a4ac --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Failure.java @@ -0,0 +1,89 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import com.google.gson.annotations.SerializedName; + +public class Failure +{ + @SerializedName("Error") + private Error error; + + public Error getError() + { + return error; + } + + public void setError(Error error) + { + this.error = error; + } + + public Failure withError(Error error) + { + setError(error); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((error == null) ? 0 : error.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof Failure)) + { + return false; + } + Failure other = (Failure)obj; + if (error == null) + { + if (other.error != null) + { + return false; + } + } + else if (!error.equals(other.error)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Failure [error="); + builder.append(error); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/FamilyStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/FamilyStatus.java new file mode 100644 index 0000000000000..cddea5a606fae --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/FamilyStatus.java @@ -0,0 +1,88 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import java.util.List; + +public class FamilyStatus +{ + private List beds; + + public List getBeds() + { + return beds; + } + + public void setBeds(List beds) + { + this.beds = beds; + } + + public FamilyStatus withBeds(List beds) + { + setBeds(beds); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((beds == null) ? 0 : beds.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof FamilyStatus)) + { + return false; + } + FamilyStatus other = (FamilyStatus)obj; + if (beds == null) + { + if (other.beds != null) + { + return false; + } + } + else if (!beds.equals(other.beds)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("FamilyStatus [beds="); + builder.append(beds); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java new file mode 100644 index 0000000000000..7cc35096fb6e0 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java @@ -0,0 +1,179 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +public class LoginInfo +{ + private String userId; + private String key; + private Long registrationState; + private Long edpLoginStatus; + private String edpLoginMessage; + + public String getUserId() + { + return userId; + } + + public void setUserId(String userId) + { + this.userId = userId; + } + + public LoginInfo withUserId(String userId) + { + setUserId(userId); + return this; + } + + public String getKey() + { + return key; + } + + public void setKey(String key) + { + this.key = key; + } + + public LoginInfo withKey(String key) + { + setKey(key); + return this; + } + + public Long getRegistrationState() + { + return registrationState; + } + + public void setRegistrationState(Long registrationState) + { + this.registrationState = registrationState; + } + + public LoginInfo withRegistrationState(Long registrationState) + { + setRegistrationState(registrationState); + return this; + } + + public Long getEdpLoginStatus() + { + return edpLoginStatus; + } + + public void setEdpLoginStatus(Long edpLoginStatus) + { + this.edpLoginStatus = edpLoginStatus; + } + + public LoginInfo withEdpLoginStatus(Long edpLoginStatus) + { + setEdpLoginStatus(edpLoginStatus); + return this; + } + + public String getEdpLoginMessage() + { + return edpLoginMessage; + } + + public void setEdpLoginMessage(String edpLoginMessage) + { + this.edpLoginMessage = edpLoginMessage; + } + + public LoginInfo withEdpLoginMessage(String edpLoginMessage) + { + setEdpLoginMessage(edpLoginMessage); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + (int)(registrationState ^ (registrationState >>> 32)); + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof LoginInfo)) + { + return false; + } + LoginInfo other = (LoginInfo)obj; + if (key == null) + { + if (other.key != null) + { + return false; + } + } + else if (!key.equals(other.key)) + { + return false; + } + if (!registrationState.equals(other.registrationState)) + { + return false; + } + if (userId == null) + { + if (other.userId != null) + { + return false; + } + } + else if (!userId.equals(other.userId)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("LoginInfo [userId="); + builder.append(userId); + builder.append(", key="); + builder.append(key); + builder.append(", registrationState="); + builder.append(registrationState); + builder.append(", edpLoginStatus="); + builder.append(edpLoginStatus); + builder.append(", edpLoginMessage="); + builder.append(edpLoginMessage); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java new file mode 100644 index 0000000000000..07835f054ebe9 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java @@ -0,0 +1,117 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +public class LoginRequest +{ + private String login; + private String password; + + public String getLogin() + { + return login; + } + + public void setLogin(String login) + { + this.login = login; + } + + public LoginRequest withLogin(String login) + { + setLogin(login); + return this; + } + + public String getPassword() + { + return password; + } + + public void setPassword(String password) + { + this.password = password; + } + + public LoginRequest withPassword(String password) + { + setPassword(password); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((login == null) ? 0 : login.hashCode()); + result = prime * result + ((password == null) ? 0 : password.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof LoginRequest)) + { + return false; + } + LoginRequest other = (LoginRequest)obj; + if (login == null) + { + if (other.login != null) + { + return false; + } + } + else if (!login.equals(other.login)) + { + return false; + } + if (password == null) + { + if (other.password != null) + { + return false; + } + } + else if (!password.equals(other.password)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("LoginRequest [login="); + builder.append(login); + builder.append(", password="); + builder.append(password); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/PauseMode.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/PauseMode.java new file mode 100644 index 0000000000000..56278864655a9 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/PauseMode.java @@ -0,0 +1,136 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +public class PauseMode +{ + private String accountId; + private String bedId; + private String pauseMode; + + public String getAccountId() + { + return accountId; + } + + public void setAccountId(String accountId) + { + this.accountId = accountId; + } + + public PauseMode withAccountId(String accountId) + { + setAccountId(accountId); + return this; + } + + public String getBedId() + { + return bedId; + } + + public void setBedId(String bedId) + { + this.bedId = bedId; + } + + public PauseMode withBedId(String bedId) + { + setBedId(bedId); + return this; + } + + public String getPauseMode() + { + return pauseMode; + } + + public void setPauseMode(String pauseMode) + { + this.pauseMode = pauseMode; + } + + public PauseMode withPauseMode(String pauseMode) + { + setPauseMode(pauseMode); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((accountId == null) ? 0 : accountId.hashCode()); + result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof PauseMode)) + { + return false; + } + PauseMode other = (PauseMode)obj; + if (accountId == null) + { + if (other.accountId != null) + { + return false; + } + } + else if (!accountId.equals(other.accountId)) + { + return false; + } + if (bedId == null) + { + if (other.bedId != null) + { + return false; + } + } + else if (!bedId.equals(other.bedId)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("PauseMode [accountId="); + builder.append(accountId); + builder.append(", bedId="); + builder.append(bedId); + builder.append(", pauseMode="); + builder.append(pauseMode); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java new file mode 100644 index 0000000000000..8a9ff0adfce52 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java @@ -0,0 +1,509 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import com.google.gson.annotations.SerializedName; + +public class Sleeper +{ + private String firstName; + private Boolean active; + private Boolean emailValidated; + @SerializedName("isChild") + private Boolean child; + private String bedId; + private String birthYear; + private String zipCode; + private String timezone; + @SerializedName("isMale") + private Boolean male; + private Integer weight; // lbs + private String duration; + private String sleeperId; + private Integer height; // inches + private Long licenseVersion; + private String username; + private Integer birthMonth; // 0-based; 12 means not entered? + private Integer sleepGoal; + @SerializedName("isAccountOwner") + private Boolean accountOwner; + private String accountId; + private String email; + private String avatar; + private String lastLogin; // should be ZonedDateTime but provider passes string "null" when missing + private Integer side; // 0=left; 1=right + + public String getFirstName() + { + return firstName; + } + + public void setFirstName(String firstName) + { + this.firstName = firstName; + } + + public Sleeper withFirstName(String firstName) + { + setFirstName(firstName); + return this; + } + + public Boolean isActive() + { + return active; + } + + public void setActive(Boolean active) + { + this.active = active; + } + + public Sleeper withActive(Boolean active) + { + setActive(active); + return this; + } + + public Boolean isEmailValidated() + { + return emailValidated; + } + + public void setEmailValidated(Boolean emailValidated) + { + this.emailValidated = emailValidated; + } + + public Sleeper withEmailValidated(Boolean emailValidated) + { + setEmailValidated(emailValidated); + return this; + } + + public Boolean isChild() + { + return child; + } + + public void setChild(Boolean child) + { + this.child = child; + } + + public Sleeper withChild(Boolean child) + { + setChild(child); + return this; + } + + public String getBedId() + { + return bedId; + } + + public void setBedId(String bedId) + { + this.bedId = bedId; + } + + public Sleeper withBedId(String bedId) + { + setBedId(bedId); + return this; + } + + public String getBirthYear() + { + return birthYear; + } + + public void setBirthYear(String birthYear) + { + this.birthYear = birthYear; + } + + public Sleeper withBirthYear(String birthYear) + { + setBirthYear(birthYear); + return this; + } + + public String getZipCode() + { + return zipCode; + } + + public void setZipCode(String zipCode) + { + this.zipCode = zipCode; + } + + public Sleeper withZipCode(String zipCode) + { + setZipCode(zipCode); + return this; + } + + public String getTimezone() + { + return timezone; + } + + public void setTimezone(String timezone) + { + this.timezone = timezone; + } + + public Sleeper withTimezone(String timezone) + { + setTimezone(timezone); + return this; + } + + public Boolean isMale() + { + return male; + } + + public void setMale(Boolean male) + { + this.male = male; + } + + public Sleeper withMale(Boolean male) + { + setMale(male); + return this; + } + + public Integer getWeight() + { + return weight; + } + + public void setWeight(Integer weight) + { + this.weight = weight; + } + + public Sleeper withWeight(Integer weight) + { + setWeight(weight); + return this; + } + + public String getDuration() + { + return duration; + } + + public void setDuration(String duration) + { + this.duration = duration; + } + + public Sleeper withDuration(String duration) + { + setDuration(duration); + return this; + } + + public String getSleeperId() + { + return sleeperId; + } + + public void setSleeperId(String sleeperId) + { + this.sleeperId = sleeperId; + } + + public Sleeper withSleeperId(String sleeperId) + { + setSleeperId(sleeperId); + return this; + } + + public Integer getHeight() + { + return height; + } + + public void setHeight(Integer height) + { + this.height = height; + } + + public Sleeper withHeight(Integer height) + { + setHeight(height); + return this; + } + + public Long getLicenseVersion() + { + return licenseVersion; + } + + public void setLicenseVersion(Long licenseVersion) + { + this.licenseVersion = licenseVersion; + } + + public Sleeper withLicenseVersion(Long licenseVersion) + { + setLicenseVersion(licenseVersion); + return this; + } + + public String getUsername() + { + return username; + } + + public void setUsername(String username) + { + this.username = username; + } + + public Sleeper withUsername(String username) + { + setUsername(username); + return this; + } + + public Integer getBirthMonth() + { + return birthMonth; + } + + public void setBirthMonth(Integer birthMonth) + { + this.birthMonth = birthMonth; + } + + public Sleeper withBirthMonth(Integer birthMonth) + { + setBirthMonth(birthMonth); + return this; + } + + public Integer getSleepGoal() + { + return sleepGoal; + } + + public void setSleepGoal(Integer sleepGoal) + { + this.sleepGoal = sleepGoal; + } + + public Sleeper withSleepGoal(Integer sleepGoal) + { + setSleepGoal(sleepGoal); + return this; + } + + public Boolean isAccountOwner() + { + return accountOwner; + } + + public void setAccountOwner(Boolean accountOwner) + { + this.accountOwner = accountOwner; + } + + public Sleeper withAccountOwner(Boolean accountOwner) + { + setAccountOwner(accountOwner); + return this; + } + + public String getAccountId() + { + return accountId; + } + + public void setAccountId(String accountId) + { + this.accountId = accountId; + } + + public Sleeper withAccountId(String accountId) + { + setAccountId(accountId); + return this; + } + + public String getEmail() + { + return email; + } + + public void setEmail(String email) + { + this.email = email; + } + + public Sleeper withEmail(String email) + { + setEmail(email); + return this; + } + + public String getAvatar() + { + return avatar; + } + + public void setAvatar(String avatar) + { + this.avatar = avatar; + } + + public Sleeper withAvatar(String avatar) + { + setAvatar(avatar); + return this; + } + + public String getLastLogin() + { + return lastLogin; + } + + public void setLastLogin(String lastLogin) + { + this.lastLogin = lastLogin; + } + + public Sleeper withLastLogin(String lastLogin) + { + setLastLogin(lastLogin); + return this; + } + + public Integer getSide() + { + return side; + } + + public void setSide(Integer side) + { + this.side = side; + } + + public Sleeper withSide(Integer side) + { + setSide(side); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((sleeperId == null) ? 0 : sleeperId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof Sleeper)) + { + return false; + } + Sleeper other = (Sleeper)obj; + if (sleeperId == null) + { + if (other.sleeperId != null) + { + return false; + } + } + else if (!sleeperId.equals(other.sleeperId)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("Sleeper [firstName="); + builder.append(firstName); + builder.append(", active="); + builder.append(active); + builder.append(", emailValidated="); + builder.append(emailValidated); + builder.append(", child="); + builder.append(child); + builder.append(", bedId="); + builder.append(bedId); + builder.append(", birthYear="); + builder.append(birthYear); + builder.append(", zipCode="); + builder.append(zipCode); + builder.append(", timezone="); + builder.append(timezone); + builder.append(", male="); + builder.append(male); + builder.append(", weight="); + builder.append(weight); + builder.append(", duration="); + builder.append(duration); + builder.append(", sleeperId="); + builder.append(sleeperId); + builder.append(", height="); + builder.append(height); + builder.append(", licenseVersion="); + builder.append(licenseVersion); + builder.append(", username="); + builder.append(username); + builder.append(", birthMonth="); + builder.append(birthMonth); + builder.append(", sleepGoal="); + builder.append(sleepGoal); + builder.append(", accountOwner="); + builder.append(accountOwner); + builder.append(", accountId="); + builder.append(accountId); + builder.append(", email="); + builder.append(email); + builder.append(", avatar="); + builder.append(avatar); + builder.append(", lastLogin="); + builder.append(lastLogin); + builder.append(", side="); + builder.append(side); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java new file mode 100644 index 0000000000000..4c793ef1a05a9 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java @@ -0,0 +1,88 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import java.util.List; + +public class SleepersResponse +{ + private List sleepers; + + public List getSleepers() + { + return sleepers; + } + + public void setSleepers(List sleepers) + { + this.sleepers = sleepers; + } + + public SleepersResponse withSleepers(List sleepers) + { + setSleepers(sleepers); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((sleepers == null) ? 0 : sleepers.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof SleepersResponse)) + { + return false; + } + SleepersResponse other = (SleepersResponse)obj; + if (sleepers == null) + { + if (other.sleepers != null) + { + return false; + } + } + else if (!sleepers.equals(other.sleepers)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("SleepersResponse [sleepers="); + builder.append(sleepers); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java new file mode 100644 index 0000000000000..674e2ef7449d9 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java @@ -0,0 +1,145 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import java.time.Duration; +import java.time.format.DateTimeParseException; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TimeSince +{ + private static final Pattern PATTERN = Pattern.compile("(([0-9]+) d )?([0-9]{2}):([0-9]{2}):([0-9]{2})", + Pattern.CASE_INSENSITIVE); + + private Duration duration; + + public Duration getDuration() + { + return duration; + } + + public void setDuration(Duration duration) + { + this.duration = duration == null ? null : duration.abs(); + } + + public TimeSince withDuration(long days, long hours, long minutes, long seconds) + { + return withDuration(Duration.ofSeconds(TimeUnit.DAYS.toSeconds(days) + + TimeUnit.HOURS.toSeconds(hours) + + TimeUnit.MINUTES.toSeconds(minutes) + + seconds)); + } + + public TimeSince withDuration(Duration duration) + { + setDuration(duration); + return this; + } + + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + ((duration == null) ? 0 : duration.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + if (obj == null) + { + return false; + } + if (!(obj instanceof TimeSince)) + { + return false; + } + TimeSince other = (TimeSince)obj; + if (duration == null) + { + if (other.duration != null) + { + return false; + } + } + else if (!duration.equals(other.duration)) + { + return false; + } + return true; + } + + @Override + public String toString() + { + long totalDays = duration.toDays(); + long totalHours = duration.toHours(); + long totalMinutes = duration.toMinutes(); + long totalSeconds = duration.getSeconds(); + + long hours = totalHours - TimeUnit.DAYS.toHours(totalDays); + long minutes = totalMinutes - TimeUnit.HOURS.toMinutes(totalHours); + long seconds = totalSeconds - TimeUnit.MINUTES.toSeconds(totalMinutes); + + if (totalDays > 0) + { + return String.format("%d d %02d:%02d:%02d", totalDays, hours, minutes, seconds); + } + + return String.format("%02d:%02d:%02d", hours, minutes, seconds); + } + + public static TimeSince parse(CharSequence text) + { + Objects.requireNonNull(text, "text"); + + Matcher matcher = PATTERN.matcher(text); + if (!matcher.matches()) + { + throw new DateTimeParseException("Text cannot be parsed", text, 0); + } + + String dayMatch = matcher.group(2); + String hourMatch = matcher.group(3); + String minuteMatch = matcher.group(4); + String secondMatch = matcher.group(5); + + StringBuilder sb = new StringBuilder("P"); + if (dayMatch != null) + { + sb.append(dayMatch).append('D'); + } + sb.append('T') + .append(hourMatch) + .append('H') + .append(minuteMatch) + .append('M') + .append(secondMatch) + .append('S'); + + return new TimeSince().withDuration(Duration.parse(sb.toString())); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java new file mode 100644 index 0000000000000..73fe4565b5b9a --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java @@ -0,0 +1,71 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.io.FileReader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.sleepiq.api.impl.GsonGenerator; +import org.openhab.binding.sleepiq.api.model.BedSideStatus; +import org.openhab.binding.sleepiq.api.model.TimeSince; +import org.openhab.binding.sleepiq.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class BedSideStatusTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + BedSideStatus bedSideStatus = new BedSideStatus().withAlertDetailedMessage("No Alert") + .withAlertId(0L) + .withInBed(false) + .withLastLink(new TimeSince().withDuration(3, + 5, + 4, + 38)) + .withPressure(573) + .withSleepNumber(55); + assertEquals(readJson("bed-side-status.json"), gson.toJson(bedSideStatus)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("bed-side-status.json"))) + { + BedSideStatus bedSideStatus = gson.fromJson(reader, BedSideStatus.class); + assertEquals("No Alert", bedSideStatus.getAlertDetailedMessage()); + assertEquals(Long.valueOf(0L), bedSideStatus.getAlertId()); + assertFalse(bedSideStatus.isInBed()); + assertEquals(new TimeSince().withDuration(3, 5, 4, 38), bedSideStatus.getLastLink()); + assertEquals(Integer.valueOf(573), bedSideStatus.getPressure()); + assertEquals(Integer.valueOf(55), bedSideStatus.getSleepNumber()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java new file mode 100644 index 0000000000000..2a335d5f3909a --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.FileReader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.sleepiq.api.impl.GsonGenerator; +import org.openhab.binding.sleepiq.api.model.BedSideStatus; +import org.openhab.binding.sleepiq.api.model.BedStatus; +import org.openhab.binding.sleepiq.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class BedStatusTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + BedStatus bedStatus = new BedStatus().withBedId("-9999999999999999999") + .withLeftSide(new BedSideStatus().withInBed(true)) + .withRightSide(new BedSideStatus().withInBed(false)) + .withStatus(1L); + assertEquals(readJson("bed-status.json"), gson.toJson(bedStatus)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("bed-status.json"))) + { + BedStatus bedStatus = gson.fromJson(reader, BedStatus.class); + assertEquals("-9999999999999999999", bedStatus.getBedId()); + assertEquals(Long.valueOf(1L), bedStatus.getStatus()); + + BedSideStatus leftSide = bedStatus.getLeftSide(); + assertNotNull(leftSide); + assertTrue(leftSide.isInBed()); + + BedSideStatus rightSide = bedStatus.getRightSide(); + assertNotNull(rightSide); + assertFalse(rightSide.isInBed()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java new file mode 100644 index 0000000000000..386b1c3b7a85e --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.sleepiq.api.impl.GsonGenerator; +import org.openhab.binding.sleepiq.api.model.Bed; +import org.openhab.binding.sleepiq.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class BedTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + Bed bed = new Bed().withAccountId("-8888888888888888888") + .withBase("MODULAR") + .withBedId("-9999999999999999999") + .withDualSleep(true) + .withKidsBed(false) + .withMacAddress("AABBCCDDEEFF") + .withModel("P5") + .withName("Bed") + .withPurchaseDate(ZonedDateTime.of(2017, + 2, + 2, + 0, + 0, + 1, + 0, + ZoneId.of("Z").normalized())) + .withReference("55555555555-5") + .withRegistrationDate(ZonedDateTime.of(2017, + 2, + 17, + 2, + 14, + 10, + 0, + ZoneId.of("Z").normalized())) + .withReturnRequestStatus(0L) + .withSerial("") + .withSize("QUEEN") + .withSku("QP5") + .withSleeperLeftId("-2222222222222222222") + .withSleeperRightId("-1111111111111111111") + .withStatus(1L) + .withTimezone("US/Pacific") + .withVersion("") + .withZipCode("90210"); + assertEquals(readJson("bed.json"), gson.toJson(bed)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("bed.json"))) + { + Bed bed = gson.fromJson(reader, Bed.class); + assertEquals("-8888888888888888888", bed.getAccountId()); + assertEquals("MODULAR", bed.getBase()); + assertEquals("-9999999999999999999", bed.getBedId()); + assertEquals(true, bed.isDualSleep()); + assertEquals(false, bed.isKidsBed()); + assertEquals("AABBCCDDEEFF", bed.getMacAddress()); + assertEquals("P5", bed.getModel()); + assertEquals("Bed", bed.getName()); + assertEquals(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized()), + bed.getPurchaseDate()); + assertEquals("55555555555-5", bed.getReference()); + assertEquals(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized()), + bed.getRegistrationDate()); + assertEquals(Long.valueOf(0L), bed.getReturnRequestStatus()); + assertEquals("", bed.getSerial()); + assertEquals("QUEEN", bed.getSize()); + assertEquals("QP5", bed.getSku()); + assertEquals("-2222222222222222222", bed.getSleeperLeftId()); + assertEquals("-1111111111111111111", bed.getSleeperRightId()); + assertEquals(Long.valueOf(1L), bed.getStatus()); + assertEquals("US/Pacific", bed.getTimezone()); + assertEquals("", bed.getVersion()); + assertEquals("90210", bed.getZipCode()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java new file mode 100644 index 0000000000000..91b760b5cd057 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.FileReader; +import java.util.Arrays; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.sleepiq.api.impl.GsonGenerator; +import org.openhab.binding.sleepiq.api.model.Bed; +import org.openhab.binding.sleepiq.api.model.BedsResponse; +import org.openhab.binding.sleepiq.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class BedsResponseTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + BedsResponse bedsResponse = new BedsResponse().withBeds(Arrays.asList(new Bed().withName("Bed1"), + new Bed().withName("Bed2"))); + assertEquals(readJson("beds-response.json"), gson.toJson(bedsResponse)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("beds-response.json"))) + { + BedsResponse bedsResponse = gson.fromJson(reader, BedsResponse.class); + + List beds = bedsResponse.getBeds(); + assertNotNull(beds); + assertEquals(2, beds.size()); + assertEquals("Bed1", beds.get(0).getName()); + assertEquals("Bed2", beds.get(1).getName()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java new file mode 100644 index 0000000000000..425e713d59535 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.FileReader; +import java.util.Arrays; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.sleepiq.api.impl.GsonGenerator; +import org.openhab.binding.sleepiq.api.model.BedStatus; +import org.openhab.binding.sleepiq.api.model.FamilyStatus; +import org.openhab.binding.sleepiq.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class FamilyStatusTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + FamilyStatus familyStatus = new FamilyStatus().withBeds(Arrays.asList(new BedStatus().withStatus(1L))); + assertEquals(readJson("family-status.json"), gson.toJson(familyStatus)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("family-status.json"))) + { + FamilyStatus familyStatus = gson.fromJson(reader, FamilyStatus.class); + + List beds = familyStatus.getBeds(); + assertNotNull(beds); + assertEquals(1, beds.size()); + assertEquals(Long.valueOf(1L), beds.get(0).getStatus()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/PauseModeTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/PauseModeTest.java new file mode 100644 index 0000000000000..c565b6e765192 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/PauseModeTest.java @@ -0,0 +1,60 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.sleepiq.api.impl.GsonGenerator; +import org.openhab.binding.sleepiq.api.model.PauseMode; +import org.openhab.binding.sleepiq.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class PauseModeTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + PauseMode pauseMode = new PauseMode().withAccountId("-8888888888888888888") + .withBedId("-9999999999999999999") + .withPauseMode("off"); + assertEquals(readJson("pause-mode.json"), gson.toJson(pauseMode)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("pause-mode.json"))) + { + PauseMode pauseMode = gson.fromJson(reader, PauseMode.class); + assertEquals("-8888888888888888888", pauseMode.getAccountId()); + assertEquals("-9999999999999999999", pauseMode.getBedId()); + assertEquals("off", pauseMode.getPauseMode()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java new file mode 100644 index 0000000000000..9cf37252cef11 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java @@ -0,0 +1,117 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; + +import java.io.FileReader; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.sleepiq.api.impl.GsonGenerator; +import org.openhab.binding.sleepiq.api.model.Sleeper; +import org.openhab.binding.sleepiq.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class SleeperTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + Sleeper sleeper = new Sleeper().withAccountId("-5555555555555555555") + .withAccountOwner(true) + .withActive(true) + .withAvatar("") + .withBedId("-9999999999999999999") + .withBirthMonth(6) + .withBirthYear("1970") + .withChild(false) + .withDuration("") + .withEmail("alice@domain.com") + .withEmailValidated(true) + .withFirstName("Alice") + .withHeight(64) + .withLastLogin("2017-02-17 20:19:36 CST") + .withLicenseVersion(6L) + .withMale(false) + .withSide(1) + .withSleeperId("-1111111111111111111") + .withSleepGoal(450) + .withTimezone("US/Pacific") + .withUsername("alice@domain.com") + .withWeight(110) + .withZipCode("90210"); + assertEquals(readJson("sleeper.json"), gson.toJson(sleeper)); + } + + @Test + public void testSerializeLastLoginNull() throws Exception + { + Sleeper sleeper = new Sleeper().withLastLogin("null"); + assertEquals(readJson("sleeper-lastlogin-null.json"), gson.toJson(sleeper)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("sleeper.json"))) + { + Sleeper sleeper = gson.fromJson(reader, Sleeper.class); + assertEquals("-5555555555555555555", sleeper.getAccountId()); + assertEquals(true, sleeper.isAccountOwner()); + assertEquals(true, sleeper.isActive()); + assertEquals("", sleeper.getAvatar()); + assertEquals("-9999999999999999999", sleeper.getBedId()); + assertEquals(Integer.valueOf(6), sleeper.getBirthMonth()); + assertEquals("1970", sleeper.getBirthYear()); + assertEquals(false, sleeper.isChild()); + assertEquals("", sleeper.getDuration()); + assertEquals("alice@domain.com", sleeper.getEmail()); + assertEquals(true, sleeper.isEmailValidated()); + assertEquals("Alice", sleeper.getFirstName()); + assertEquals(Integer.valueOf(64), sleeper.getHeight()); + assertEquals("2017-02-17 20:19:36 CST", sleeper.getLastLogin()); + assertEquals(Long.valueOf(6L), sleeper.getLicenseVersion()); + assertEquals(false, sleeper.isMale()); + assertEquals(Integer.valueOf(1), sleeper.getSide()); + assertEquals("-1111111111111111111", sleeper.getSleeperId()); + assertEquals(Integer.valueOf(450), sleeper.getSleepGoal()); + assertEquals("US/Pacific", sleeper.getTimezone()); + assertEquals("alice@domain.com", sleeper.getUsername()); + assertEquals(Integer.valueOf(110), sleeper.getWeight()); + assertEquals("90210", sleeper.getZipCode()); + } + } + + @Test + public void testDeserializeLastLoginNull() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("sleeper-lastlogin-null.json"))) + { + Sleeper sleeper = gson.fromJson(reader, Sleeper.class); + assertEquals("null", sleeper.getLastLogin()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java new file mode 100644 index 0000000000000..62969c79367cd --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.FileReader; +import java.util.Arrays; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.openhab.binding.sleepiq.api.impl.GsonGenerator; +import org.openhab.binding.sleepiq.api.model.Sleeper; +import org.openhab.binding.sleepiq.api.model.SleepersResponse; +import org.openhab.binding.sleepiq.api.test.AbstractTest; + +import com.google.gson.Gson; + +public class SleepersResponseTest extends AbstractTest +{ + private static Gson gson; + + @BeforeClass + public static void setUpBeforeClass() + { + gson = GsonGenerator.create(true); + } + + @Test + public void testSerializeAllFields() throws Exception + { + SleepersResponse sleepersResponse = new SleepersResponse().withSleepers(Arrays.asList(new Sleeper().withFirstName("Alice"), + new Sleeper().withFirstName("Bob"))); + assertEquals(readJson("sleepers-response.json"), gson.toJson(sleepersResponse)); + } + + @Test + public void testDeserializeAllFields() throws Exception + { + try (FileReader reader = new FileReader(getTestDataFile("sleepers-response.json"))) + { + SleepersResponse sleepersResponse = gson.fromJson(reader, SleepersResponse.class); + + List sleepers = sleepersResponse.getSleepers(); + assertNotNull(sleepers); + assertEquals(2, sleepers.size()); + assertEquals("Alice", sleepers.get(0).getFirstName()); + assertEquals("Bob", sleepers.get(1).getFirstName()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java new file mode 100644 index 0000000000000..54c658cb5fbc7 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.model; + +import static org.junit.Assert.assertEquals; + +import java.time.Duration; + +import org.junit.Test; +import org.openhab.binding.sleepiq.api.model.TimeSince; + +public class TimeSinceTest +{ + @Test + public void testWithDuration() + { + assertEquals(new TimeSince().withDuration(0, 0, 0, 0).getDuration(), + new TimeSince().withDuration(Duration.parse("PT00H00M00S")).getDuration()); + assertEquals(new TimeSince().withDuration(0, 2, 3, 4).getDuration(), + new TimeSince().withDuration(Duration.parse("PT02H03M04S")).getDuration()); + assertEquals(new TimeSince().withDuration(0, 12, 34, 56).getDuration(), + new TimeSince().withDuration(Duration.parse("PT12H34M56S")).getDuration()); + assertEquals(new TimeSince().withDuration(1, 2, 3, 4).getDuration(), + new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).getDuration()); + assertEquals(new TimeSince().withDuration(12, 23, 34, 45).getDuration(), + new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).getDuration()); + } + + @Test + public void testToString() + { + assertEquals("00:00:00", + new TimeSince().withDuration(Duration.parse("PT00H00M00S")).toString()); + assertEquals("02:03:04", + new TimeSince().withDuration(Duration.parse("PT02H03M04S")).toString()); + assertEquals("12:34:56", + new TimeSince().withDuration(Duration.parse("PT12H34M56S")).toString()); + assertEquals("1 d 02:03:04", + new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).toString()); + assertEquals("12 d 23:34:45", + new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).toString()); + } + + @Test + public void testParse() + { + assertEquals(Duration.parse("PT00H00M00S"), TimeSince.parse("00:00:00").getDuration()); + assertEquals(Duration.parse("PT2H3M4S"), TimeSince.parse("02:03:04").getDuration()); + assertEquals(Duration.parse("PT12H34M56S"), TimeSince.parse("12:34:56").getDuration()); + assertEquals(Duration.parse("P1DT2H3M4S"), TimeSince.parse("1 d 02:03:04").getDuration()); + assertEquals(Duration.parse("P12DT23H34M45S"), + TimeSince.parse("12 d 23:34:45").getDuration()); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java new file mode 100644 index 0000000000000..f9dfd395b565c --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017 Gregory Moyer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openhab.binding.sleepiq.api.test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public abstract class AbstractTest +{ + private static final String RESOURCES_PATH = "src/test/resources/"; + + protected File getTestDataFile(String name) + { + return getTestDataPath(name).toFile(); + } + + protected Path getTestDataPath(String name) + { + String packageName = this.getClass().getPackage().getName(); + + List paths = new ArrayList<>(); + paths.addAll(Arrays.asList(packageName.split("\\."))); + paths.add(name); + + return Paths.get(RESOURCES_PATH, paths.toArray(new String[paths.size()])); + } + + protected String readJson(String jsonFileName) throws IOException + { + return new String(Files.readAllBytes(getTestDataPath(jsonFileName))); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/feature/feature.xml b/bundles/org.openhab.binding.sleepiq/src/main/feature/feature.xml index 1f7c440c1c0bc..d835bb11e81f1 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.sleepiq/src/main/feature/feature.xml @@ -1,10 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:com.eclipsesource.jaxrs/provider-gson/2.3 - mvn:org.openhab.addons.bundles/org.openhab.binding.sleepiq/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.sleepiq/${project.version} + diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java new file mode 100644 index 0000000000000..f082daab03b64 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java @@ -0,0 +1,85 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.sleepiq.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; + +import com.google.gson.Gson; + +/** + * JSON reader/writer for Jersey using GSON. + * + * @author Simon Kaufmann - Initial contribution + * + * @param + */ +@Provider +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class GsonProvider implements MessageBodyReader, MessageBodyWriter { + + private final Gson gson; + + public GsonProvider(Gson gson) { + this.gson = gson; + } + + @Override + public long getSize(T t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return -1; + } + + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return true; + } + + @Override + public void writeTo(T object, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { + try (OutputStream stream = entityStream) { + entityStream.write(gson.toJson(object).getBytes(StandardCharsets.UTF_8)); + entityStream.flush(); + } + } + + @Override + public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return true; + } + + @Override + public T readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, InputStream entityStream) + throws IOException, WebApplicationException { + try (InputStreamReader reader = new InputStreamReader(entityStream, StandardCharsets.UTF_8)) { + return gson.fromJson(reader, type); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java index 75d1b32624ec4..eec54e219cc78 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java @@ -19,13 +19,13 @@ import org.eclipse.smarthome.config.discovery.DiscoveryResult; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.sleepiq.api.model.Bed; import org.openhab.binding.sleepiq.internal.SleepIQBindingConstants; import org.openhab.binding.sleepiq.internal.config.SleepIQBedConfiguration; import org.openhab.binding.sleepiq.internal.handler.SleepIQCloudHandler; import org.openhab.binding.sleepiq.internal.handler.SleepIQDualBedHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.sleepiq.api.model.Bed; /** * The {@link SleepIQBedDiscoveryService} is responsible for processing the @@ -72,7 +72,7 @@ protected void startScan() { bed.getMacAddress()); // thing already exists - if (cloudHandler.getThingByUID(thingUID) != null) { + if (cloudHandler.getThing().getThing(thingUID) != null) { continue; } diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java index 5ff449ed5ec56..c68f419547530 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java @@ -12,8 +12,8 @@ */ package org.openhab.binding.sleepiq.internal.handler; -import org.syphr.sleepiq.api.SleepIQ; -import org.syphr.sleepiq.api.model.BedStatus; +import org.openhab.binding.sleepiq.api.SleepIQ; +import org.openhab.binding.sleepiq.api.model.BedStatus; /** * The {@link BedStatusListener} is notified when a chamber is updated. diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java index 92e22d7a45590..61bf66062ee2f 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java @@ -36,18 +36,18 @@ import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.ConfigStatusBridgeHandler; import org.eclipse.smarthome.core.types.Command; +import org.openhab.binding.sleepiq.api.Configuration; +import org.openhab.binding.sleepiq.api.LoginException; +import org.openhab.binding.sleepiq.api.SleepIQ; +import org.openhab.binding.sleepiq.api.UnauthorizedException; +import org.openhab.binding.sleepiq.api.model.Bed; +import org.openhab.binding.sleepiq.api.model.BedStatus; +import org.openhab.binding.sleepiq.api.model.FamilyStatus; import org.openhab.binding.sleepiq.internal.SleepIQBindingConstants; import org.openhab.binding.sleepiq.internal.SleepIQConfigStatusMessage; import org.openhab.binding.sleepiq.internal.config.SleepIQCloudConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.sleepiq.api.Configuration; -import org.syphr.sleepiq.api.LoginException; -import org.syphr.sleepiq.api.SleepIQ; -import org.syphr.sleepiq.api.UnauthorizedException; -import org.syphr.sleepiq.api.model.Bed; -import org.syphr.sleepiq.api.model.BedStatus; -import org.syphr.sleepiq.api.model.FamilyStatus; /** * The {@link SleepIQCloudHandler} is responsible for handling commands, which are diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java index cca5d880df1e4..2dd6b1c17a016 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java @@ -32,13 +32,13 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; +import org.openhab.binding.sleepiq.api.SleepIQ; +import org.openhab.binding.sleepiq.api.model.Bed; +import org.openhab.binding.sleepiq.api.model.BedSideStatus; +import org.openhab.binding.sleepiq.api.model.BedStatus; import org.openhab.binding.sleepiq.internal.config.SleepIQBedConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.syphr.sleepiq.api.SleepIQ; -import org.syphr.sleepiq.api.model.Bed; -import org.syphr.sleepiq.api.model.BedSideStatus; -import org.syphr.sleepiq.api.model.BedStatus; /** * The {@link SleepIQDualBedHandler} is responsible for handling channel state updates from the cloud service. diff --git a/bundles/org.openhab.binding.sleepiq/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.sleepiq/src/main/resources/ESH-INF/binding/binding.xml index d0b319447606a..4df7651df522c 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.sleepiq/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + SleepIQ Binding This is the binding for the Sleep Number SleepIQ system. diff --git a/bundles/org.openhab.binding.sleepiq/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.sleepiq/src/main/resources/ESH-INF/thing/thing-types.xml index 0e4e040a44f99..1f90098565b81 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.sleepiq/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -36,32 +36,32 @@ - + @@ -98,37 +98,38 @@ Switch The presence of a person or object on the chamber - + Number The Sleep Number setting of the chamber - + Number The current pressure inside the chamber - + String - The amount of time that has passed since a connection was made from the chamber to the cloud service (D d HH:MM:SS) - + The amount of time that has passed since a connection was made from the chamber to the cloud service (D d + HH:MM:SS) + Number Identifier for an alert condition with the chamber - + String A detailed message describing an alert condition with the chamber - + diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed-side-status.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed-side-status.json new file mode 100644 index 0000000000000..045e2fe853ed6 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed-side-status.json @@ -0,0 +1,8 @@ +{ + "isInBed": false, + "alertDetailedMessage": "No Alert", + "sleepNumber": 55, + "alertId": 0, + "lastLink": "3 d 05:04:38", + "pressure": 573 +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed-status.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed-status.json new file mode 100644 index 0000000000000..1793077378f63 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed-status.json @@ -0,0 +1,10 @@ +{ + "status": 1, + "bedId": "-9999999999999999999", + "leftSide": { + "isInBed": true + }, + "rightSide": { + "isInBed": false + } +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed.json new file mode 100644 index 0000000000000..eb1afa052e3de --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/bed.json @@ -0,0 +1,23 @@ +{ + "registrationDate": "2017-02-17T02:14:10Z", + "sleeperRightId": "-1111111111111111111", + "base": "MODULAR", + "returnRequestStatus": 0, + "size": "QUEEN", + "name": "Bed", + "serial": "", + "isKidsBed": false, + "dualSleep": true, + "bedId": "-9999999999999999999", + "status": 1, + "sleeperLeftId": "-2222222222222222222", + "version": "", + "accountId": "-8888888888888888888", + "timezone": "US/Pacific", + "model": "P5", + "purchaseDate": "2017-02-02T00:00:01Z", + "macAddress": "AABBCCDDEEFF", + "sku": "QP5", + "zipcode": "90210", + "reference": "55555555555-5" +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/beds-response.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/beds-response.json new file mode 100644 index 0000000000000..a116cb2ab7741 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/beds-response.json @@ -0,0 +1,10 @@ +{ + "beds": [ + { + "name": "Bed1" + }, + { + "name": "Bed2" + } + ] +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/family-status.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/family-status.json new file mode 100644 index 0000000000000..aff7fcced3ca8 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/family-status.json @@ -0,0 +1,7 @@ +{ + "beds": [ + { + "status": 1 + } + ] +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/pause-mode.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/pause-mode.json new file mode 100644 index 0000000000000..5c64e288a2b51 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/pause-mode.json @@ -0,0 +1,5 @@ +{ + "accountId": "-8888888888888888888", + "bedId": "-9999999999999999999", + "pauseMode": "off" +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleeper-lastlogin-null.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleeper-lastlogin-null.json new file mode 100644 index 0000000000000..f0f17bcc75350 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleeper-lastlogin-null.json @@ -0,0 +1,3 @@ +{ + "lastLogin": "null" +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleeper.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleeper.json new file mode 100644 index 0000000000000..3afb3aeee38c9 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleeper.json @@ -0,0 +1,25 @@ +{ + "firstName": "Alice", + "active": true, + "emailValidated": true, + "isChild": false, + "bedId": "-9999999999999999999", + "birthYear": "1970", + "zipCode": "90210", + "timezone": "US/Pacific", + "isMale": false, + "weight": 110, + "duration": "", + "sleeperId": "-1111111111111111111", + "height": 64, + "licenseVersion": 6, + "username": "alice@domain.com", + "birthMonth": 6, + "sleepGoal": 450, + "isAccountOwner": true, + "accountId": "-5555555555555555555", + "email": "alice@domain.com", + "avatar": "", + "lastLogin": "2017-02-17 20:19:36 CST", + "side": 1 +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleepers-response.json b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleepers-response.json new file mode 100644 index 0000000000000..0f81998902cab --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/resources/org/openhab/binding/sleepiq/api/model/sleepers-response.json @@ -0,0 +1,10 @@ +{ + "sleepers": [ + { + "firstName": "Alice" + }, + { + "firstName": "Bob" + } + ] +} \ No newline at end of file diff --git a/bundles/org.openhab.binding.smaenergymeter/pom.xml b/bundles/org.openhab.binding.smaenergymeter/pom.xml index 8cc954b007575..53c440f387e36 100644 --- a/bundles/org.openhab.binding.smaenergymeter/pom.xml +++ b/bundles/org.openhab.binding.smaenergymeter/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.smaenergymeter diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/feature/feature.xml b/bundles/org.openhab.binding.smaenergymeter/src/main/feature/feature.xml index 61947bb011ac3..4e3ca1b678c3c 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.smaenergymeter/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.smaenergymeter/${project.version} + diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/SMAEnergyMeterBindingConstants.java b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/SMAEnergyMeterBindingConstants.java index 61cc131e051c3..c00de0caa9767 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/SMAEnergyMeterBindingConstants.java +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/SMAEnergyMeterBindingConstants.java @@ -39,5 +39,4 @@ public class SMAEnergyMeterBindingConstants { public static final String CHANNEL_POWER_OUT = "powerOut"; public static final String CHANNEL_ENERGY_IN = "energyIn"; public static final String CHANNEL_ENERGY_OUT = "energyOut"; - } diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/SMAEnergyMeterHandlerFactory.java b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/SMAEnergyMeterHandlerFactory.java index 0f5fc5b6a946b..8d85569e397a7 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/SMAEnergyMeterHandlerFactory.java +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/SMAEnergyMeterHandlerFactory.java @@ -46,5 +46,4 @@ protected ThingHandler createHandler(Thing thing) { return null; } - } diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/configuration/EnergyMeterConfig.java b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/configuration/EnergyMeterConfig.java index bc11fab77df3b..e0cf2be893a18 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/configuration/EnergyMeterConfig.java +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/configuration/EnergyMeterConfig.java @@ -46,5 +46,4 @@ public Integer getPollingPeriod() { public void setPollingPeriod(Integer pollingPeriod) { this.pollingPeriod = pollingPeriod; } - } diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/discovery/SMAEnergyMeterDiscoveryService.java b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/discovery/SMAEnergyMeterDiscoveryService.java index 07bc966572911..bc4fd3d6775ba 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/discovery/SMAEnergyMeterDiscoveryService.java +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/discovery/SMAEnergyMeterDiscoveryService.java @@ -87,5 +87,4 @@ private synchronized void discover() { logger.debug("Thing discovered '{}'", result); } - } diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/EnergyMeter.java b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/EnergyMeter.java index f5da54e1117e7..aaa6ae1dd2a24 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/EnergyMeter.java +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/EnergyMeter.java @@ -106,5 +106,4 @@ public DecimalType getEnergyIn() { public DecimalType getEnergyOut() { return new DecimalType(energyOut.getValue()); } - } diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/FieldDTO.java b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/FieldDTO.java index 032243fd15760..b260d8156e62e 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/FieldDTO.java +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/FieldDTO.java @@ -57,5 +57,4 @@ private long bytesToUInt32(byte[] bytes) { ByteBuffer buffer = ByteBuffer.wrap(bytes); return buffer.getLong(); } - } diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/SMAEnergyMeterHandler.java b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/SMAEnergyMeterHandler.java index f274417cfa2ad..263ad07516839 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/SMAEnergyMeterHandler.java +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/java/org/openhab/binding/smaenergymeter/internal/handler/SMAEnergyMeterHandler.java @@ -110,5 +110,4 @@ private synchronized void updateData() { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR, e.getMessage()); } } - } diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.smaenergymeter/src/main/resources/ESH-INF/binding/binding.xml index a1111acc58c56..cb3f1d5e2259d 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - SMA Energy Meter Binding diff --git a/bundles/org.openhab.binding.smaenergymeter/src/main/resources/ESH-INF/thing/energyMeter.xml b/bundles/org.openhab.binding.smaenergymeter/src/main/resources/ESH-INF/thing/energyMeter.xml index 12931eda1478d..4e488928c954e 100644 --- a/bundles/org.openhab.binding.smaenergymeter/src/main/resources/ESH-INF/thing/energyMeter.xml +++ b/bundles/org.openhab.binding.smaenergymeter/src/main/resources/ESH-INF/thing/energyMeter.xml @@ -8,10 +8,10 @@ - - - - + + + + @@ -25,8 +25,7 @@ IP address of the multicast group 239.12.255.254 - + Port of the multicast group 9522 @@ -45,24 +44,24 @@ Number Energy - + Number Energy - + Number Energy - + Number Energy - + diff --git a/bundles/org.openhab.binding.smartmeter/pom.xml b/bundles/org.openhab.binding.smartmeter/pom.xml index ef95af3e9905e..a0d64d669a05a 100644 --- a/bundles/org.openhab.binding.smartmeter/pom.xml +++ b/bundles/org.openhab.binding.smartmeter/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.smartmeter diff --git a/bundles/org.openhab.binding.smartmeter/src/main/feature/feature.xml b/bundles/org.openhab.binding.smartmeter/src/main/feature/feature.xml index 333737798a0ae..d9f748b466825 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.smartmeter/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.smartmeter/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.smartmeter/${project.version} + diff --git a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/MeterValue.java b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/MeterValue.java index 054f9fd87717e..b669596a1b515 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/MeterValue.java +++ b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/MeterValue.java @@ -125,5 +125,4 @@ public String getObisCode() { public void setStatus(String status) { this.status = status; } - } diff --git a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/ObisCode.java b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/ObisCode.java index 1760ede0e58c5..702ba629d4210 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/ObisCode.java +++ b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/ObisCode.java @@ -126,5 +126,4 @@ public boolean matches(@Nullable Byte a, @Nullable Byte b, Byte c, Byte d, Byte public boolean matches(Byte c, Byte d, Byte e) { return matches(null, null, c, d, e, null); } - } diff --git a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterChannelTypeProvider.java b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterChannelTypeProvider.java index 7d33f2b1e8447..5c53f25e39006 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterChannelTypeProvider.java +++ b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterChannelTypeProvider.java @@ -65,7 +65,6 @@ public Collection getChannelTypes(@Nullable Locale locale) { @Override public void errorOccurred(Throwable e) { // Nothing to do if there is an reading error... - } @Override @@ -112,5 +111,4 @@ private ChannelType getChannelType(Unit unit, String obis) { public ChannelTypeUID getChannelTypeIdForObis(String obis) { return obisChannelMap.get(obis).getUID(); } - } diff --git a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterConfigProvider.java b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterConfigProvider.java index 5b2560713aa05..fee7a6e9f722a 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterConfigProvider.java +++ b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterConfigProvider.java @@ -77,5 +77,4 @@ public class SmartMeterConfigProvider implements ConfigOptionProvider { } return null; } - } diff --git a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterHandler.java b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterHandler.java index 055e78b51f845..c8bb8850a71eb 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterHandler.java +++ b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterHandler.java @@ -288,5 +288,4 @@ private > State applyConformity(Channel channel, QuantityT } return currentState; } - } diff --git a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterHandlerFactory.java b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterHandlerFactory.java index 0b45d24d57f83..634224b3849e7 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterHandlerFactory.java +++ b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/SmartMeterHandlerFactory.java @@ -77,5 +77,4 @@ protected void unsetSerialPortManager(SerialPortManager serialPortManager) { return null; } - } diff --git a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/conformity/negate/NegateBitModel.java b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/conformity/negate/NegateBitModel.java index cca74c202b055..e02bd6e75386b 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/conformity/negate/NegateBitModel.java +++ b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/conformity/negate/NegateBitModel.java @@ -93,5 +93,4 @@ public boolean equals(@Nullable Object obj) { public boolean isStatus() { return status; } - } diff --git a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/iec62056/Iec62056_21MeterReader.java b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/iec62056/Iec62056_21MeterReader.java index f20d0a2c18e4c..ac3b3bb07f082 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/iec62056/Iec62056_21MeterReader.java +++ b/bundles/org.openhab.binding.smartmeter/src/main/java/org/openhab/binding/smartmeter/internal/iec62056/Iec62056_21MeterReader.java @@ -60,5 +60,4 @@ protected IMeterReaderConnector createConnector(Supplier - Smartmeter Binding - The Smartmeter binding is able to read SML messages (PUSH) and supports IEC 62056-21 modes A,B,C (PULL) and D (PUSH). + The Smartmeter binding is able to read SML messages (PUSH) and supports IEC 62056-21 modes A,B,C (PULL) + and D (PUSH). diff --git a/bundles/org.openhab.binding.smartmeter/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.smartmeter/src/main/resources/ESH-INF/thing/thing-types.xml index a7ce031d4ec0f..d679cc940e8b0 100644 --- a/bundles/org.openhab.binding.smartmeter/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.smartmeter/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -33,7 +34,8 @@ true AUTO - The baudrate of the serial port. If set to 'AUTO', it is dependent on the selected mode. The default is 300 baud for modes A, B, and C and 2400 baud for mode D, and 9600 baud for SML. + The baudrate of the serial port. If set to 'AUTO', it is dependent on the selected mode. The default is + 300 baud for modes A, B, and C and 2400 baud for mode D, and 9600 baud for SML. false @@ -46,7 +48,8 @@ true NONE - Reserved to conform to special semantics specified in specific standards. EDL_FNN: Currently applies the energy direction to WATT channels (which are absolute values) (see fnn lastenheft edl) + Reserved to conform to special semantics specified in specific standards. EDL_FNN: Currently applies + the energy direction to WATT channels (which are absolute values) (see fnn lastenheft edl) true diff --git a/bundles/org.openhab.binding.smartmeter/src/test/java/org/openhab/binding/smartmeter/TestMeterReading.java b/bundles/org.openhab.binding.smartmeter/src/test/java/org/openhab/binding/smartmeter/TestMeterReading.java index f8aff53d8dbf7..4388a82cd2e98 100644 --- a/bundles/org.openhab.binding.smartmeter/src/test/java/org/openhab/binding/smartmeter/TestMeterReading.java +++ b/bundles/org.openhab.binding.smartmeter/src/test/java/org/openhab/binding/smartmeter/TestMeterReading.java @@ -150,7 +150,6 @@ MeterDevice getMeterDevice(ConnectorBase connector) { protected > void populateValueCache(Object smlFile) { addObisCache(new MeterValue("123", "333", null)); } - }; } } diff --git a/bundles/org.openhab.binding.snmp/pom.xml b/bundles/org.openhab.binding.snmp/pom.xml index e371d67633514..6d7ff9fa1389d 100644 --- a/bundles/org.openhab.binding.snmp/pom.xml +++ b/bundles/org.openhab.binding.snmp/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.snmp diff --git a/bundles/org.openhab.binding.snmp/src/main/feature/feature.xml b/bundles/org.openhab.binding.snmp/src/main/feature/feature.xml index 5690a78254106..292c8da08ef99 100644 --- a/bundles/org.openhab.binding.snmp/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.snmp/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.snmp/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.snmp/${project.version} + diff --git a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpTargetHandler.java b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpTargetHandler.java index ba3e33dc5e73f..ce1777a35664c 100644 --- a/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpTargetHandler.java +++ b/bundles/org.openhab.binding.snmp/src/main/java/org/openhab/binding/snmp/internal/SnmpTargetHandler.java @@ -439,5 +439,4 @@ private void refresh() { } } } - } diff --git a/bundles/org.openhab.binding.snmp/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.snmp/src/main/resources/ESH-INF/binding/binding.xml index a8c74500aaef2..0aad84ffa15f4 100644 --- a/bundles/org.openhab.binding.snmp/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.snmp/src/main/resources/ESH-INF/binding/binding.xml @@ -11,7 +11,7 @@ 0 - Port for receiving traps, set to 0 to disable. + Port for receiving traps, set to 0 to disable. diff --git a/bundles/org.openhab.binding.snmp/src/test/java/org/openhab/binding/snmp/internal/SnmpTargetHandlerTest.java b/bundles/org.openhab.binding.snmp/src/test/java/org/openhab/binding/snmp/internal/SnmpTargetHandlerTest.java index 1b7ca484bcef6..b11ec10857f78 100644 --- a/bundles/org.openhab.binding.snmp/src/test/java/org/openhab/binding/snmp/internal/SnmpTargetHandlerTest.java +++ b/bundles/org.openhab.binding.snmp/src/test/java/org/openhab/binding/snmp/internal/SnmpTargetHandlerTest.java @@ -61,7 +61,6 @@ public void testChannelsProperlyUpdate() throws IOException { new OctetString("on"), false)); assertNull( onResponseSwitchChannel(SnmpChannelMode.TRAP, SnmpDatatype.INT32, "1", "2", new Integer32(2), false)); - } @Test @@ -94,7 +93,6 @@ public void testCommandsAreProperlyHandledByNumberChannel() throws IOException { variable = handleCommandNumberStringChannel(SnmpBindingConstants.CHANNEL_TYPE_UID_NUMBER, SnmpDatatype.INT32, new StringType(TEST_STRING), false); assertNull(variable); - } @Test diff --git a/bundles/org.openhab.binding.solaredge/pom.xml b/bundles/org.openhab.binding.solaredge/pom.xml index 2c6c664a62485..0b409730317d6 100644 --- a/bundles/org.openhab.binding.solaredge/pom.xml +++ b/bundles/org.openhab.binding.solaredge/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.solaredge diff --git a/bundles/org.openhab.binding.solaredge/src/main/feature/feature.xml b/bundles/org.openhab.binding.solaredge/src/main/feature/feature.xml index 4c6d3cb185f4e..158b13e6de93b 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.solaredge/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.solaredge/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.solaredge/${project.version} + diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/AtomicReferenceTrait.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/AtomicReferenceTrait.java index 2c3bd19467bc2..fb17192110989 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/AtomicReferenceTrait.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/AtomicReferenceTrait.java @@ -42,7 +42,7 @@ default void cancelJob(@Nullable Future job) { * updates a job reference with a new job. the old job will be cancelled if there is one. * * @param jobReference reference to be updated - * @param newJob job to be assigned + * @param newJob job to be assigned */ default void updateJobReference(AtomicReference<@Nullable Future> jobReference, Future newJob) { cancelJob(jobReference.getAndSet(newJob)); diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/SolarEdgeBindingConstants.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/SolarEdgeBindingConstants.java index a62480345b3bc..9d94b22b2f568 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/SolarEdgeBindingConstants.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/SolarEdgeBindingConstants.java @@ -78,5 +78,4 @@ public class SolarEdgeBindingConstants { public static final int WEB_REQUEST_QUEUE_MAX_SIZE = 20; public static final Set SUPPORTED_THING_TYPES_UIDS = Collections.singleton(THING_TYPE_GENERIC); - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/SolarEdgeHandlerFactory.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/SolarEdgeHandlerFactory.java index 7caba2c09da7a..0c026f01a3521 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/SolarEdgeHandlerFactory.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/SolarEdgeHandlerFactory.java @@ -71,5 +71,4 @@ protected void unsetHttpClientFactory(HttpClientFactory httpClientFactory) { logger.debug("unsetHttpClientFactory"); this.httpClient = null; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/callback/AbstractCommandCallback.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/callback/AbstractCommandCallback.java index 6d3a3daf29c7f..fc946eb53bd22 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/callback/AbstractCommandCallback.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/callback/AbstractCommandCallback.java @@ -79,7 +79,6 @@ public AbstractCommandCallback(SolarEdgeConfiguration config) { this.communicationStatus = new CommunicationStatus(); this.config = config; this.gson = new Gson(); - } /** @@ -118,7 +117,6 @@ public final void onFailure(Response response, Throwable failure) { } else { communicationStatus.setHttpCode(Code.INTERNAL_SERVER_ERROR); } - } @Override @@ -183,5 +181,4 @@ public final StatusUpdateListener getListener() { public final void setListener(StatusUpdateListener listener) { this.listener = listener; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/LiveDataUpdateMeterless.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/LiveDataUpdateMeterless.java index 46eddbdda6d96..aed528e1fac53 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/LiveDataUpdateMeterless.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/LiveDataUpdateMeterless.java @@ -73,5 +73,4 @@ public void onComplete(Result result) { } } } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/LiveDataUpdatePrivateApi.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/LiveDataUpdatePrivateApi.java index 91e520ed0d77d..a85a09dabf37c 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/LiveDataUpdatePrivateApi.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/LiveDataUpdatePrivateApi.java @@ -73,5 +73,4 @@ public void onComplete(Result result) { } } } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/PrivateApiTokenCheck.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/PrivateApiTokenCheck.java index b3df8d99a3a56..d9e2033dd3f33 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/PrivateApiTokenCheck.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/PrivateApiTokenCheck.java @@ -51,5 +51,4 @@ protected String getURL() { public void onComplete(Result result) { getListener().update(getCommunicationStatus()); } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/PublicApiKeyCheck.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/PublicApiKeyCheck.java index c6dab3c25b328..4b7995ad147f5 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/PublicApiKeyCheck.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/PublicApiKeyCheck.java @@ -51,5 +51,4 @@ protected String getURL() { public void onComplete(Result result) { getListener().update(getCommunicationStatus()); } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/SolarEdgeCommand.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/SolarEdgeCommand.java index 6ae77674c5f4f..babc0fa1161ce 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/SolarEdgeCommand.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/command/SolarEdgeCommand.java @@ -48,5 +48,4 @@ public interface SolarEdgeCommand extends SuccessListener, FailureListener, Cont * @param listener */ void setListener(StatusUpdateListener listener); - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/config/SolarEdgeConfiguration.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/config/SolarEdgeConfiguration.java index 93208412f678d..9bc5fb11d1f06 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/config/SolarEdgeConfiguration.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/config/SolarEdgeConfiguration.java @@ -107,5 +107,4 @@ public String toString() { .append("aggregate data pollingInterval", getAggregateDataPollingInterval()) .append("asyncTimeout", getAsyncTimeout()).append("syncTimeout", getSyncTimeout()).toString(); } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/CommunicationStatus.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/CommunicationStatus.java index 0cc52830e6f24..fc139d0f40183 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/CommunicationStatus.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/CommunicationStatus.java @@ -49,5 +49,4 @@ public final String getMessage() { } return ""; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/StatusUpdateListener.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/StatusUpdateListener.java index 4cc7a7f1d6079..0a1841e5a0225 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/StatusUpdateListener.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/StatusUpdateListener.java @@ -23,5 +23,4 @@ public interface StatusUpdateListener { void update(CommunicationStatus status); - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/WebInterface.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/WebInterface.java index fe8806798b158..36544a05e1f40 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/WebInterface.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/connector/WebInterface.java @@ -159,7 +159,6 @@ public void update(CommunicationStatus status) { command.performAction(httpClient); } } - } /** @@ -283,7 +282,6 @@ private boolean preCheck() { this.handler.setStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, preCheckStatusMessage); return false; - } /** @@ -317,5 +315,4 @@ private boolean isAuthenticated() { private void setAuthenticated(boolean authenticated) { this.authenticated = authenticated; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/handler/SolarEdgeBaseHandler.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/handler/SolarEdgeBaseHandler.java index 5839dfdb8dc22..583ed4e6d995f 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/handler/SolarEdgeBaseHandler.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/handler/SolarEdgeBaseHandler.java @@ -152,5 +152,4 @@ public void setStatusInfo(ThingStatus status, ThingStatusDetail statusDetail, St public SolarEdgeConfiguration getConfiguration() { return this.getConfigAs(SolarEdgeConfiguration.class); } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/handler/SolarEdgeHandler.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/handler/SolarEdgeHandler.java index 8e2d2d86e9699..4f98b033298f1 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/handler/SolarEdgeHandler.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/handler/SolarEdgeHandler.java @@ -35,9 +35,9 @@ public interface SolarEdgeHandler extends ThingHandler { * Called from {@link WebInterface#authenticate()} to update * the thing status because updateStatus is protected. * - * @param status Bridge status + * @param status Bridge status * @param statusDetail Bridge status detail - * @param description Bridge status description + * @param description Bridge status description */ void setStatusInfo(ThingStatus status, ThingStatusDetail statusDetail, String description); diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AbstractAggregateDataResponsePrivateApi.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AbstractAggregateDataResponsePrivateApi.java index f555f440754e7..a14ae51ebbe54 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AbstractAggregateDataResponsePrivateApi.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AbstractAggregateDataResponsePrivateApi.java @@ -104,5 +104,4 @@ protected final void assignPercentage(Map targetMap, Channel cha } targetMap.put(channel, result); } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateDataResponsePublicApi.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateDataResponsePublicApi.java index 96f288ddaae4b..aa39a5aded93d 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateDataResponsePublicApi.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateDataResponsePublicApi.java @@ -354,5 +354,4 @@ protected final void assignPercentage(Map targetMap, Channel cha targetMap.put(channel, result); } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateMonthDataResponsePrivateApi.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateMonthDataResponsePrivateApi.java index d985cfa4c4ee2..9006486b8520a 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateMonthDataResponsePrivateApi.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateMonthDataResponsePrivateApi.java @@ -60,5 +60,4 @@ public Map getValues() { return valueMap; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateWeekDataResponsePrivateApi.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateWeekDataResponsePrivateApi.java index 0f88e73ecff23..80d01010a346e 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateWeekDataResponsePrivateApi.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateWeekDataResponsePrivateApi.java @@ -60,5 +60,4 @@ public Map getValues() { return valueMap; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateYearDataResponsePrivateApi.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateYearDataResponsePrivateApi.java index 4c2419737e244..1ac3eb2d2348b 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateYearDataResponsePrivateApi.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/AggregateYearDataResponsePrivateApi.java @@ -60,5 +60,4 @@ public Map getValues() { return valueMap; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/DataResponse.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/DataResponse.java index e833a21811c3e..2f83a45bcc032 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/DataResponse.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/DataResponse.java @@ -74,5 +74,4 @@ default Unit determinePowerUnit(String unit) { } return null; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/LiveDataResponse.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/LiveDataResponse.java index 40ad20b07f5b8..59274984da10e 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/LiveDataResponse.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/LiveDataResponse.java @@ -79,7 +79,6 @@ public static class SiteCurrentPowerFlow { public BatteryValue storage; public List connections; - } private SiteCurrentPowerFlow siteCurrentPowerFlow; diff --git a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/LiveDataResponseMeterless.java b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/LiveDataResponseMeterless.java index a07945505153d..da538d9ad2821 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/LiveDataResponseMeterless.java +++ b/bundles/org.openhab.binding.solaredge/src/main/java/org/openhab/binding/solaredge/internal/model/LiveDataResponseMeterless.java @@ -114,5 +114,4 @@ public final Overview getOverview() { public final void setOverview(Overview overview) { this.overview = overview; } - } diff --git a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/binding/binding.xml index 1146dfd309c32..b6a4ee41505cb 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - SolarEdge Binding This is the binding for SolarEdge. diff --git a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/config/config.xml index 1b845eda93ee2..658fa975a1096 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - @@ -18,7 +19,8 @@ - API Key to access the official solaredge API. If using Private API this must be fills with Spring Security Token (Check Browser Cookies when logged into website) + API Key to access the official solaredge API. If using Private API this must be fills with Spring + Security Token (Check Browser Cookies when logged into website) password @@ -32,19 +34,23 @@ - Private API allows to avoid the limit of 300 API calls per day but is less documented and therefore less stable. If no meter is available you cannot use the private API, it does not provide live data for this kind of setup. + Private API allows to avoid the limit of 300 API calls per day but is less documented and therefore less + stable. If no meter is available you cannot use the private API, it does not provide live data for this kind of + setup. false - Interval in which live data is polled from SolarEdge (in minutes). If not using private API this should not be less than 10 minutes. + Interval in which live data is polled from SolarEdge (in minutes). If not using private API this should + not be less than 10 minutes. 10 - Interval in which aggregate data is polled from SolarEdge (in minutes). If not using private API this must not be less than 60 minutes. + Interval in which aggregate data is polled from SolarEdge (in minutes). If not using private API this + must not be less than 60 minutes. 60 diff --git a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-channel-groups.xml b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-channel-groups.xml index 05ffed28ccc3a..fc2993650fd69 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-channel-groups.xml +++ b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-channel-groups.xml @@ -1,23 +1,24 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -25,13 +26,13 @@ Aggregate data (by day) - - - - - - - + + + + + + + @@ -39,13 +40,13 @@ Aggregate data (by week) - - - - - - - + + + + + + + @@ -53,13 +54,13 @@ Aggregate data (by month) - - - - - - - + + + + + + + @@ -67,13 +68,13 @@ Aggregate data (by year) - - - - - - - + + + + + + + diff --git a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-channel-types.xml b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-channel-types.xml index 7f683b8622df8..56f84772065cb 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-channel-types.xml +++ b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-channel-types.xml @@ -1,5 +1,6 @@ - @@ -52,7 +53,7 @@ - Number:Percent + Number:Dimensionless Current Charge Level @@ -117,7 +118,7 @@ - Number:Percent + Number:Dimensionless Self Consumption Coverage diff --git a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-thing.xml b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-thing.xml index 13da3a792fd8f..e081ebe1ee1d5 100644 --- a/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-thing.xml +++ b/bundles/org.openhab.binding.solaredge/src/main/resources/ESH-INF/thing/generic-thing.xml @@ -1,5 +1,6 @@ - @@ -7,13 +8,13 @@ data retrieved from SolarEdge web interface - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.solarlog/pom.xml b/bundles/org.openhab.binding.solarlog/pom.xml index 87211e8412aec..bb40792f28639 100644 --- a/bundles/org.openhab.binding.solarlog/pom.xml +++ b/bundles/org.openhab.binding.solarlog/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.solarlog diff --git a/bundles/org.openhab.binding.solarlog/src/main/feature/feature.xml b/bundles/org.openhab.binding.solarlog/src/main/feature/feature.xml index 5d6c31c5aa63f..c515283b670cc 100644 --- a/bundles/org.openhab.binding.solarlog/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.solarlog/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.solarlog/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.solarlog/${project.version} + diff --git a/bundles/org.openhab.binding.solarlog/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.solarlog/src/main/resources/ESH-INF/binding/binding.xml index dac5f877e4fed..41bdaec5f3766 100644 --- a/bundles/org.openhab.binding.solarlog/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.solarlog/src/main/resources/ESH-INF/binding/binding.xml @@ -4,7 +4,11 @@ xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd"> Solar-Log Binding - This is the binding for the Solar-Log product range developed and sold by Solare Datensysteme GmbH. The Solar-Log devices allow monitoring of Photovoltaic (PV) installations and provide a JSON API to extract data. This includes information about current energy production and use, and other vital parameters of a PV installation. This binding makes this data accessible to openHAB from where it can be persistently stored, used to trigger actions or be displayed for information. + This is the binding for the Solar-Log product range developed and sold by Solare Datensysteme GmbH. The + Solar-Log devices allow monitoring of Photovoltaic (PV) installations and provide a JSON API to extract data. This + includes information about current energy production and use, and other vital parameters of a PV installation. This + binding makes this data accessible to openHAB from where it can be persistently stored, used to trigger actions or be + displayed for information. Johann Richard diff --git a/bundles/org.openhab.binding.solarlog/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.solarlog/src/main/resources/ESH-INF/thing/thing-types.xml index c522c80ffb051..4d236039a21d7 100644 --- a/bundles/org.openhab.binding.solarlog/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.solarlog/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfymylink/.classpath b/bundles/org.openhab.binding.somfymylink/.classpath new file mode 100644 index 0000000000000..39abf1c5e9102 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/.classpath @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.somfymylink/.project b/bundles/org.openhab.binding.somfymylink/.project new file mode 100644 index 0000000000000..104819095ccf0 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/.project @@ -0,0 +1,23 @@ + + + org.openhab.binding.somfymylink + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.somfymylink/NOTICE b/bundles/org.openhab.binding.somfymylink/NOTICE new file mode 100644 index 0000000000000..4c20ef446c1e4 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/NOTICE @@ -0,0 +1,13 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab2-addons diff --git a/bundles/org.openhab.binding.somfymylink/README.md b/bundles/org.openhab.binding.somfymylink/README.md new file mode 100644 index 0000000000000..bde3b39634e62 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/README.md @@ -0,0 +1,65 @@ +# Somfy myLink Binding + +This binding supports the [Somfy myLink](https://www.somfysystems.com/en-us/products/1811403/mylink-) device for control of Somfy RTS blinds/shades. + +## Supported Things + +Currently these things are supported: + +- bridge (Somfy MyLink bridge, which can discover roller shades and scenes) +- roller shades (UP, DOWN, STOP control of a roller shade). + +This binding has been tested with myLink firmware 5.23. + +## Discovery + +To start a discovery: + +- install this binding +- open Paper UI +- add a new thing in menu Configuration/Things +- choose SomfyMyLink Binding and select Somfy MyLink Bridge +- enter it's IP Address and system id. The system id This can be found in the integration settings -> Control4 section of your My Link app + +If the supplied ip address and system id are correct, the automatic discovery starts immediately and detected roller shades appear in Paper UI inbox. + +## Thing Configuration + +### mylink + +| Parameter | Parameter ID | Required/Optional | Description | +|------------------|-------------------|-------------------|-------------| +| IP or Hostname | ipAddress | Required | Hostname or IP Address of the myLink device | +| System Id | systemId | Required | The system id configured on the myLink device | + +### shade + +| Parameter | Parameter ID | Required/Optional | Description | +|------------------|-------------------|-------------------|-------------| +| Target ID | targetId | Required | Address of shade in the Somfy system | + +### scene + +| Parameter | Parameter ID | Required/Optional | Description | +|------------------|-------------------|-------------------|-------------| +| Scene ID | sceneId | Required | Address of scene in the Somfy system | + +## Channels + +The following channels are supported by the binding. Note that specific weather station models may support only some or all of these channels. + +| Channel ID | Item Type | Description | +|---------------------------------|-------------------------|---------------------------------------------------------------| +| shadeControl | Rollershutter | Device control (UP, DOWN, STOP) | +| scenelist | String | Comma-separated list of scenes of form sceneId=sceneName | +| button | Switch | Button to trigger a scene or rule | + +## Example + +### Things + +``` +Bridge somfymylink:mylink:mylink1 "myLink Bridge" @ "Office" [ ipAddress="192.168.1.1", systemId="mysystemidhere" ] { + Thing shade shade1 "Living Room" [ targetId="CC114A21.1" ] +} +``` \ No newline at end of file diff --git a/bundles/org.openhab.binding.somfymylink/pom.xml b/bundles/org.openhab.binding.somfymylink/pom.xml new file mode 100644 index 0000000000000..fa97d7feeef9c --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/pom.xml @@ -0,0 +1,17 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 2.5.6-SNAPSHOT + + + org.openhab.binding.somfymylink + + openHAB Add-ons :: Bundles :: Somfy MyLink Binding + + diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/SomfyMyLinkBindingConstants.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/SomfyMyLinkBindingConstants.java new file mode 100644 index 0000000000000..69ed4b06c4972 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/SomfyMyLinkBindingConstants.java @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.ThingTypeUID; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkBindingConstants { + + private static final String BINDING_ID = "somfymylink"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_SHADE = new ThingTypeUID(BINDING_ID, "shade"); + public static final ThingTypeUID THING_TYPE_SCENE = new ThingTypeUID(BINDING_ID, "scene"); + public static final ThingTypeUID THING_TYPE_MYLINK = new ThingTypeUID(BINDING_ID, "mylink"); + + // List of all Channel ids + public static final String CHANNEL_SHADELEVEL = "shadelevel"; + public static final String CHANNEL_SCENECONTROL = "scenecontrol"; + public static final String CHANNEL_SCENES = "sceneid"; + + // Thing config properties + public static final String TARGET_ID = "targetId"; + public static final String SCENE_ID = "sceneId"; +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/SomfyMyLinkHandlerFactory.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/SomfyMyLinkHandlerFactory.java new file mode 100644 index 0000000000000..ff9fbdd6ae631 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/SomfyMyLinkHandlerFactory.java @@ -0,0 +1,81 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal; + +import static org.openhab.binding.somfymylink.internal.SomfyMyLinkBindingConstants.*; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.somfymylink.internal.handler.SomfyMyLinkBridgeHandler; +import org.openhab.binding.somfymylink.internal.handler.SomfyMyLinkStateDescriptionOptionsProvider; +import org.openhab.binding.somfymylink.internal.handler.SomfySceneHandler; +import org.openhab.binding.somfymylink.internal.handler.SomfyShadeHandler; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.somfymylink", service = ThingHandlerFactory.class) +public class SomfyMyLinkHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>( + Arrays.asList(THING_TYPE_MYLINK, THING_TYPE_SHADE, THING_TYPE_SCENE)); + + public static final Set DISCOVERABLE_DEVICE_TYPES_UIDS = new HashSet<>( + Arrays.asList(THING_TYPE_SHADE, THING_TYPE_SCENE)); + + private @Nullable SomfyMyLinkStateDescriptionOptionsProvider stateDescriptionProvider; + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (thingTypeUID.equals(THING_TYPE_MYLINK)) { + return new SomfyMyLinkBridgeHandler((Bridge) thing, stateDescriptionProvider); + } + if (THING_TYPE_SHADE.equals(thingTypeUID)) { + return new SomfyShadeHandler(thing); + } + if (THING_TYPE_SCENE.equals(thingTypeUID)) { + return new SomfySceneHandler(thing); + } + + return null; + } + + @Reference + protected void setDynamicStateDescriptionProvider(SomfyMyLinkStateDescriptionOptionsProvider provider) { + this.stateDescriptionProvider = provider; + } + + protected void unsetDynamicStateDescriptionProvider(SomfyMyLinkStateDescriptionOptionsProvider provider) { + this.stateDescriptionProvider = null; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/config/SomfyMyLinkConfiguration.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/config/SomfyMyLinkConfiguration.java new file mode 100644 index 0000000000000..7ed4569b90967 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/config/SomfyMyLinkConfiguration.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link SomfyMyLinkConfiguration} class contains fields mapping thing configuration parameters. + * + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkConfiguration { + public String ipAddress = ""; + + public String systemId = ""; +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/discovery/SomfyMyLinkDeviceDiscoveryService.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/discovery/SomfyMyLinkDeviceDiscoveryService.java new file mode 100644 index 0000000000000..f78b1ad8d8d41 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/discovery/SomfyMyLinkDeviceDiscoveryService.java @@ -0,0 +1,190 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.discovery; + +import static org.openhab.binding.somfymylink.internal.SomfyMyLinkBindingConstants.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; +import org.eclipse.smarthome.config.discovery.DiscoveryResult; +import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; +import org.eclipse.smarthome.config.discovery.DiscoveryService; +import org.eclipse.smarthome.config.discovery.ScanListener; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingTypeUID; +import org.eclipse.smarthome.core.thing.ThingUID; +import org.eclipse.smarthome.core.thing.binding.ThingHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; +import org.openhab.binding.somfymylink.internal.SomfyMyLinkHandlerFactory; +import org.openhab.binding.somfymylink.internal.handler.SomfyMyLinkBridgeHandler; +import org.openhab.binding.somfymylink.internal.handler.SomfyMyLinkException; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkScene; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkShade; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Deactivate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link SomfyMyLinkDeviceDiscoveryService} is responsible discovering things connected to the mylink. + * + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkDeviceDiscoveryService extends AbstractDiscoveryService + implements DiscoveryService, ThingHandlerService { + + private static final int DISCOVERY_REFRESH_SEC = 900; + + private final Logger logger = LoggerFactory.getLogger(SomfyMyLinkDeviceDiscoveryService.class); + private @NonNullByDefault({}) SomfyMyLinkBridgeHandler mylinkHandler; + private @Nullable Future scanTask; + private @Nullable ScheduledFuture discoveryJob; + + public SomfyMyLinkDeviceDiscoveryService() { + super(SomfyMyLinkHandlerFactory.DISCOVERABLE_DEVICE_TYPES_UIDS, 10); + } + + @Override + public void setThingHandler(@Nullable ThingHandler handler) { + if (handler instanceof SomfyMyLinkBridgeHandler) { + this.mylinkHandler = (SomfyMyLinkBridgeHandler) handler; + } + } + + @Override + public @Nullable ThingHandler getThingHandler() { + return mylinkHandler; + } + + @Override + @Activate + public void activate() { + super.activate(null); + } + + @Override + @Deactivate + public void deactivate() { + super.deactivate(); + } + + @Override + protected void startBackgroundDiscovery() { + logger.debug("Starting Somfy My Link background discovery"); + + ScheduledFuture discoveryJob = this.discoveryJob; + if (discoveryJob == null || discoveryJob.isCancelled()) { + discoveryJob = scheduler.scheduleWithFixedDelay(this::discoverDevices, 10, DISCOVERY_REFRESH_SEC, + TimeUnit.SECONDS); + } + } + + @Override + protected void stopBackgroundDiscovery() { + logger.debug("Stopping Somfy MyLink background discovery"); + + ScheduledFuture discoveryJob = this.discoveryJob; + if (discoveryJob != null) { + discoveryJob.cancel(true); + this.discoveryJob = null; + } + } + + @Override + protected synchronized void startScan() { + Future scanTask = this.scanTask; + if (scanTask == null || scanTask.isDone()) { + logger.debug("Starting somfy mylink discovery scan"); + scanTask = scheduler.submit(this::discoverDevices); + } + } + + @Override + public void stopScan() { + Future scanTask = this.scanTask; + if (scanTask != null) { + logger.debug("Stopping somfy mylink discovery scan"); + scanTask.cancel(true); + } + super.stopScan(); + } + + private synchronized void discoverDevices() { + logger.info("Scanning for things..."); + + if (this.mylinkHandler.getThing().getStatus() != ThingStatus.ONLINE) { + logger.info("Skipping device discover as bridge is {}", this.mylinkHandler.getThing().getStatus()); + return; + } + + try { + // get the shade list + SomfyMyLinkShade[] shades = this.mylinkHandler.getShadeList(); + + for (SomfyMyLinkShade shade : shades) { + String id = shade.getTargetID(); + String label = "Somfy Shade " + shade.getName(); + + if (id != null) { + logger.debug("Adding device {}", id); + notifyThingDiscovery(THING_TYPE_SHADE, id, label, TARGET_ID); + } + } + + SomfyMyLinkScene[] scenes = this.mylinkHandler.getSceneList(); + + for (SomfyMyLinkScene scene : scenes) { + String id = scene.getTargetID(); + String label = "Somfy Scene " + scene.getName(); + + logger.debug("Adding device {}", id); + notifyThingDiscovery(THING_TYPE_SCENE, id, label, SCENE_ID); + } + } catch (SomfyMyLinkException e) { + logger.warn("Error scanning for devices: {}", e.getMessage(), e); + ScanListener scanListener = this.scanListener; + if (scanListener != null) { + scanListener.onErrorOccurred(e); + } + } + } + + private void notifyThingDiscovery(ThingTypeUID thingTypeUID, String id, String label, String idType) { + if (id.isEmpty()) { + logger.info("Discovered {} with no ID", label); + return; + } + + ThingUID bridgeUID = this.mylinkHandler.getThing().getUID(); + ThingUID uid = new ThingUID(thingTypeUID, bridgeUID, id); + + Map properties = new HashMap<>(); + + properties.put(idType, id); + + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withBridge(bridgeUID).withLabel(label) + .withProperties(properties).withRepresentationProperty(idType).build(); + + thingDiscovered(result); + + logger.debug("Discovered {}", uid); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkBridgeHandler.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkBridgeHandler.java new file mode 100644 index 0000000000000..ed8b02cb8e9fe --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkBridgeHandler.java @@ -0,0 +1,387 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.handler; + +import static org.openhab.binding.somfymylink.internal.SomfyMyLinkBindingConstants.*; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.Writer; +import java.net.Socket; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.common.NamedThreadFactory; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; +import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; +import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.core.types.RefreshType; +import org.eclipse.smarthome.core.types.StateOption; +import org.openhab.binding.somfymylink.internal.SomfyMyLinkBindingConstants; +import org.openhab.binding.somfymylink.internal.config.SomfyMyLinkConfiguration; +import org.openhab.binding.somfymylink.internal.discovery.SomfyMyLinkDeviceDiscoveryService; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkCommandBase; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkCommandSceneList; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkCommandSceneSet; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkCommandShadeDown; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkCommandShadeList; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkCommandShadePing; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkCommandShadeStop; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkCommandShadeUp; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkErrorResponse; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkPingResponse; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkResponseBase; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkScene; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkScenesResponse; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkShade; +import org.openhab.binding.somfymylink.internal.model.SomfyMyLinkShadesResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * The {@link SomfyMyLinkBridgeHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkBridgeHandler extends BaseBridgeHandler { + + private final Logger logger = LoggerFactory.getLogger(SomfyMyLinkBridgeHandler.class); + private static final int HEARTBEAT_MINUTES = 2; + private static final int MYLINK_PORT = 44100; + private static final int MYLINK_DEFAULT_TIMEOUT = 5000; + private static final int CONNECTION_DELAY = 1000; + private static final SomfyMyLinkShade[] EMPTY_SHADE_LIST = new SomfyMyLinkShade[0]; + private static final SomfyMyLinkScene[] EMPTY_SCENE_LIST = new SomfyMyLinkScene[0]; + + private SomfyMyLinkConfiguration config = new SomfyMyLinkConfiguration(); + private @Nullable ScheduledFuture heartbeat; + private @Nullable SomfyMyLinkStateDescriptionOptionsProvider stateDescriptionProvider; + private @Nullable ExecutorService commandExecutor; + + // Gson & parser + private final Gson gson = new Gson(); + + public SomfyMyLinkBridgeHandler(Bridge bridge, + @Nullable SomfyMyLinkStateDescriptionOptionsProvider stateDescriptionProvider) { + super(bridge); + this.stateDescriptionProvider = stateDescriptionProvider; + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + logger.debug("Command received on mylink {}", command); + + try { + if (CHANNEL_SCENES.equals(channelUID.getId())) { + if (command instanceof RefreshType) { + return; + } + + if (command instanceof StringType) { + Integer sceneId = Integer.decode(command.toString()); + commandScene(sceneId); + } + } + } catch (SomfyMyLinkException e) { + logger.info("Error handling command: {}", e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + @Override + public void initialize() { + logger.info("Initializing mylink"); + config = getThing().getConfiguration().as(SomfyMyLinkConfiguration.class); + + commandExecutor = Executors.newSingleThreadExecutor(new NamedThreadFactory(thing.getUID().getAsString(), true)); + + if (validConfiguration(config)) { + // start the keepalive process + if (heartbeat == null) { + logger.info("Starting heartbeat job every {} min", HEARTBEAT_MINUTES); + heartbeat = this.scheduler.scheduleWithFixedDelay(this::sendHeartbeat, 0, HEARTBEAT_MINUTES, + TimeUnit.MINUTES); + } + } + } + + @Override + public Collection> getServices() { + return Collections.singleton(SomfyMyLinkDeviceDiscoveryService.class); + } + + private boolean validConfiguration(@Nullable SomfyMyLinkConfiguration config) { + if (config == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "mylink configuration missing"); + return false; + } + + if (config.ipAddress.isEmpty() || config.systemId.isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "mylink address or system id not specified"); + return false; + } + + return true; + } + + private void cancelHeartbeat() { + logger.debug("Stopping heartbeat"); + ScheduledFuture heartbeat = this.heartbeat; + + if (heartbeat != null) { + logger.debug("Cancelling heartbeat job"); + heartbeat.cancel(true); + this.heartbeat = null; + } else { + logger.debug("Heartbeat was not active"); + } + } + + private void sendHeartbeat() { + try { + logger.debug("Sending heartbeat"); + + SomfyMyLinkCommandShadePing command = new SomfyMyLinkCommandShadePing(config.systemId); + sendCommandWithResponse(command, SomfyMyLinkPingResponse.class).get(); + updateStatus(ThingStatus.ONLINE); + + } catch (SomfyMyLinkException | InterruptedException | ExecutionException e) { + logger.warn("Problem with mylink during heartbeat: {}", e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + public SomfyMyLinkShade[] getShadeList() throws SomfyMyLinkException { + SomfyMyLinkCommandShadeList command = new SomfyMyLinkCommandShadeList(config.systemId); + + try { + SomfyMyLinkShadesResponse response = sendCommandWithResponse(command, SomfyMyLinkShadesResponse.class) + .get(); + + if (response != null) { + return response.getResult(); + } else { + return EMPTY_SHADE_LIST; + } + } catch (InterruptedException | ExecutionException e) { + throw new SomfyMyLinkException("Problem while getting shade list.", e); + } + } + + public SomfyMyLinkScene[] getSceneList() throws SomfyMyLinkException { + SomfyMyLinkCommandSceneList command = new SomfyMyLinkCommandSceneList(config.systemId); + SomfyMyLinkStateDescriptionOptionsProvider stateDescriptionProvider = this.stateDescriptionProvider; + + try { + SomfyMyLinkScenesResponse response = sendCommandWithResponse(command, SomfyMyLinkScenesResponse.class) + .get(); + + if (response != null && stateDescriptionProvider != null) { + List options = new ArrayList<>(); + for (SomfyMyLinkScene scene : response.result) { + options.add(new StateOption(scene.getTargetID(), scene.getName())); + } + + logger.debug("Setting {} options on bridge", options.size()); + + stateDescriptionProvider.setStateOptions( + new ChannelUID(getThing().getUID(), SomfyMyLinkBindingConstants.CHANNEL_SCENES), options); + + return response.getResult(); + } else { + return EMPTY_SCENE_LIST; + } + } catch (InterruptedException | ExecutionException e) { + throw new SomfyMyLinkException("Problem getting scene list.", e); + } + } + + public void commandShadeUp(String targetId) throws SomfyMyLinkException { + SomfyMyLinkCommandShadeUp cmd = new SomfyMyLinkCommandShadeUp(targetId, config.systemId); + sendCommand(cmd); + } + + public void commandShadeDown(String targetId) throws SomfyMyLinkException { + SomfyMyLinkCommandShadeDown cmd = new SomfyMyLinkCommandShadeDown(targetId, config.systemId); + sendCommand(cmd); + } + + public void commandShadeStop(String targetId) throws SomfyMyLinkException { + SomfyMyLinkCommandShadeStop cmd = new SomfyMyLinkCommandShadeStop(targetId, config.systemId); + sendCommand(cmd); + } + + public void commandScene(Integer sceneId) throws SomfyMyLinkException { + SomfyMyLinkCommandSceneSet cmd = new SomfyMyLinkCommandSceneSet(sceneId, config.systemId); + sendCommand(cmd); + } + + private CompletableFuture<@Nullable Void> sendCommand(SomfyMyLinkCommandBase command) { + CompletableFuture<@Nullable Void> future = new CompletableFuture<>(); + ExecutorService commandExecutor = this.commandExecutor; + if (commandExecutor != null) { + commandExecutor.execute(() -> { + String json = gson.toJson(command); + try (Socket socket = getConnection(); + Writer out = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.US_ASCII)) { + logger.debug("Sending: {}", json); + out.write(json); + out.flush(); + logger.debug("Sent: {}", json); + + // give time for mylink to process + Thread.sleep(CONNECTION_DELAY); + } catch (SocketTimeoutException e) { + logger.warn("Timeout sending command to mylink: {} Message: {}", json, e.getMessage()); + } catch (IOException e) { + logger.warn("Problem sending command to mylink: {} Message: {}", json, e.getMessage()); + } catch (InterruptedException e) { + logger.warn("Interrupted while waiting after sending command to mylink: {} Message: {}", json, + e.getMessage()); + } catch (Exception e) { + logger.warn("Unexpected exception while sending command to mylink: {} Message: {}", json, + e.getMessage()); + } + future.complete(null); + }); + } else { + future.complete(null); + } + + return future; + } + + private CompletableFuture<@Nullable T> sendCommandWithResponse( + SomfyMyLinkCommandBase command, Class responseType) { + CompletableFuture<@Nullable T> future = new CompletableFuture<>(); + ExecutorService commandExecutor = this.commandExecutor; + if (commandExecutor != null) { + commandExecutor.submit(() -> { + String json = gson.toJson(command); + + try (Socket socket = getConnection(); + Writer out = new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.US_ASCII); + BufferedReader in = new BufferedReader( + new InputStreamReader(socket.getInputStream(), StandardCharsets.US_ASCII))) { + + // send the command + logger.debug("Sending: {}", json); + out.write(json); + out.flush(); + + // read the response + try { + T response = parseResponse(in, responseType); + future.complete(response); + Thread.sleep(CONNECTION_DELAY); + return; + } catch (SomfyMyLinkException e) { + future.completeExceptionally(e); + return; + } + } catch (SocketTimeoutException e) { + logger.warn("Timeout sending command to mylink: {} Message: {}", json, e.getMessage()); + future.completeExceptionally(new SomfyMyLinkException("Timeout sending command to mylink", e)); + } catch (IOException e) { + logger.warn("Problem sending command to mylink: {} Message: {}", json, e.getMessage()); + future.completeExceptionally(new SomfyMyLinkException("Problem sending command to mylink", e)); + } catch (InterruptedException e) { + logger.warn("Interrupted while waiting after sending command to mylink: {} Message: {}", json, + e.getMessage()); + future.complete(null); + } catch (Exception e) { + logger.warn("Unexpected exception while sending command to mylink: {} Message: {}", json, + e.getMessage()); + future.completeExceptionally(e); + } + }); + } else { + future.complete(null); + } + return future; + } + + private T parseResponse(Reader reader, Class responseType) { + JsonParser parser = new JsonParser(); + JsonObject jsonObj = parser.parse(gson.newJsonReader(reader)).getAsJsonObject(); + + logger.debug("Got full message: {}", jsonObj.toString()); + + if (jsonObj.has("error")) { + SomfyMyLinkErrorResponse errorResponse = gson.fromJson(jsonObj, SomfyMyLinkErrorResponse.class); + logger.info("Error parsing mylink response: {}", errorResponse.error.message); + throw new SomfyMyLinkException("Incomplete message."); + } + + return gson.fromJson(jsonObj, responseType); + } + + private Socket getConnection() throws IOException, SomfyMyLinkException { + try { + logger.debug("Getting connection to mylink on: {} Post: {}", config.ipAddress, MYLINK_PORT); + String myLinkAddress = config.ipAddress; + Socket socket = new Socket(myLinkAddress, MYLINK_PORT); + socket.setSoTimeout(MYLINK_DEFAULT_TIMEOUT); + return socket; + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + throw e; + } + } + + @Override + public void thingUpdated(Thing thing) { + SomfyMyLinkConfiguration newConfig = thing.getConfiguration().as(SomfyMyLinkConfiguration.class); + config = newConfig; + } + + @Override + public void dispose() { + cancelHeartbeat(); + dispose(commandExecutor); + } + + private static void dispose(@Nullable ExecutorService executor) { + if (executor != null) { + executor.shutdownNow(); + } + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkException.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkException.java new file mode 100644 index 0000000000000..374caf6125932 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkException.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link SomfyMyLinkException} is for throwing errors from the mylink binding + * + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public SomfyMyLinkException() { + super(); + } + + public SomfyMyLinkException(String message) { + super(message); + } + + public SomfyMyLinkException(String message, Throwable cause) { + super(message, cause); + } + + public SomfyMyLinkException(Throwable cause) { + super(cause); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkStateDescriptionOptionsProvider.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkStateDescriptionOptionsProvider.java new file mode 100644 index 0000000000000..df736baa7fe3d --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyMyLinkStateDescriptionOptionsProvider.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.handler; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.thing.binding.BaseDynamicStateDescriptionProvider; +import org.eclipse.smarthome.core.thing.i18n.ChannelTypeI18nLocalizationService; +import org.eclipse.smarthome.core.thing.type.DynamicStateDescriptionProvider; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * Dynamic provider of state options while leaving other state description fields as original. + * + * @author Gregory Moyer - Initial contribution + * @author Mark Hilbush - Adapted to squeezebox binding + */ +@Component(service = { DynamicStateDescriptionProvider.class, SomfyMyLinkStateDescriptionOptionsProvider.class }) +@NonNullByDefault +public class SomfyMyLinkStateDescriptionOptionsProvider extends BaseDynamicStateDescriptionProvider { + + @Reference + protected void setChannelTypeI18nLocalizationService( + final ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) { + this.channelTypeI18nLocalizationService = channelTypeI18nLocalizationService; + } + + protected void unsetChannelTypeI18nLocalizationService( + final ChannelTypeI18nLocalizationService channelTypeI18nLocalizationService) { + this.channelTypeI18nLocalizationService = null; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfySceneHandler.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfySceneHandler.java new file mode 100644 index 0000000000000..d7f5716a64051 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfySceneHandler.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.handler; + +import static org.openhab.binding.somfymylink.internal.SomfyMyLinkBindingConstants.CHANNEL_SCENECONTROL; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.BridgeHandler; +import org.eclipse.smarthome.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link SomfySceneHandler} is responsible for handling commands for scenes + * + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfySceneHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(SomfySceneHandler.class); + + public SomfySceneHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + updateStatus(ThingStatus.ONLINE); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + try { + if (CHANNEL_SCENECONTROL.equals(channelUID.getId()) && command instanceof OnOffType) { + Integer targetId = Integer.decode(channelUID.getThingUID().getId()); + + if (command.equals(OnOffType.ON)) { + getBridgeHandler().commandScene(targetId); + updateState(channelUID, OnOffType.OFF); + } + } + } catch (SomfyMyLinkException e) { + logger.warn("Error handling command: {}", e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + protected SomfyMyLinkBridgeHandler getBridgeHandler() { + Bridge bridge = this.getBridge(); + if (bridge == null) { + throw new SomfyMyLinkException("No bridge was found"); + } + + BridgeHandler handler = bridge.getHandler(); + if (handler == null) { + throw new SomfyMyLinkException("No handler was found"); + } + + return (SomfyMyLinkBridgeHandler) handler; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyShadeHandler.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyShadeHandler.java new file mode 100644 index 0000000000000..62c5a664e40fb --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/handler/SomfyShadeHandler.java @@ -0,0 +1,117 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.handler; + +import static org.openhab.binding.somfymylink.internal.SomfyMyLinkBindingConstants.CHANNEL_SHADELEVEL; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.smarthome.core.library.types.StopMoveType; +import org.eclipse.smarthome.core.library.types.UpDownType; +import org.eclipse.smarthome.core.thing.Bridge; +import org.eclipse.smarthome.core.thing.ChannelUID; +import org.eclipse.smarthome.core.thing.Thing; +import org.eclipse.smarthome.core.thing.ThingStatus; +import org.eclipse.smarthome.core.thing.ThingStatusDetail; +import org.eclipse.smarthome.core.thing.ThingStatusInfo; +import org.eclipse.smarthome.core.thing.binding.BaseThingHandler; +import org.eclipse.smarthome.core.thing.binding.BridgeHandler; +import org.eclipse.smarthome.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link SomfyShadeHandler} is responsible for handling commands for shades + * + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyShadeHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(SomfyShadeHandler.class); + + public SomfyShadeHandler(Thing thing) { + super(thing); + } + + @Override + public void initialize() { + initDeviceState(); + } + + @Override + public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { + logger.info("Bridge status changed to {} updating {}", bridgeStatusInfo.getStatus(), getThing().getLabel()); + + if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE + && getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_OFFLINE) { + initDeviceState(); + } else if (bridgeStatusInfo.getStatus() == ThingStatus.OFFLINE) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + } + } + + public void initDeviceState() { + Bridge bridge = getBridge(); + + if (bridge == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bridge configured"); + logger.debug("Initialized device state for shade {} {}", ThingStatus.OFFLINE, + ThingStatusDetail.CONFIGURATION_ERROR); + } else if (bridge.getStatus() == ThingStatus.ONLINE) { + updateStatus(ThingStatus.ONLINE); + logger.debug("Initialized device state for shade {}", ThingStatus.ONLINE); + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + logger.debug("Initialized device state for shade {} {}", ThingStatus.OFFLINE, + ThingStatusDetail.BRIDGE_OFFLINE); + } + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + try { + if (CHANNEL_SHADELEVEL.equals(channelUID.getId())) { + String targetId = channelUID.getThingUID().getId(); + + if (command instanceof UpDownType) { + if (command.equals(UpDownType.DOWN)) { + getBridgeHandler().commandShadeDown(targetId); + } else { + getBridgeHandler().commandShadeUp(targetId); + } + } + + if (command instanceof StopMoveType) { + getBridgeHandler().commandShadeStop(targetId); + } + } + } catch (SomfyMyLinkException e) { + logger.warn("Error handling command: {}", e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); + } + } + + protected SomfyMyLinkBridgeHandler getBridgeHandler() { + Bridge bridge = this.getBridge(); + if (bridge == null) { + throw new SomfyMyLinkException("No bridge was found"); + } + + BridgeHandler handler = bridge.getHandler(); + if (handler == null) { + throw new SomfyMyLinkException("No handler was found"); + } + + return (SomfyMyLinkBridgeHandler) handler; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandBase.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandBase.java new file mode 100644 index 0000000000000..1c6c8d138b887 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandBase.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import java.util.concurrent.ThreadLocalRandom; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandBase { + + public final int id; + + public SomfyMyLinkCommandBase() { + this.id = ThreadLocalRandom.current().nextInt(1, 1000); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandParamsBase.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandParamsBase.java new file mode 100644 index 0000000000000..31f45ba4ee0bb --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandParamsBase.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandParamsBase { + + public final String auth; + + public SomfyMyLinkCommandParamsBase(String auth) { + this.auth = auth; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneBase.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneBase.java new file mode 100644 index 0000000000000..14a4b70b83be7 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneBase.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 +*/ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandSceneBase extends SomfyMyLinkCommandBase { + + public final String method; + public final SomfyMyLinkCommandSceneParams params; + + public SomfyMyLinkCommandSceneBase(int sceneId, String method, String auth) { + this.method = method; + this.params = new SomfyMyLinkCommandSceneParams(sceneId, auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneList.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneList.java new file mode 100644 index 0000000000000..2c9fd70051765 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneList.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandSceneList extends SomfyMyLinkCommandShadeBase { + public SomfyMyLinkCommandSceneList(String auth) { + super("*.*", "mylink.scene.list", auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneParams.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneParams.java new file mode 100644 index 0000000000000..f8e346a2d529b --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneParams.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandSceneParams extends SomfyMyLinkCommandParamsBase { + + public final int sceneId; + + public SomfyMyLinkCommandSceneParams(int sceneId, String auth) { + super(auth); + this.sceneId = sceneId; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneSet.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneSet.java new file mode 100644 index 0000000000000..816e89d91d0fd --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandSceneSet.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandSceneSet extends SomfyMyLinkCommandSceneBase { + public SomfyMyLinkCommandSceneSet(int sceneId, String auth) { + super(sceneId, "mylink.scene.run", auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeBase.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeBase.java new file mode 100644 index 0000000000000..69afe9700ac0d --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeBase.java @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 +*/ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandShadeBase extends SomfyMyLinkCommandBase { + + public final String method; + public final SomfyMyLinkCommandShadeParams params; + + public SomfyMyLinkCommandShadeBase(String targetId, String method, String auth) { + this.method = method; + this.params = new SomfyMyLinkCommandShadeParams(targetId, auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeDown.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeDown.java new file mode 100644 index 0000000000000..61d64d0f73632 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeDown.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandShadeDown extends SomfyMyLinkCommandShadeBase { + + public SomfyMyLinkCommandShadeDown(String targetId, String auth) { + super(targetId, "mylink.move.down", auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeList.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeList.java new file mode 100644 index 0000000000000..951d4b855f9bd --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeList.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandShadeList extends SomfyMyLinkCommandShadeBase { + + public SomfyMyLinkCommandShadeList(String auth) { + super("*.*", "mylink.status.info", auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeParams.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeParams.java new file mode 100644 index 0000000000000..27719cc321c53 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeParams.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandShadeParams extends SomfyMyLinkCommandParamsBase { + + public final String targetId; + + public SomfyMyLinkCommandShadeParams(String targetId, String auth) { + super(auth); + this.targetId = targetId.replace('-', '.'); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadePing.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadePing.java new file mode 100644 index 0000000000000..723fa65ca2df0 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadePing.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandShadePing extends SomfyMyLinkCommandShadeBase { + + public SomfyMyLinkCommandShadePing(String auth) { + super("*.*", "mylink.status.ping", auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeStop.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeStop.java new file mode 100644 index 0000000000000..d493b2658b17d --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeStop.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandShadeStop extends SomfyMyLinkCommandShadeBase { + + public SomfyMyLinkCommandShadeStop(String targetId, String auth) { + super(targetId, "mylink.move.stop", auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeUp.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeUp.java new file mode 100644 index 0000000000000..9c45876280d51 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkCommandShadeUp.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ + +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkCommandShadeUp extends SomfyMyLinkCommandShadeBase { + + public SomfyMyLinkCommandShadeUp(String targetId, String auth) { + super(targetId, "mylink.move.up", auth); + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkError.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkError.java new file mode 100644 index 0000000000000..8e02254cbcaef --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkError.java @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkError { + + public String code = ""; + + public String message = ""; +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkErrorResponse.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkErrorResponse.java new file mode 100644 index 0000000000000..eed7ece48776b --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkErrorResponse.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkErrorResponse extends SomfyMyLinkResponseBase { + + public SomfyMyLinkError error = new SomfyMyLinkError(); + + public @Nullable SomfyMyLinkError getError() { + return error; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkPingResponse.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkPingResponse.java new file mode 100644 index 0000000000000..5f27584417110 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkPingResponse.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkPingResponse extends SomfyMyLinkResponseBase { + + public String[] result = new String[0]; + + public String[] getResult() { + return result; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkResponseBase.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkResponseBase.java new file mode 100644 index 0000000000000..77e4e1033c13e --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkResponseBase.java @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkResponseBase { + + public @Nullable String jsonrpc; + + public @Nullable String id; + + public @Nullable String getId() { + return id; + } + + public @Nullable String getJsonRpc() { + return jsonrpc; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkScene.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkScene.java new file mode 100644 index 0000000000000..9b8810df9c046 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkScene.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkScene { + + private String sceneID = ""; + + private String name = ""; + + public String getTargetID() { + return sceneID; + } + + public String getName() { + return name; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkScenesResponse.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkScenesResponse.java new file mode 100644 index 0000000000000..aa716d6f2729d --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkScenesResponse.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkScenesResponse extends SomfyMyLinkResponseBase { + + public SomfyMyLinkScene[] result = new SomfyMyLinkScene[0]; + + public SomfyMyLinkScene[] getResult() { + return result; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkShade.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkShade.java new file mode 100644 index 0000000000000..f779faa52ec1f --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkShade.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkShade { + + private @Nullable String targetID; + + private @Nullable String name; + + public @Nullable String getTargetID() { + String targetID = this.targetID; + return targetID != null ? targetID.replace('.', '-') : null; + } + + public @Nullable String getName() { + return name; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkShadesResponse.java b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkShadesResponse.java new file mode 100644 index 0000000000000..4d62c60a5d241 --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/java/org/openhab/binding/somfymylink/internal/model/SomfyMyLinkShadesResponse.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.somfymylink.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * @author Chris Johnson - Initial contribution + */ +@NonNullByDefault +public class SomfyMyLinkShadesResponse extends SomfyMyLinkResponseBase { + + public SomfyMyLinkShade[] result = new SomfyMyLinkShade[0]; + + public SomfyMyLinkShade[] getResult() { + return result; + } +} diff --git a/bundles/org.openhab.binding.somfymylink/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.somfymylink/src/main/resources/ESH-INF/binding/binding.xml new file mode 100644 index 0000000000000..32c5789abcf6e --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/resources/ESH-INF/binding/binding.xml @@ -0,0 +1,10 @@ + + + + Somfy MyLink Binding + This is the binding for Somfy MyLink. + Chris Johnson + + diff --git a/bundles/org.openhab.binding.somfymylink/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.somfymylink/src/main/resources/ESH-INF/thing/thing-types.xml new file mode 100644 index 0000000000000..6145de863201c --- /dev/null +++ b/bundles/org.openhab.binding.somfymylink/src/main/resources/ESH-INF/thing/thing-types.xml @@ -0,0 +1,85 @@ + + + + + + + Somfy MyLink bridge enabling communication with Somfy devices + + + + + + network-address + + The IP or hostname of the Somfy MyLink + + + + The system id of the My Link bridge. This can be found in the integration settings on your My Link app + + + + + + + + + + + Scene control + + + + + + + + Address of scene in the Somfy system + + + + + + + + + + + Controls shades + + + + + + + + Address of shade in the Somfy system + + + + + + String + + Comma-separated list of scenes of form sceneId=sceneName + + + + + Rollershutter + + Device control (UP, DOWN, MY/STOP, closure 0-100%) + + + + Switch + + Button to trigger a scene or rule + Switch + + + diff --git a/bundles/org.openhab.binding.somfytahoma/README.md b/bundles/org.openhab.binding.somfytahoma/README.md index a3dc493d77d75..5fbab7c3ef07e 100644 --- a/bundles/org.openhab.binding.somfytahoma/README.md +++ b/bundles/org.openhab.binding.somfytahoma/README.md @@ -60,59 +60,63 @@ Please see the example below. ## Channels -| Thing | Channel | Note | -|-------------------------------------------------------------------------------|:---------------------:|------------------------------------------------------------------------------------------------------------------| -| bridge | N.A | bridge does not expose any channel | -| gateway | status | status of your Tahoma gateway | -| gate | gate_command | used for controlling your gate (open, close, stop, pedestrian) | -| gate | gate_state | get state of your gate | -| roller shutter, screen, venetian blind, garage door, awning, pergola, curtain | control | device controller which reacts to commands UP/DOWN/ON/OFF/OPEN/CLOSE/MY/STOP + closure 0-100 | -| window | control | device controller which reacts to commands UP/DOWN/ON/OFF/OPEN/CLOSE/STOP + closure 0-100 | -| silent roller shutter | silent_control | similar to control channel but in silent mode | -| venetian blind, adjustable slats roller shutter | orientation | percentual orientation of the blind's slats, it can have value 0-100). For IO Homecontrol devices only (non RTS) | -| adjustable slats roller shutter | rocker | used for setting the rocker position of the roller shutter, the only position allowing the slats control | -| action group | execute_action | switch which reacts to ON command and triggers the predefined Tahoma action | -| onoff, light | switch | reacts to standard ON/OFF commands | -| smoke sensor, occupancy sensor, contact sensor & water sensor | contact | normal value is CLOSE, changes to OPEN when detection triggered | -| smoke sensor, occupancy sensor, contact sensor & water sensor | sensor_defect | indicates the health of the sensor (dead, lowBatter, maintenanceRequired, noDefect) | -| smoke sensor | radio_battery | maintenance radio part battery state (low, normal) | -| smoke sensor | sensor_battery | maintenance sensor part battery state (absence, low, normal) | -| smoke sensor | short_check | triggering the smoke sensor's short check | -| smoke sensor | long_check | triggering the smoke sensor's long check | -| light sensor | luminance | light luminance value in luxes | -| electricity sensor | energy_consumption | energy consumption value in watts | -| humidity sensor | humidity | current relative humidity | -| dock | battery_status | indicates running on battery (yes/no) | -| dock | battery_level | remaining battery percentage | -| dock | siren_status | used for controlling and getting siren state (on, off, cyclic) | -| dock | short_beep | testing of dock's siren - short beep | -| dock | long_beep | testing of dock's siren - long beep | -| siren | battery | battery level full/low/normal/verylow | -| siren | onoff | controlling siren status ON/OFF | -| siren | memorized_volume | setting memorized volume (normal/highest) | -| pod | cyclic_button | pod cyclic button state | -| pod | battery_status | pod battery status state | -| pod | lighting_led_pod_mode | lighting LED pod mod state | -| interior alarm | alarm_command | used for sending commands to Somfy alarm device | -| interior alarm | intrusion_control | used for alarm external intrusion controlling | -| interior alarm, myfox alarm | alarm_state | state of the Somfy alarm | -| interior alarm | target_alarm_state | target state of the Somfy alarm | -| interior alarm, myfox alarm | intrusion_state | intrusion state of the Somfy alarm | -| external alarm | active_zones_state | state of external alarm active zones | -| door lock | lock | switch representing unlocked/locked state | -| door lock | open | switch representing open/close state | -| on/off heating system | target_heating_level | target heating level (off, eco, comfort, frostprotection) | -| heating system | current_temperature | current temperature of the heating system | -| heating system | current_state | current state of the heating system | -| heating system, thermostat | target_temperature | target temperature of the heating system | -| heating system, thermostat | battery_level | battery level of the heating system | -| thermostat | heating_mode | standard heating mode of the thermostat (away, freeze, manual, ...) | -| thermostat | derogation_heating_mode | derogation heating mode of the thermostat (away, freeze, manual, ...) | -| thermostat | derogation_activation | derogation activation state (inactive, active) | -| temperature sensor | temperature | temperature reported by the sensor | -| myfox camera, myfox alarm | cloud_status | cloud connection status | -| myfox camera | shutter | controlling of the camera shutter | -| myfox alarm | myfox_alarm_command | used for sending commands to Somfy Myfox alarm device | +| Thing | Channel | Note | +|-------------------------------------------------------------------------------|:---------------------:|-------------------------------------------------------------------------------------------------------------------------------| +| bridge | N.A | bridge does not expose any channel | +| gateway | status | status of your Tahoma gateway | +| gate | gate_command | used for controlling your gate (open, close, stop, pedestrian) | +| gate | gate_state | get state of your gate | +| roller shutter, screen, venetian blind, garage door, awning, pergola, curtain | control | device controller which reacts to commands UP/DOWN/ON/OFF/OPEN/CLOSE/MY/STOP + closure 0-100 | +| window | control | device controller which reacts to commands UP/DOWN/ON/OFF/OPEN/CLOSE/STOP + closure 0-100 | +| silent roller shutter | silent_control | similar to control channel but in silent mode | +| venetian blind, adjustable slats roller shutter | orientation | percentual orientation of the blind's slats, it can have value 0-100. For IO Homecontrol devices only (non RTS) | +| venetian blind, adjustable slats roller shutter | closure_orientation | percentual closure and orientation of the blind's slats, it can have value 0-100. For IO Homecontrol devices only (non RTS) | +| adjustable slats roller shutter | rocker | used for setting the rocker position of the roller shutter, the only position allowing the slats control | +| action group | execute_action | switch which reacts to ON command and triggers the predefined Tahoma action | +| onoff, light | switch | reacts to standard ON/OFF commands | +| smoke sensor, occupancy sensor, contact sensor & water sensor | contact | normal value is CLOSE, changes to OPEN when detection triggered | +| smoke sensor, occupancy sensor, contact sensor & water sensor | sensor_defect | indicates the health of the sensor (dead, lowBatter, maintenanceRequired, noDefect) | +| smoke sensor | radio_battery | maintenance radio part battery state (low, normal) | +| smoke sensor | sensor_battery | maintenance sensor part battery state (absence, low, normal) | +| smoke sensor | short_check | triggering the smoke sensor's short check | +| smoke sensor | long_check | triggering the smoke sensor's long check | +| light sensor | luminance | light luminance value in luxes | +| electricity sensor | energy_consumption | energy consumption value in watts | +| humidity sensor | humidity | current relative humidity | +| dock | battery_status | indicates running on battery (yes/no) | +| dock | battery_level | remaining battery percentage | +| dock | siren_status | used for controlling and getting siren state (on, off, cyclic) | +| dock | short_beep | testing of dock's siren - short beep | +| dock | long_beep | testing of dock's siren - long beep | +| siren | battery | battery level full/low/normal/verylow | +| siren | onoff | controlling siren status ON/OFF | +| siren | memorized_volume | setting memorized volume (normal/highest) | +| pod | cyclic_button | pod cyclic button state | +| pod | battery_status | pod battery status state | +| pod | lighting_led_pod_mode | lighting LED pod mod state | +| interior alarm | alarm_command | used for sending commands to Somfy alarm device | +| interior alarm | intrusion_control | used for alarm external intrusion controlling | +| interior alarm, myfox alarm | alarm_state | state of the Somfy alarm | +| interior alarm | target_alarm_state | target state of the Somfy alarm | +| interior alarm, myfox alarm | intrusion_state | intrusion state of the Somfy alarm | +| external alarm | active_zones_state | state of external alarm active zones | +| door lock | lock | switch representing unlocked/locked state | +| door lock | open | switch representing open/close state | +| on/off heating system | target_heating_level | target heating level (off, eco, comfort, frostprotection) | +| heating system | current_temperature | current temperature of the heating system | +| heating system | current_state | current state of the heating system | +| heating system, thermostat | target_temperature | target temperature of the heating system | +| heating system, thermostat | battery_level | battery level of the heating system | +| thermostat | heating_mode | standard heating mode of the thermostat (away, freeze, manual, ...) | +| thermostat | derogation_heating_mode | derogation heating mode of the thermostat (away, freeze, manual, ...) | +| thermostat | derogation_activation | derogation activation state (inactive, active) | +| temperature sensor | temperature | temperature reported by the sensor | +| myfox camera, myfox alarm | cloud_status | cloud connection status | +| myfox camera | shutter | controlling of the camera shutter | +| myfox alarm | myfox_alarm_command | used for sending commands to Somfy Myfox alarm device | + + +### Remarks All things which have a RSSI (relative received signal) state, expose a channel "rssi". @@ -124,11 +128,13 @@ When a roller shutter-like thing receives STOP command, there are two possible b If you want to set the MY position of a roller shutter and you don't care the possible movement, try sending the MOVE command (OH2 does not know MY, so it stands for "move to MY position") ``` -sendCommand(ROLLERSHUTTER_THING, MOVE) +CONTROL_CHANNEL.sendCommand(MOVE) ``` -or + +Blinds and adjustable slats roller shutters can control their closure and orientation by sending a comma separated string consisting of closure (0-100) and orientation (0-100) to the "closure_orientaion" channel. + ``` -ROLLERSHUTTER_THING.sendCommand(MOVE) +CLOSURE_ORIENTATION_CHANNEL.sendCommand("50,50") ``` ## Full Example diff --git a/bundles/org.openhab.binding.somfytahoma/pom.xml b/bundles/org.openhab.binding.somfytahoma/pom.xml index e113c255c3d37..c8134098b1443 100644 --- a/bundles/org.openhab.binding.somfytahoma/pom.xml +++ b/bundles/org.openhab.binding.somfytahoma/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.somfytahoma diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/feature/feature.xml b/bundles/org.openhab.binding.somfytahoma/src/main/feature/feature.xml index 9ccee3c5534bb..6e1e589a0f2d9 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - mvn:org.openhab.addons.bundles/org.openhab.binding.somfytahoma/${project.version} - + + openhab-runtime-base + openhab-transport-http + mvn:org.openhab.addons.bundles/org.openhab.binding.somfytahoma/${project.version} + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/SomfyTahomaBindingConstants.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/SomfyTahomaBindingConstants.java index a1c7b5b57dfc4..ff58f344457dd 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/SomfyTahomaBindingConstants.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/SomfyTahomaBindingConstants.java @@ -43,8 +43,7 @@ public class SomfyTahomaBindingConstants { "rollershutter_silent"); // Uno Roller Shutter - public static final ThingTypeUID THING_TYPE_ROLLERSHUTTER_UNO = new ThingTypeUID(BINDING_ID, - "rollershutter_uno"); + public static final ThingTypeUID THING_TYPE_ROLLERSHUTTER_UNO = new ThingTypeUID(BINDING_ID, "rollershutter_uno"); // Screen public static final ThingTypeUID THING_TYPE_SCREEN = new ThingTypeUID(BINDING_ID, "screen"); @@ -105,7 +104,8 @@ public class SomfyTahomaBindingConstants { // Heating system public static final ThingTypeUID THING_TYPE_HEATING_SYSTEM = new ThingTypeUID(BINDING_ID, "heatingsystem"); - public static final ThingTypeUID THING_TYPE_ONOFF_HEATING_SYSTEM = new ThingTypeUID(BINDING_ID, "onoffheatingsystem"); + public static final ThingTypeUID THING_TYPE_ONOFF_HEATING_SYSTEM = new ThingTypeUID(BINDING_ID, + "onoffheatingsystem"); // Door lock public static final ThingTypeUID THING_TYPE_DOOR_LOCK = new ThingTypeUID(BINDING_ID, "doorlock"); @@ -135,7 +135,8 @@ public class SomfyTahomaBindingConstants { public static final ThingTypeUID THING_TYPE_SIREN = new ThingTypeUID(BINDING_ID, "siren"); // Adjustable slats roller shutter - public static final ThingTypeUID THING_TYPE_ADJUSTABLE_SLATS_ROLLERSHUTTER = new ThingTypeUID(BINDING_ID, "adjustableslatsrollershutter"); + public static final ThingTypeUID THING_TYPE_ADJUSTABLE_SLATS_ROLLERSHUTTER = new ThingTypeUID(BINDING_ID, + "adjustableslatsrollershutter"); // MyFox Camera public static final ThingTypeUID THING_TYPE_MYFOX_CAMERA = new ThingTypeUID(BINDING_ID, "myfoxcamera"); @@ -160,6 +161,7 @@ public class SomfyTahomaBindingConstants { // Blind public static final String ORIENTATION = "orientation"; + public static final String CLOSURE_AND_ORIENTATION = "closure_orientation"; // Action group public static final String EXECUTE_ACTION = "execute_action"; @@ -183,7 +185,6 @@ public class SomfyTahomaBindingConstants { public static final String RADIO_BATTERY = "radio_battery"; public static final String SENSOR_BATTERY = "sensor_battery"; - // Light sensor public static final String LUMINANCE = "luminance"; @@ -268,6 +269,7 @@ public class SomfyTahomaBindingConstants { // Commands public static final String COMMAND_MY = "my"; public static final String COMMAND_SET_CLOSURE = "setClosure"; + public static final String COMMAND_SET_CLOSURE_ORIENTATION = "setClosureAndOrientation"; public static final String COMMAND_SET_DEPLOYMENT = "setDeployment"; public static final String COMMAND_SET_ORIENTATION = "setOrientation"; public static final String COMMAND_SET_CLOSURESPEED = "setClosureAndLinearSpeed"; @@ -344,19 +346,18 @@ public class SomfyTahomaBindingConstants { public static final String COMPLETED_EVENT = "COMPLETED"; // supported thing types for discovery - public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>(Arrays.asList( - THING_TYPE_GATEWAY, THING_TYPE_ROLLERSHUTTER, THING_TYPE_ROLLERSHUTTER_SILENT, THING_TYPE_SCREEN, - THING_TYPE_VENETIANBLIND, THING_TYPE_EXTERIORSCREEN, THING_TYPE_EXTERIORVENETIANBLIND, - THING_TYPE_GARAGEDOOR, THING_TYPE_AWNING, THING_TYPE_ACTIONGROUP, THING_TYPE_ONOFF, THING_TYPE_LIGHT, - THING_TYPE_LIGHTSENSOR, THING_TYPE_SMOKESENSOR, THING_TYPE_CONTACTSENSOR, THING_TYPE_OCCUPANCYSENSOR, - THING_TYPE_WINDOW, THING_TYPE_INTERNAL_ALARM, THING_TYPE_EXTERNAL_ALARM, THING_TYPE_POD, - THING_TYPE_HEATING_SYSTEM, THING_TYPE_ONOFF_HEATING_SYSTEM, THING_TYPE_DOOR_LOCK, THING_TYPE_PERGOLA, - THING_TYPE_WINDOW_HANDLE, THING_TYPE_TEMPERATURESENSOR, THING_TYPE_GATE, THING_TYPE_CURTAIN, - THING_TYPE_ELECTRICITYSENSOR, THING_TYPE_DOCK, THING_TYPE_SIREN, THING_TYPE_ADJUSTABLE_SLATS_ROLLERSHUTTER, - THING_TYPE_MYFOX_CAMERA, THING_TYPE_ROLLERSHUTTER_UNO, THING_TYPE_WATERSENSOR, THING_TYPE_HUMIDITYSENSOR, - THING_TYPE_MYFOX_ALARM, THING_TYPE_THERMOSTAT)); - - //somfy gateways + public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>(Arrays.asList(THING_TYPE_GATEWAY, + THING_TYPE_ROLLERSHUTTER, THING_TYPE_ROLLERSHUTTER_SILENT, THING_TYPE_SCREEN, THING_TYPE_VENETIANBLIND, + THING_TYPE_EXTERIORSCREEN, THING_TYPE_EXTERIORVENETIANBLIND, THING_TYPE_GARAGEDOOR, THING_TYPE_AWNING, + THING_TYPE_ACTIONGROUP, THING_TYPE_ONOFF, THING_TYPE_LIGHT, THING_TYPE_LIGHTSENSOR, THING_TYPE_SMOKESENSOR, + THING_TYPE_CONTACTSENSOR, THING_TYPE_OCCUPANCYSENSOR, THING_TYPE_WINDOW, THING_TYPE_INTERNAL_ALARM, + THING_TYPE_EXTERNAL_ALARM, THING_TYPE_POD, THING_TYPE_HEATING_SYSTEM, THING_TYPE_ONOFF_HEATING_SYSTEM, + THING_TYPE_DOOR_LOCK, THING_TYPE_PERGOLA, THING_TYPE_WINDOW_HANDLE, THING_TYPE_TEMPERATURESENSOR, + THING_TYPE_GATE, THING_TYPE_CURTAIN, THING_TYPE_ELECTRICITYSENSOR, THING_TYPE_DOCK, THING_TYPE_SIREN, + THING_TYPE_ADJUSTABLE_SLATS_ROLLERSHUTTER, THING_TYPE_MYFOX_CAMERA, THING_TYPE_ROLLERSHUTTER_UNO, + THING_TYPE_WATERSENSOR, THING_TYPE_HUMIDITYSENSOR, THING_TYPE_MYFOX_ALARM, THING_TYPE_THERMOSTAT)); + + // somfy gateways public static Map gatewayTypes = new HashMap() { { put(0, "VIRTUAL_KIZBOX"); diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/config/SomfyTahomaConfig.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/config/SomfyTahomaConfig.java index 73f7c1a59954d..c1b644fd222f7 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/config/SomfyTahomaConfig.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/config/SomfyTahomaConfig.java @@ -15,7 +15,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; /** - * The {@link SomfyTahomaConfig} is is the base class for configuration + * The {@link SomfyTahomaConfig} is is the base class for configuration * information held by devices and modules. * * @author Ondrej Pecta - Initial contribution diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaAdjustableSlatsRollerShutterHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaAdjustableSlatsRollerShutterHandler.java index 431968a3335ff..ce4cce5561aca 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaAdjustableSlatsRollerShutterHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaAdjustableSlatsRollerShutterHandler.java @@ -38,7 +38,7 @@ public SomfyTahomaAdjustableSlatsRollerShutterHandler(Thing thing) { stateNames.put(CONTROL, CLOSURE_OR_ROCKER_STATE); stateNames.put(ROCKER, CLOSURE_OR_ROCKER_STATE); stateNames.put(ORIENTATION, SLATE_ORIENTATION_STATE); - //override state type because the control may return string 'rocker' + // override state type because the control may return string 'rocker' cacheStateType(CONTROL, TYPE_PERCENT); } @@ -76,33 +76,40 @@ public void updateThingChannels(SomfyTahomaState state) { @Override public void handleCommand(ChannelUID channelUID, Command command) { super.handleCommand(channelUID, command); - if (!ROCKER.equals(channelUID.getId()) && !CONTROL.equals(channelUID.getId()) - && !ORIENTATION.equals(channelUID.getId())) { - return; - } if (command instanceof RefreshType) { return; - } else if (ROCKER.equals(channelUID.getId())) { - if (OnOffType.ON.equals(command)) { - sendCommand(COMMAND_SET_ROCKERPOSITION); - } - } else { - String cmd = getTahomaCommand(command.toString(), channelUID.getId()); - if (COMMAND_SET_ROCKERPOSITION.equals(cmd)) { - String executionId = getCurrentExecutions(); - if (executionId != null) { - // Check if the roller shutter is moving and rocker is sent => STOP it - cancelExecution(executionId); - } else { + } + + switch (channelUID.getId()) { + case ROCKER: + if (OnOffType.ON.equals(command)) { sendCommand(COMMAND_SET_ROCKERPOSITION); } - } else { - String param = (COMMAND_SET_CLOSURE.equals(cmd) || COMMAND_SET_ORIENTATION.equals(cmd)) - ? "[" + command.toString() + "]" - : "[]"; - sendCommand(cmd, param); - } + break; + case CLOSURE_AND_ORIENTATION: + sendCommand(COMMAND_SET_CLOSURE_ORIENTATION, "[" + command.toString() + "]"); + break; + case CONTROL: + case ORIENTATION: + String cmd = getTahomaCommand(command.toString(), channelUID.getId()); + if (COMMAND_SET_ROCKERPOSITION.equals(cmd)) { + String executionId = getCurrentExecutions(); + if (executionId != null) { + // Check if the roller shutter is moving and rocker is sent => STOP it + cancelExecution(executionId); + } else { + sendCommand(COMMAND_SET_ROCKERPOSITION); + } + } else { + String param = (COMMAND_SET_CLOSURE.equals(cmd) || COMMAND_SET_ORIENTATION.equals(cmd)) + ? "[" + toInteger(command) + "]" + : "[]"; + sendCommand(cmd, param); + } + break; + default: + return; } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaAwningHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaAwningHandler.java index 2a2c2d3feee22..2e2b3a9f9b11e 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaAwningHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaAwningHandler.java @@ -50,13 +50,13 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else if (COMMAND_STOP.equals(cmd)) { String executionId = getCurrentExecutions(); if (executionId != null) { - //Check if the awning is moving and STOP is sent => STOP it + // Check if the awning is moving and STOP is sent => STOP it cancelExecution(executionId); } else { sendCommand(COMMAND_MY); } } else { - String param = COMMAND_SET_DEPLOYMENT.equals(cmd) ? "[" + command.toString() + "]" : "[]"; + String param = COMMAND_SET_DEPLOYMENT.equals(cmd) ? "[" + toInteger(command) + "]" : "[]"; sendCommand(cmd, param); } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBaseThingHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBaseThingHandler.java index b43c95986565f..9990dcb032ae1 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBaseThingHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBaseThingHandler.java @@ -76,7 +76,7 @@ public void initialize() { private void createRSSIChannel() { if (thing.getChannel(RSSI) == null) { logger.debug("{} Creating a rssi channel", url); - createChannel(RSSI, "Number","RSSI Level"); + createChannel(RSSI, "Number", "RSSI Level"); } } @@ -318,7 +318,7 @@ private void updateRSSIChannel(SomfyTahomaState state) { } public void updateThingChannels(SomfyTahomaState state) { - stateNames.forEach((k,v) -> { + stateNames.forEach((k, v) -> { if (v.equals(state.getName())) { Channel ch = thing.getChannel(k); if (ch != null) { @@ -331,4 +331,8 @@ public void updateThingChannels(SomfyTahomaState state) { } }); } + + public int toInteger(Command command) { + return (command instanceof DecimalType) ? ((DecimalType) command).intValue() : 0; + } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java index 50f7e631ca9d8..97e3297258bae 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaBridgeHandler.java @@ -23,9 +23,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonSyntaxException; import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -45,6 +42,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonSyntaxException; + /** * The {@link SomfyTahomaBridgeHandler} is responsible for handling commands, which are * sent to one of the channels. @@ -171,17 +172,20 @@ public synchronized void login() { try { url = TAHOMA_API_URL + "login"; - String urlParameters = "userId=" + urlEncode(thingConfig.getEmail()) + "&userPassword=" + urlEncode(thingConfig.getPassword()); + String urlParameters = "userId=" + urlEncode(thingConfig.getEmail()) + "&userPassword=" + + urlEncode(thingConfig.getPassword()); ContentResponse response = sendRequestBuilder(url, HttpMethod.POST) - .content(new StringContentProvider(urlParameters), "application/x-www-form-urlencoded; charset=UTF-8") + .content(new StringContentProvider(urlParameters), + "application/x-www-form-urlencoded; charset=UTF-8") .send(); if (logger.isTraceEnabled()) { logger.trace("Login response: {}", response.getContentAsString()); } - SomfyTahomaLoginResponse data = gson.fromJson(response.getContentAsString(), SomfyTahomaLoginResponse.class); + SomfyTahomaLoginResponse data = gson.fromJson(response.getContentAsString(), + SomfyTahomaLoginResponse.class); if (data.isSuccess()) { logger.debug("SomfyTahoma version: {}", data.getVersion()); String id = registerEvents(); @@ -193,7 +197,8 @@ public synchronized void login() { logger.debug("Events id error: {}", id); } } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error logging in: " + data.getError()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Error logging in: " + data.getError()); if (data.getError().startsWith(TOO_MANY_REQUESTS)) { setTooManyRequests(); } @@ -204,7 +209,8 @@ public synchronized void login() { } catch (InterruptedException | ExecutionException | TimeoutException e) { if (e instanceof ExecutionException) { if (e.getMessage().contains(AUTHENTICATION_CHALLENGE)) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Authentication challenge"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Authentication challenge"); setTooManyRequests(); return; } @@ -324,7 +330,6 @@ private void cleanup() { } } - @Override public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { super.bridgeStatusChanged(bridgeStatusInfo); @@ -484,7 +489,7 @@ private void processEvent(SomfyTahomaEvent event) { processGatewayEvent(event); break; default: - //ignore other states + // ignore other states } } @@ -497,7 +502,7 @@ private synchronized void updateThings() { } } - //update all states only if necessary + // update all states only if necessary if (needsUpdate) { updateAllStates(); reconciliation = false; @@ -541,7 +546,7 @@ private void unregisterExecution(String execId) { } private void processGatewayEvent(SomfyTahomaEvent event) { - //update gateway status + // update gateway status for (Thing th : getThing().getThings()) { if (THING_TYPE_GATEWAY.equals(th.getThingTypeUID())) { SomfyTahomaGatewayHandler gatewayHandler = (SomfyTahomaGatewayHandler) th.getHandler(); @@ -606,7 +611,7 @@ private void refreshTahomaStates() { return; } - //force Tahoma to ask for actual states + // force Tahoma to ask for actual states forceGatewaySync(); } @@ -632,27 +637,33 @@ private void logout() { } } - private String sendPostToTahomaWithCookie(String url, String urlParameters) throws InterruptedException, ExecutionException, TimeoutException { + private String sendPostToTahomaWithCookie(String url, String urlParameters) + throws InterruptedException, ExecutionException, TimeoutException { return sendMethodToTahomaWithCookie(url, HttpMethod.POST, urlParameters); } - private String sendGetToTahomaWithCookie(String url) throws InterruptedException, ExecutionException, TimeoutException { + private String sendGetToTahomaWithCookie(String url) + throws InterruptedException, ExecutionException, TimeoutException { return sendMethodToTahomaWithCookie(url, HttpMethod.GET); } - private String sendPutToTahomaWithCookie(String url) throws InterruptedException, ExecutionException, TimeoutException { + private String sendPutToTahomaWithCookie(String url) + throws InterruptedException, ExecutionException, TimeoutException { return sendMethodToTahomaWithCookie(url, HttpMethod.PUT); } - private String sendDeleteToTahomaWithCookie(String url) throws InterruptedException, ExecutionException, TimeoutException { + private String sendDeleteToTahomaWithCookie(String url) + throws InterruptedException, ExecutionException, TimeoutException { return sendMethodToTahomaWithCookie(url, HttpMethod.DELETE); } - private String sendMethodToTahomaWithCookie(String url, HttpMethod method) throws InterruptedException, ExecutionException, TimeoutException { + private String sendMethodToTahomaWithCookie(String url, HttpMethod method) + throws InterruptedException, ExecutionException, TimeoutException { return sendMethodToTahomaWithCookie(url, method, ""); } - private String sendMethodToTahomaWithCookie(String url, HttpMethod method, String urlParameters) throws InterruptedException, ExecutionException, TimeoutException { + private String sendMethodToTahomaWithCookie(String url, HttpMethod method, String urlParameters) + throws InterruptedException, ExecutionException, TimeoutException { logger.trace("Sending {} to url: {} with data: {}", method.asString(), url, urlParameters); Request request = sendRequestBuilder(url, method); if (StringUtils.isNotEmpty(urlParameters)) { @@ -672,13 +683,9 @@ private String sendMethodToTahomaWithCookie(String url, HttpMethod method, Strin } private Request sendRequestBuilder(String url, HttpMethod method) { - return httpClient.newRequest(url) - .method(method) - .header(HttpHeader.ACCEPT_LANGUAGE, "en-US,en") - .header(HttpHeader.ACCEPT_ENCODING, "gzip, deflate") - .header("X-Requested-With", "XMLHttpRequest") - .timeout(TAHOMA_TIMEOUT, TimeUnit.SECONDS) - .agent(TAHOMA_AGENT); + return httpClient.newRequest(url).method(method).header(HttpHeader.ACCEPT_LANGUAGE, "en-US,en") + .header(HttpHeader.ACCEPT_ENCODING, "gzip, deflate").header("X-Requested-With", "XMLHttpRequest") + .timeout(TAHOMA_TIMEOUT, TimeUnit.SECONDS).agent(TAHOMA_AGENT); } public void sendCommand(String io, String command, String params) { @@ -700,8 +707,9 @@ public void sendCommand(String io, String command, String params) { url = EXEC_URL + "apply"; String value = params.equals("[]") ? command : params.replace("\"", ""); - String urlParameters = "{\"label\":\"" + getThingLabelByURL(io) + " - " + value + " - OH2\",\"actions\":[{\"deviceURL\":\"" + io + "\",\"commands\":[{\"name\":\"" - + command + "\",\"parameters\":" + params + "}]}]}"; + String urlParameters = "{\"label\":\"" + getThingLabelByURL(io) + " - " + value + + " - OH2\",\"actions\":[{\"deviceURL\":\"" + io + "\",\"commands\":[{\"name\":\"" + command + + "\",\"parameters\":" + params + "}]}]}"; line = sendPostToTahomaWithCookie(url, urlParameters); @@ -740,10 +748,10 @@ private String getThingLabelByURL(String io) { Thing th = getThingByDeviceUrl(io); if (th != null) { if (th.getProperties().containsKey(NAME_STATE)) { - //Return label from Tahoma + // Return label from Tahoma return th.getProperties().get(NAME_STATE).replace("\"", ""); } - //Return label from OH2 + // Return label from OH2 return th.getLabel() != null ? th.getLabel().replace("\"", "") : ""; } return "null"; @@ -799,7 +807,6 @@ public void executeActionGroup(String id) { if (!UNAUTHORIZED.equals(execId) && execId != null) { registerExecution(id, execId); } - } private boolean reLogin() { diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaElectricitySensorHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaElectricitySensorHandler.java index 6167ad441025a..ab33b36243fc7 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaElectricitySensorHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaElectricitySensorHandler.java @@ -27,7 +27,7 @@ public class SomfyTahomaElectricitySensorHandler extends SomfyTahomaBaseThingHan public SomfyTahomaElectricitySensorHandler(Thing thing) { super(thing); stateNames.put(ENERGY_CONSUMPTION, ENERGY_CONSUMPTION_STATE); - //override state type because the cloud sends consumption in percent + // override state type because the cloud sends consumption in percent cacheStateType(ENERGY_CONSUMPTION_STATE, TYPE_DECIMAL); } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaExternalAlarmHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaExternalAlarmHandler.java index b90fb14173534..3a57a0bc28324 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaExternalAlarmHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaExternalAlarmHandler.java @@ -41,5 +41,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { sendCommand(command.toString()); } } - } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaGatewayHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaGatewayHandler.java index f42ce0afcf8b0..e8a6e8519cefb 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaGatewayHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaGatewayHandler.java @@ -43,7 +43,7 @@ public void refresh(String channel) { if (ch != null) { updateState(ch.getUID(), new StringType(tahomaStatus)); } - //update the firmware property + // update the firmware property String fw = status.getProtocolVersion(); updateProperty(PROPERTY_FIRMWARE_VERSION, fw); @@ -53,5 +53,4 @@ public void refresh(String channel) { public String getGateWayId() { return getThing().getConfiguration().get("id").toString(); } - } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaMyfoxCameraHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaMyfoxCameraHandler.java index 11f1de2e1e52d..e6e3ea30a8028 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaMyfoxCameraHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaMyfoxCameraHandler.java @@ -44,7 +44,7 @@ public void updateThingChannels(SomfyTahomaState state) { if (MYFOX_SHUTTER_STATUS_STATE.equals(state.getName())) { Channel ch = thing.getChannel(SHUTTER); if (ch != null) { - //we need to covert opened/closed values to ON/OFF + // we need to covert opened/closed values to ON/OFF boolean open = "opened".equals(state.getValue()); updateState(ch.getUID(), open ? OnOffType.ON : OnOffType.OFF); } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaOccupancySensorHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaOccupancySensorHandler.java index 3184435042363..ba4da9be3d5bc 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaOccupancySensorHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaOccupancySensorHandler.java @@ -31,5 +31,4 @@ public SomfyTahomaOccupancySensorHandler(Thing thing) { stateNames.put(CONTACT, "core:OccupancyState"); stateNames.put(SENSOR_DEFECT, SENSOR_DEFECT_STATE); } - } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaRollerShutterHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaRollerShutterHandler.java index ed9477fec87c0..83bad878e9420 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaRollerShutterHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaRollerShutterHandler.java @@ -51,13 +51,13 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else if (COMMAND_STOP.equals(cmd)) { String executionId = getCurrentExecutions(); if (executionId != null) { - //Check if the roller shutter is moving and STOP is sent => STOP it + // Check if the roller shutter is moving and STOP is sent => STOP it cancelExecution(executionId); } else { sendCommand(COMMAND_MY); } } else { - String param = COMMAND_SET_CLOSURE.equals(cmd) ? "[" + command.toString() + "]" : "[]"; + String param = COMMAND_SET_CLOSURE.equals(cmd) ? "[" + toInteger(command) + "]" : "[]"; sendCommand(cmd, param); } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSilentRollerShutterHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSilentRollerShutterHandler.java index 1382b569e8117..05644f74b17a7 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSilentRollerShutterHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSilentRollerShutterHandler.java @@ -50,7 +50,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else if (COMMAND_STOP.equals(cmd)) { String executionId = getCurrentExecutions(); if (executionId != null) { - //Check if the roller shutter is moving and STOP is sent => STOP it + // Check if the roller shutter is moving and STOP is sent => STOP it cancelExecution(executionId); } else { sendCommand(COMMAND_MY); @@ -61,7 +61,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { String param = "[" + command.toString() + ", \"lowspeed\"]"; sendCommand(COMMAND_SET_CLOSURESPEED, param); } else { - String param = COMMAND_SET_CLOSURE.equals(cmd) ? "[" + command.toString() + "]" : "[]"; + String param = COMMAND_SET_CLOSURE.equals(cmd) ? "[" + toInteger(command) + "]" : "[]"; sendCommand(cmd, param); } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSirenHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSirenHandler.java index 888b16e3539b8..aa3bbfbaf812c 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSirenHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSirenHandler.java @@ -45,7 +45,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { return; } - //it is possible only to disable the siren + // it is possible only to disable the siren if (ONOFF_STATE.equals(channelUID.getId()) && command.equals(OnOffType.OFF)) { sendCommand(COMMAND_OFF); } @@ -54,6 +54,5 @@ public void handleCommand(ChannelUID channelUID, Command command) { if (MEMORIZED_VOLUME.equals(channelUID.getId()) && command instanceof StringType) { sendCommand("setMemorizedSimpleVolume", "[\"" + command.toString().toLowerCase() + "\"]"); } - } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSmokeSensorHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSmokeSensorHandler.java index 3e8687f211143..b436849e426c4 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSmokeSensorHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaSmokeSensorHandler.java @@ -46,7 +46,5 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else if (ALARM_CHECK.equals(channelUID.getId())) { sendCommand(COMMAND_CHECK_TRIGGER, "[\"" + command.toString().toLowerCase() + "\"]"); } - } } - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaTemperatureSensorHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaTemperatureSensorHandler.java index 865639ed1860a..941c2fb548c0e 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaTemperatureSensorHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaTemperatureSensorHandler.java @@ -31,7 +31,7 @@ public SomfyTahomaTemperatureSensorHandler(Thing thing) { super(thing); stateNames.put(TEMPERATURE, "core:TemperatureState"); - //override state type because the cloud sends both percent & decimal + // override state type because the cloud sends both percent & decimal cacheStateType("core:TemperatureState", TYPE_DECIMAL); } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaThermostatHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaThermostatHandler.java index 9c1594691d0af..cf50860117754 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaThermostatHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaThermostatHandler.java @@ -32,6 +32,6 @@ public SomfyTahomaThermostatHandler(Thing thing) { stateNames.put(BATTERY_LEVEL, BATTERY_LEVEL_STATE); stateNames.put(HEATING_MODE, "somfythermostat:HeatingModeState"); stateNames.put(DEROGATION_HEATING_MODE, "somfythermostat:DerogationHeatingModeState"); - stateNames.put(DEROGATION_ACTIVATION, "core:DerogationActivationState" ); + stateNames.put(DEROGATION_ACTIVATION, "core:DerogationActivationState"); } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaVenetianBlindHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaVenetianBlindHandler.java index 1df1ee4e96699..5355cf8577f6a 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaVenetianBlindHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaVenetianBlindHandler.java @@ -38,30 +38,38 @@ public SomfyTahomaVenetianBlindHandler(Thing thing) { @Override public void handleCommand(ChannelUID channelUID, Command command) { super.handleCommand(channelUID, command); - if (!CONTROL.equals(channelUID.getId()) && !ORIENTATION.equals(channelUID.getId())) { - return; - } if (command instanceof RefreshType) { return; - } else { - String cmd = getTahomaCommand(command.toString(), channelUID.getId()); - if (COMMAND_MY.equals(cmd)) { - sendCommand(COMMAND_MY); - } else if (COMMAND_STOP.equals(cmd)) { - String executionId = getCurrentExecutions(); - if (executionId != null) { - //Check if the venetian blind is moving and STOP is sent => STOP it - cancelExecution(executionId); - } else { + } + + switch (channelUID.getId()) { + case CLOSURE_AND_ORIENTATION: + sendCommand(COMMAND_SET_CLOSURE_ORIENTATION, "[" + command.toString() + "]"); + break; + case CONTROL: + case ORIENTATION: + String cmd = getTahomaCommand(command.toString(), channelUID.getId()); + if (COMMAND_MY.equals(cmd)) { sendCommand(COMMAND_MY); + } else if (COMMAND_STOP.equals(cmd)) { + String executionId = getCurrentExecutions(); + if (executionId != null) { + // Check if the venetian blind is moving and STOP is sent => STOP it + cancelExecution(executionId); + } else { + sendCommand(COMMAND_MY); + } + } else { + String param = (COMMAND_SET_CLOSURE.equals(cmd) || COMMAND_SET_ORIENTATION.equals(cmd)) + ? "[" + toInteger(command) + "]" + : "[]"; + sendCommand(cmd, param); } - } else { - String param = (COMMAND_SET_CLOSURE.equals(cmd) || COMMAND_SET_ORIENTATION.equals(cmd)) ? "[" + command.toString() + "]" : "[]"; - sendCommand(cmd, param); - } + break; + default: + return; } - } private String getTahomaCommand(String command, String channelId) { diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaWindowHandler.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaWindowHandler.java index e5a436339aea3..6ce5fcd2b6dc6 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaWindowHandler.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/handler/SomfyTahomaWindowHandler.java @@ -45,15 +45,15 @@ public void handleCommand(ChannelUID channelUID, Command command) { } else { String cmd = getTahomaCommand(command.toString()); if (COMMAND_STOP.equals(cmd)) { - //Check if the window is not moving + // Check if the window is not moving String executionId = getCurrentExecutions(); if (executionId != null) { - //STOP command should be interpreted if window is moving - //otherwise do nothing + // STOP command should be interpreted if window is moving + // otherwise do nothing cancelExecution(executionId); } } else { - String param = COMMAND_SET_CLOSURE.equals(cmd) ? "[" + command.toString() + "]" : "[]"; + String param = COMMAND_SET_CLOSURE.equals(cmd) ? "[" + toInteger(command) + "]" : "[]"; sendCommand(cmd, param); } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/model/SomfyTahomaEvent.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/model/SomfyTahomaEvent.java index 0f02e6b58b427..519d18878be2b 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/model/SomfyTahomaEvent.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/model/SomfyTahomaEvent.java @@ -15,9 +15,10 @@ import java.util.ArrayList; import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; + import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import org.eclipse.jdt.annotation.NonNullByDefault; /** * The {@link SomfyTahomaEvent} holds information about Tahoma diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/model/SomfyTahomaState.java b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/model/SomfyTahomaState.java index 477b03eccf190..20dbeba3d894e 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/model/SomfyTahomaState.java +++ b/bundles/org.openhab.binding.somfytahoma/src/main/java/org/openhab/binding/somfytahoma/internal/model/SomfyTahomaState.java @@ -41,10 +41,6 @@ public String getName() { @Override public String toString() { - return "{" + - "name='" + name + '\'' + - ", type=" + type + - ", value=" + value + - '}'; + return "{" + "name='" + name + '\'' + ", type=" + type + ", value=" + value + '}'; } } diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/binding/binding.xml index 9fccb43f2fe58..05562cf85df70 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + SomfyTahoma Binding This is the binding for SomfyTahoma. diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/config/config.xml index 188f6a2c3dbf6..57a49c27b8cd1 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/actiongroup.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/actiongroup.xml index e23551d524c6f..a59ea6442a48b 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/actiongroup.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/actiongroup.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/adjustableslatsrollershutter.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/adjustableslatsrollershutter.xml index e6c89d7676bd6..90fdb4b690045 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/adjustableslatsrollershutter.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/adjustableslatsrollershutter.xml @@ -1,5 +1,6 @@ - @@ -13,6 +14,7 @@ + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/awning.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/awning.xml index 205a00224524a..28565f300ff36 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/awning.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/awning.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/channels.xml index ba95c5c96729f..ac002d5c040c8 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/channels.xml @@ -1,5 +1,6 @@ - @@ -137,7 +138,7 @@ Number:Dimensionless The current relative humidity - + @@ -219,7 +220,7 @@ Number:Energy The energy consumption reported by the sensor - + @@ -331,4 +332,10 @@ State of the radio part of the Somfy sensor + + + String + + A channel for setting closure and orientation of the blind + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/contactsensor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/contactsensor.xml index dbe86645f8120..04715f03589c1 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/contactsensor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/contactsensor.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/curtain.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/curtain.xml index c7aa762b873be..3681a96224bc7 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/curtain.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/curtain.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/dock.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/dock.xml index 18bf00f9b9752..5f09f0caea3b6 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/dock.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/dock.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/doorlock.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/doorlock.xml index 44407bca5cce4..380cd0a748e7a 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/doorlock.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/doorlock.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/electricitysensor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/electricitysensor.xml index 4377fe0fe907c..5205f64e9fde8 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/electricitysensor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/electricitysensor.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/exteriorscreen.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/exteriorscreen.xml index a981e158d0ada..48e31e494a372 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/exteriorscreen.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/exteriorscreen.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/exteriorvenetianblind.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/exteriorvenetianblind.xml index fc31c3f207183..b3072c409bcfe 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/exteriorvenetianblind.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/exteriorvenetianblind.xml @@ -1,5 +1,6 @@ - @@ -11,6 +12,7 @@ + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/externalalarm.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/externalalarm.xml index 333c2019fc3dc..399333c692a60 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/externalalarm.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/externalalarm.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/garagedoor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/garagedoor.xml index 275f5a57644d3..ee93e8802d189 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/garagedoor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/garagedoor.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/gate.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/gate.xml index 6202eb0784b11..65ec0d88fd9e4 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/gate.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/gate.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/gateway.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/gateway.xml index cbf1bd1756411..c8bd1d8755e40 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/gateway.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/gateway.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/heatingsystem.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/heatingsystem.xml index 764bb115d71f2..e509d851fc054 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/heatingsystem.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/heatingsystem.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/humiditysensor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/humiditysensor.xml index 7750196a7313d..88185b78e0834 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/humiditysensor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/humiditysensor.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/internalalarm.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/internalalarm.xml index 10a0e9fbd5ea1..836750b8d18b1 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/internalalarm.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/internalalarm.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/light.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/light.xml index e7fa5bae11613..34e0811788e0b 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/light.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/light.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/lightsensor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/lightsensor.xml index 454d1e7d8ff58..a267284ea597f 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/lightsensor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/lightsensor.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/myfoxalarm.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/myfoxalarm.xml index e72995236b4c2..3b1d08c8168ed 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/myfoxalarm.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/myfoxalarm.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/myfoxcamera.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/myfoxcamera.xml index d9c033ed7a5b1..97e92e629db62 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/myfoxcamera.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/myfoxcamera.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/occupancysensor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/occupancysensor.xml index b815f5c54cf48..df9bd77695b96 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/occupancysensor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/occupancysensor.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/onoff.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/onoff.xml index 640ff52c563b9..62b14ac4d1444 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/onoff.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/onoff.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/onoffheatingsystem.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/onoffheatingsystem.xml index c223b5e4377ba..990642cef2df8 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/onoffheatingsystem.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/onoffheatingsystem.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/pergola.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/pergola.xml index 6763cd0d2434a..037338f057729 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/pergola.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/pergola.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/pod.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/pod.xml index 2e7a7f52d7144..9a197d1964706 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/pod.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/pod.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter.xml index 78cb872e86976..1d29f6ce8fd8a 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter_silent.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter_silent.xml index abfef9bde1867..c3776b73940ad 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter_silent.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter_silent.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter_uno.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter_uno.xml index d15535fbe93fe..0371bfce889e9 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter_uno.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/rollershutter_uno.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/screen.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/screen.xml index 992dfd1a00aa0..b401eebf0a6d6 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/screen.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/screen.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/siren.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/siren.xml index 0e23c47d2503f..521a18bfc31d0 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/siren.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/siren.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/smokesensor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/smokesensor.xml index 70d2e440f5ff6..2fa2c91b529c5 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/smokesensor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/smokesensor.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/temperaturesensor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/temperaturesensor.xml index dd4e4f1bc188a..edd8be5dfffaa 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/temperaturesensor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/temperaturesensor.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/thermostat.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/thermostat.xml index b9ea67e23ea53..e06b786755c5d 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/thermostat.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/thermostat.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/venetianblind.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/venetianblind.xml index f1efeb025a7be..ba526de120b15 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/venetianblind.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/venetianblind.xml @@ -1,5 +1,6 @@ - @@ -11,6 +12,7 @@ + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/watersensor.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/watersensor.xml index 7848e81796dd6..8402fbb2dd23e 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/watersensor.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/watersensor.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/window.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/window.xml index 55aa5aa528f9e..a2a29d2217dc6 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/window.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/window.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/windowhandler.xml b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/windowhandler.xml index ea4e72247464a..9d0781363fec8 100644 --- a/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/windowhandler.xml +++ b/bundles/org.openhab.binding.somfytahoma/src/main/resources/ESH-INF/thing/windowhandler.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.sonos/README.md b/bundles/org.openhab.binding.sonos/README.md index ad6b2759c2012..e36e2d4877c45 100644 --- a/bundles/org.openhab.binding.sonos/README.md +++ b/bundles/org.openhab.binding.sonos/README.md @@ -10,9 +10,9 @@ This happens because of a TTL=1 for ALIVE packets send by Sonos devices, resulti ## Supported Things -All available Sonos (playback) devices are supported by this binding. This includes the One, Play:1, Play:3, Play:5, Connect, Connect:Amp, Playbar, Playbase, Beam and Sub. The Bridge and Boost are not supported, but these devices do only have an auxiliary role in the Sonos network and do not have any playback capability. All supported Sonos devices are registered as an audio sink in the framework. +All available Sonos (playback) devices are supported by this binding. This includes the One, OneSL, Play:1, Play:3, Play:5, Connect, Connect:Amp, Port, Amp, Playbar, Playbase, Beam and Sub. The Bridge and Boost are not supported, but these devices do only have an auxiliary role in the Sonos network and do not have any playback capability. All supported Sonos devices are registered as an audio sink in the framework. -When being defined in a \*.things file, the specific thing types One, PLAY1, PLAY3, PLAY5, PLAYBAR, PLAYBASE, Beam, CONNECT and CONNECTAMP should be used. +When being defined in a \*.things file, the specific thing types One, OneSL, PLAY1, PLAY3, PLAY5, PLAYBAR, PLAYBASE, Beam, CONNECT, CONNECTAMP, Port and Amp should be used. Please note that these thing types are case sensitive (you need to define them **exactly as stated above**). @@ -64,17 +64,21 @@ The devices support the following channels: | currenttransporturi | String | R | URI of the current AV transport | all | | favorite | String | W | Play the given favorite entry. The favorite entry has to be predefined in the Sonos Controller app | all | | led | Switch | RW | Set or get the status of the white LED on the front of the Zone Player | all | -| linein | Switch | R | Indicator set to ON when the line-in of the Zone Player is connected | PLAY5, CONNECT, CONNECTAMP, PLAYBASE | +| linein | Switch | R | Indicator set to ON when the line-in of the Zone Player is connected | PLAY5, CONNECT, CONNECTAMP, PLAYBAR, PLAYBASE, Beam, Port | +| analoglinein | Switch | R | Indicator set to ON when the analog line-in of the Zone Player is connected | Amp | +| digitallinein | Switch | R | Indicator set to ON when the digital line-in of the Zone Player is connected | Amp | | localcoordinator | Switch | R | Indicator set to ON if the this Zone Player is the Zone Group Coordinator | all | | mute | Switch | RW | Set or get the mute state of the master volume of the Zone Player | all | -| nightmode | Switch | RW | Enable or disable the night mode feature | PLAYBAR, PLAYBASE, Beam | +| nightmode | Switch | RW | Enable or disable the night mode feature | PLAYBAR, PLAYBASE, Beam, Amp | | notificationsound | String | W | Play a notification sound by a given URI | all | -| playlinein | String | W | This channel supports playing the audio source connected to the line-in of the zoneplayer identified by the Thing UID or UPnP UDN provided by the String. | PLAY5, CONNECT, CONNECTAMP, PLAYBAR, PLAYBASE, Beam | +| playlinein | String | W | This channel supports playing the audio source connected to the line-in of the zoneplayer identified by the Thing UID or UPnP UDN provided by the String. | All | | playlist | String | W | Play the given playlist. The playlist has to predefined in the Sonos Controller app | all | | playqueue | Switch | W | Play the songs from the current queue | all | | playtrack | Number | W | Play the given track number from the current queue | all | | playuri | String | W | Play the given URI | all | -| publicaddress | Switch | W | Put all Zone Players in one group, and stream audio from the line-in from the Zone Player that triggered the command | all | +| publicaddress | Switch | W | Put all Zone Players in one group, and stream audio from the line-in from the Zone Player that triggered the command | all except Amp | +| publicanalogaddress | Switch | W | Put all Zone Players in one group, and stream audio from the analog line-in from the Zone Player that triggered the command | Amp | +| publicdigitaladdress| Switch | W | Put all Zone Players in one group, and stream audio from the digital line-in from the Zone Player that triggered the command | Amp | | radio | String | W | Play the given radio station. The radio station has to be predefined in the Sonos Controller app | all | | remove | String | W | Remove the given Zone Player from the group of this Zone Player | all | | repeat | String | RW | Repeat the track or queue playback. The accepted values are OFF, ONE and ALL | all | @@ -85,7 +89,7 @@ The devices support the following channels: | shuffle | Switch | RW | Shuffle the queue playback | all | | sleeptimer | Number | RW | Set/show the duration of the SleepTimer in seconds | all | | snooze | Number | W | Snooze the running alarm, if any, with the given number of minutes | all | -| speechenhancement | Switch | RW | Enable or disable the speech enhancement feature | PLAYBAR, PLAYBASE, Beam | +| speechenhancement | Switch | RW | Enable or disable the speech enhancement feature | PLAYBAR, PLAYBASE, Beam, One, Amp | | standalone | Switch | W | Make the Zone Player leave its Group and become a standalone Zone Player | all | | state | String | R | The State channel contains state of the Zone Player, e.g. PLAYING, STOPPED, ... | all | | stop | Switch | W | Write `ON` to this channel: Stops the Zone Player player. | all | @@ -94,6 +98,10 @@ The devices support the following channels: | zonegroupid | String | R | Id of the Zone Group the Zone Player belongs to | all | | zonename | String | R | Name of the Zone associated to the Zone Player | all | +The `playline` channel accepts as command either the thing UID or the UPnP UDN. +Note that you can prefix your command value with "Analog," or "Digital," to distinguish the line-in of your Sonos device. +This is useful for the Sonos Amp in particular. + ## Audio Support All supported Sonos devices are registered as an audio sink in the framework. diff --git a/bundles/org.openhab.binding.sonos/pom.xml b/bundles/org.openhab.binding.sonos/pom.xml index fcda89cdc0487..84d7e284397d6 100644 --- a/bundles/org.openhab.binding.sonos/pom.xml +++ b/bundles/org.openhab.binding.sonos/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.sonos diff --git a/bundles/org.openhab.binding.sonos/src/main/feature/feature.xml b/bundles/org.openhab.binding.sonos/src/main/feature/feature.xml index 28c262afc76d7..ec4acb01f8d20 100644 --- a/bundles/org.openhab.binding.sonos/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.sonos/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.sonos/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.sonos/${project.version} + diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java index fa7e914a2480a..7eb7d32b31eca 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosAudioSink.java @@ -144,5 +144,4 @@ public PercentType getVolume() { public void setVolume(PercentType volume) { handler.setVolume(volume); } - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosBindingConstants.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosBindingConstants.java index 5af769a3d1a66..ce9e46ac055be 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosBindingConstants.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosBindingConstants.java @@ -35,6 +35,7 @@ public class SonosBindingConstants { // Column (:) is not used for PLAY:1, PLAY:3, PLAY:5 and CONNECT:AMP because of // ThingTypeUID and device pairing name restrictions public static final ThingTypeUID ONE_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "One"); + public static final ThingTypeUID ONE_SL_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "OneSL"); public static final ThingTypeUID PLAY1_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "PLAY1"); public static final ThingTypeUID PLAY3_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "PLAY3"); public static final ThingTypeUID PLAY5_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "PLAY5"); @@ -42,19 +43,27 @@ public class SonosBindingConstants { public static final ThingTypeUID PLAYBASE_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "PLAYBASE"); public static final ThingTypeUID BEAM_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "Beam"); public static final ThingTypeUID CONNECT_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "CONNECT"); + public static final ThingTypeUID PORT_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "Port"); public static final ThingTypeUID CONNECTAMP_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "CONNECTAMP"); + public static final ThingTypeUID AMP_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "Amp"); public static final ThingTypeUID SYMFONISK_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "SYMFONISK"); public static final ThingTypeUID ZONEPLAYER_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "zoneplayer"); public static final Set WITH_LINEIN_THING_TYPES_UIDS = Stream .of(PLAY5_THING_TYPE_UID, PLAYBAR_THING_TYPE_UID, PLAYBASE_THING_TYPE_UID, BEAM_THING_TYPE_UID, - CONNECT_THING_TYPE_UID, CONNECTAMP_THING_TYPE_UID) + CONNECT_THING_TYPE_UID, CONNECTAMP_THING_TYPE_UID, PORT_THING_TYPE_UID) .collect(Collectors.toSet()); - public static final Set SUPPORTED_KNOWN_THING_TYPES_UIDS = Stream - .of(ONE_THING_TYPE_UID, PLAY1_THING_TYPE_UID, PLAY3_THING_TYPE_UID, PLAY5_THING_TYPE_UID, - PLAYBAR_THING_TYPE_UID, PLAYBASE_THING_TYPE_UID, BEAM_THING_TYPE_UID, CONNECT_THING_TYPE_UID, - CONNECTAMP_THING_TYPE_UID, SYMFONISK_THING_TYPE_UID) + public static final Set WITH_ANALOG_LINEIN_THING_TYPES_UIDS = Stream.of(AMP_THING_TYPE_UID) + .collect(Collectors.toSet()); + + public static final Set WITH_DIGITAL_LINEIN_THING_TYPES_UIDS = Stream.of(AMP_THING_TYPE_UID) + .collect(Collectors.toSet()); + + public static final Set SUPPORTED_KNOWN_THING_TYPES_UIDS = Stream.of(ONE_THING_TYPE_UID, + ONE_SL_THING_TYPE_UID, PLAY1_THING_TYPE_UID, PLAY3_THING_TYPE_UID, PLAY5_THING_TYPE_UID, + PLAYBAR_THING_TYPE_UID, PLAYBASE_THING_TYPE_UID, BEAM_THING_TYPE_UID, CONNECT_THING_TYPE_UID, + CONNECTAMP_THING_TYPE_UID, PORT_THING_TYPE_UID, AMP_THING_TYPE_UID, SYMFONISK_THING_TYPE_UID) .collect(Collectors.toSet()); public static final Set SUPPORTED_THING_TYPES_UIDS = new HashSet<>(SUPPORTED_KNOWN_THING_TYPES_UIDS); @@ -81,6 +90,8 @@ public class SonosBindingConstants { public static final String FAVORITE = "favorite"; public static final String LED = "led"; public static final String LINEIN = "linein"; + public static final String ANALOGLINEIN = "analoglinein"; + public static final String DIGITALLINEIN = "digitallinein"; public static final String LOCALCOORDINATOR = "localcoordinator"; public static final String MUTE = "mute"; public static final String NIGHTMODE = "nightmode"; @@ -91,6 +102,8 @@ public class SonosBindingConstants { public static final String PLAYTRACK = "playtrack"; public static final String PLAYURI = "playuri"; public static final String PUBLICADDRESS = "publicaddress"; + public static final String PUBLICANALOGADDRESS = "publicanalogaddress"; + public static final String PUBLICDIGITALADDRESS = "publicdigitaladdress"; public static final String RADIO = "radio"; public static final String REMOVE = "remove"; public static final String REPEAT = "repeat"; @@ -115,5 +128,4 @@ public class SonosBindingConstants { public static final String IDENTIFICATION = "identification"; public static final String MAC_ADDRESS = "macAddress"; public static final String IP_ADDRESS = "ipAddress"; - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosEntry.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosEntry.java index cbf4a5e8369ca..1c94275f72aa3 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosEntry.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosEntry.java @@ -147,5 +147,4 @@ public String getDesc() { public void setDesc(String desc) { this.desc = desc; } - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosHandlerFactory.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosHandlerFactory.java index de71f9872b8ca..019e6ee89ccb5 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosHandlerFactory.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosHandlerFactory.java @@ -168,5 +168,4 @@ private ThingUID getPlayerUID(ThingTypeUID thingTypeUID, ThingUID thingUID, Conf return new ThingUID(thingTypeUID, udn); } } - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosMusicService.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosMusicService.java index a2cd20c807eab..cdb8b042ce97c 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosMusicService.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosMusicService.java @@ -48,5 +48,4 @@ public Integer getType() { public void setType(Integer type) { this.type = type; } - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosResourceMetaData.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosResourceMetaData.java index 3e4e5f7b2f4b9..cf37fcf4b8c7a 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosResourceMetaData.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosResourceMetaData.java @@ -86,5 +86,4 @@ public String getUpnpClass() { public String getDesc() { return desc; } - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosXMLParser.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosXMLParser.java index 75120e6c67532..6de8d609893cc 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosXMLParser.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosXMLParser.java @@ -626,7 +626,6 @@ public void endElement(String uri, String localName, String qName) throws SAXExc public List getTextFields() { return textFields; } - } private static class AVTransportEventHandler extends DefaultHandler { @@ -699,7 +698,6 @@ public void startElement(String uri, String localName, String qName, Attributes public Map getChanges() { return changes; } - } private static class MetaDataHandler extends DefaultHandler { @@ -832,7 +830,6 @@ public void endElement(String uri, String localName, String qName) throws SAXExc public Map getChanges() { return changes; } - } private static class MusicServiceHandler extends DefaultHandler { @@ -850,7 +847,6 @@ public void startElement(String uri, String localName, String qName, Attributes public List getServices() { return services; } - } public static String getRoomName(String descriptorXML) { diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZoneGroup.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZoneGroup.java index 8c27820f6b5f4..5442478a3af88 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZoneGroup.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZoneGroup.java @@ -90,5 +90,4 @@ public boolean equals(Object obj) { public int hashCode() { return id.hashCode(); } - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZonePlayerState.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZonePlayerState.java index 58608a387f346..3d59627d1f7fc 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZonePlayerState.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/SonosZonePlayerState.java @@ -25,5 +25,4 @@ public class SonosZonePlayerState { public String relTime; public SonosEntry entry; public long track; - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/config/ZonePlayerConfiguration.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/config/ZonePlayerConfiguration.java index 4ae618a4744f8..56f5f6bc131fb 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/config/ZonePlayerConfiguration.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/config/ZonePlayerConfiguration.java @@ -27,5 +27,4 @@ public class ZonePlayerConfiguration { public Integer refresh; public Integer notificationTimeout; public Integer notificationVolume; - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/discovery/ZonePlayerDiscoveryParticipant.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/discovery/ZonePlayerDiscoveryParticipant.java index 097a3fea3b20d..cfff378ee0faa 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/discovery/ZonePlayerDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/discovery/ZonePlayerDiscoveryParticipant.java @@ -86,7 +86,7 @@ public ThingUID getThingUID(RemoteDevice device) { modelName = "CONNECTAMP"; break; case "One SL": - modelName = "One"; + modelName = "OneSL"; break; default: break; @@ -117,5 +117,4 @@ private String getModelName(RemoteDevice device) { private String getSonosRoomName(RemoteDevice device) { return SonosXMLParser.getRoomName(device.getIdentity().getDescriptorURL().toString()); } - } diff --git a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/handler/ZonePlayerHandler.java b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/handler/ZonePlayerHandler.java index bd9a534c28032..715d908926611 100644 --- a/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/handler/ZonePlayerHandler.java +++ b/bundles/org.openhab.binding.sonos/src/main/java/org/openhab/binding/sonos/internal/handler/ZonePlayerHandler.java @@ -33,7 +33,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.IncreaseDecreaseType; import org.eclipse.smarthome.core.library.types.NextPreviousType; @@ -82,8 +81,6 @@ */ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOParticipant { - private final Logger logger = LoggerFactory.getLogger(ZonePlayerHandler.class); - private static final String ANALOG_LINE_IN_URI = "x-rincon-stream:"; private static final String OPTICAL_LINE_IN_URI = "x-sonos-htastream:"; private static final String QUEUE_URI = "x-rincon-queue:"; @@ -100,86 +97,64 @@ public class ZonePlayerHandler extends BaseThingHandler implements UpnpIOPartici private static final String STATE_PAUSED_PLAYBACK = "PAUSED_PLAYBACK"; private static final String STATE_STOPPED = "STOPPED"; - private final ThingRegistry localThingRegistry; - private UpnpIOService service; - private ScheduledFuture pollingJob; - private SonosZonePlayerState savedState = null; + private static final String LINEINCONNECTED = "LineInConnected"; + private static final String TOSLINEINCONNECTED = "TOSLinkConnected"; private static final Collection SERVICE_SUBSCRIPTIONS = Arrays.asList("DeviceProperties", "AVTransport", "ZoneGroupTopology", "GroupManagement", "RenderingControl", "AudioIn", "HTControl", "ContentDirectory"); - private Map subscriptionState = new HashMap<>(); protected static final int SUBSCRIPTION_DURATION = 1800; + private static final int SOCKET_TIMEOUT = 5000; /** - * Default notification timeout (in seconds) + * The default refresh interval when not specified in channel configuration. */ - private static final Integer DEFAULT_NOTIFICATION_TIMEOUT = 20; + private static final int DEFAULT_REFRESH_INTERVAL = 60; /** - * configurable notification timeout (in seconds) + * Default notification timeout (in seconds) */ - private Integer notificationTimeout = null; + private static final Integer DEFAULT_NOTIFICATION_TIMEOUT = 20; - /** - * Intrinsic lock used to synchronize the execution of notification sounds - */ - private final Object notificationLock = new Object(); + private final Logger logger = LoggerFactory.getLogger(ZonePlayerHandler.class); - /** - * {@link ThingHandler} instance of the coordinator speaker used for control delegation - */ - private ZonePlayerHandler coordinatorHandler; + private final ThingRegistry localThingRegistry; + private final UpnpIOService service; + private final String opmlUrl; + private final SonosStateDescriptionOptionProvider stateDescriptionProvider; /** - * The default refresh interval when not specified in channel configuration. + * Intrinsic lock used to synchronize the execution of notification sounds */ - private static final int DEFAULT_REFRESH_INTERVAL = 60; - - private final Map stateMap = Collections.synchronizedMap(new HashMap<>()); - - private List musicServices; - + private final Object notificationLock = new Object(); private final Object upnpLock = new Object(); - private final Object stateLock = new Object(); + private final Object jobLock = new Object(); - private final SonosStateDescriptionOptionProvider stateDescriptionProvider; + private final Map stateMap = Collections.synchronizedMap(new HashMap<>()); - private final Runnable pollingRunnable = () -> { - try { - logger.debug("Polling job"); + private ScheduledFuture pollingJob; + private SonosZonePlayerState savedState = null; - // First check if the Sonos zone is set in the UPnP service registry - // If not, set the thing state to OFFLINE and wait for the next poll - if (!isUpnpDeviceRegistered()) { - logger.debug("UPnP device {} not yet registered", getUDN()); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "@text/offline.upnp-device-not-registered [\"" + getUDN() + "\"]"); - synchronized (upnpLock) { - subscriptionState = new HashMap<>(); - } - return; - } + private Map subscriptionState = new HashMap<>(); - // Check if the Sonos zone can be joined - // If not, set the thing state to OFFLINE and do nothing else - updatePlayerState(); - if (getThing().getStatus() != ThingStatus.ONLINE) { - return; - } + /** + * configurable notification timeout (in seconds) + */ + private Integer notificationTimeout = null; - addSubscription(); + /** + * {@link ThingHandler} instance of the coordinator speaker used for control delegation + */ + private ZonePlayerHandler coordinatorHandler; - updateZoneInfo(); - updateLed(); - updateSleepTimerDuration(); - } catch (Exception e) { - logger.debug("Exception during poll: {}", e.getMessage(), e); - } - }; + private List musicServices; - private final String opmlUrl; + private enum LineInType { + ANALOG, + DIGITAL, + ANY + } public ZonePlayerHandler(ThingRegistry thingRegistry, Thing thing, UpnpIOService upnpIOService, String opmlUrl, SonosStateDescriptionOptionProvider stateDescriptionProvider) { @@ -187,9 +162,7 @@ public ZonePlayerHandler(ThingRegistry thingRegistry, Thing thing, UpnpIOService this.localThingRegistry = thingRegistry; this.opmlUrl = opmlUrl; logger.debug("Creating a ZonePlayerHandler for thing '{}'", getThing().getUID()); - if (upnpIOService != null) { - this.service = upnpIOService; - } + this.service = upnpIOService; this.stateDescriptionProvider = stateDescriptionProvider; } @@ -197,7 +170,7 @@ public ZonePlayerHandler(ThingRegistry thingRegistry, Thing thing, UpnpIOService public void dispose() { logger.debug("Handler disposed for thing {}", getThing().getUID()); - if (pollingJob != null && !pollingJob.isCancelled()) { + if (pollingJob != null) { pollingJob.cancel(true); pollingJob = null; } @@ -215,14 +188,19 @@ public void initialize() { return; } - if (getUDN() != null) { + ZonePlayerConfiguration config = getConfigAs(ZonePlayerConfiguration.class); + if (config.udn != null) { service.registerParticipant(this); - onUpdate(); - this.notificationTimeout = getConfigAs(ZonePlayerConfiguration.class).notificationTimeout; + this.notificationTimeout = config.notificationTimeout; if (this.notificationTimeout == null) { this.notificationTimeout = DEFAULT_NOTIFICATION_TIMEOUT; } + int refreshInterval = DEFAULT_REFRESH_INTERVAL; + if (config.refresh != null) { + refreshInterval = config.refresh.intValue(); + } + pollingJob = scheduler.scheduleWithFixedDelay(this::poll, 0, refreshInterval, TimeUnit.SECONDS); } else { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-missing-udn"); @@ -230,6 +208,51 @@ public void initialize() { } } + private void poll() { + synchronized (jobLock) { + if (pollingJob == null) { + return; + } + try { + logger.debug("Polling job"); + + // First check if the Sonos zone is set in the UPnP service registry + // If not, set the thing state to OFFLINE and wait for the next poll + if (!isUpnpDeviceRegistered()) { + logger.debug("UPnP device {} not yet registered", getUDN()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "@text/offline.upnp-device-not-registered [\"" + getUDN() + "\"]"); + synchronized (upnpLock) { + subscriptionState = new HashMap<>(); + } + return; + } + + // Check if the Sonos zone can be joined + // If not, set the thing state to OFFLINE and do nothing else + updatePlayerState(); + if (getThing().getStatus() != ThingStatus.ONLINE) { + return; + } + + addSubscription(); + + if (isLinked(ZONENAME)) { + updateCurrentZoneName(); + } + if (isLinked(LED)) { + updateLed(); + } + // Action GetRemainingSleepTimerDuration is failing for a group slave member (error code 500) + if (isLinked(SLEEPTIMER) && isCoordinator()) { + updateSleepTimerDuration(); + } + } catch (Exception e) { + logger.debug("Exception during poll: {}", e.getMessage(), e); + } + } + } + @Override public void handleCommand(ChannelUID channelUID, Command command) { if (command instanceof RefreshType) { @@ -261,7 +284,13 @@ public void handleCommand(ChannelUID channelUID, Command command) { becomeStandAlonePlayer(); break; case PUBLICADDRESS: - publicAddress(); + publicAddress(LineInType.ANY); + break; + case PUBLICANALOGADDRESS: + publicAddress(LineInType.ANALOG); + break; + case PUBLICDIGITALADDRESS: + publicAddress(LineInType.DIGITAL); break; case RADIO: playRadio(command); @@ -472,11 +501,23 @@ public void onValueReceived(String variable, String value, String service) { case "DialogLevel": updateChannel(SPEECHENHANCEMENT); break; - case "LineInConnected": - case "TOSLinkConnected": + case LINEINCONNECTED: if (SonosBindingConstants.WITH_LINEIN_THING_TYPES_UIDS.contains(getThing().getThingTypeUID())) { updateChannel(LINEIN); } + if (SonosBindingConstants.WITH_ANALOG_LINEIN_THING_TYPES_UIDS + .contains(getThing().getThingTypeUID())) { + updateChannel(ANALOGLINEIN); + } + break; + case TOSLINEINCONNECTED: + if (SonosBindingConstants.WITH_LINEIN_THING_TYPES_UIDS.contains(getThing().getThingTypeUID())) { + updateChannel(LINEIN); + } + if (SonosBindingConstants.WITH_DIGITAL_LINEIN_THING_TYPES_UIDS + .contains(getThing().getThingTypeUID())) { + updateChannel(DIGITALLINEIN); + } break; case "AlarmRunning": updateChannel(ALARMRUNNING); @@ -682,10 +723,20 @@ protected void updateChannel(String channelId) { } break; case LINEIN: - if (stateMap.get("LineInConnected") != null) { - newState = stateMap.get("LineInConnected").equals("true") ? OnOffType.ON : OnOffType.OFF; - } else if (stateMap.get("TOSLinkConnected") != null) { - newState = stateMap.get("TOSLinkConnected").equals("true") ? OnOffType.ON : OnOffType.OFF; + if (stateMap.get(LINEINCONNECTED) != null) { + newState = stateMap.get(LINEINCONNECTED).equals("true") ? OnOffType.ON : OnOffType.OFF; + } else if (stateMap.get(TOSLINEINCONNECTED) != null) { + newState = stateMap.get(TOSLINEINCONNECTED).equals("true") ? OnOffType.ON : OnOffType.OFF; + } + break; + case ANALOGLINEIN: + if (stateMap.get(LINEINCONNECTED) != null) { + newState = stateMap.get(LINEINCONNECTED).equals("true") ? OnOffType.ON : OnOffType.OFF; + } + break; + case DIGITALLINEIN: + if (stateMap.get(TOSLINEINCONNECTED) != null) { + newState = stateMap.get(TOSLINEINCONNECTED).equals("true") ? OnOffType.ON : OnOffType.OFF; } break; case ALARMRUNNING: @@ -856,21 +907,8 @@ public void onServiceSubscribed(String service, boolean succeeded) { } } - private void onUpdate() { - if (pollingJob == null || pollingJob.isCancelled()) { - ZonePlayerConfiguration config = getConfigAs(ZonePlayerConfiguration.class); - // use default if not specified - int refreshInterval = DEFAULT_REFRESH_INTERVAL; - if (config.refresh != null) { - refreshInterval = config.refresh.intValue(); - } - pollingJob = scheduler.scheduleWithFixedDelay(pollingRunnable, 0, refreshInterval, TimeUnit.SECONDS); - } - } - private void updatePlayerState() { - Map result = service.invokeAction(this, "DeviceProperties", "GetZoneInfo", null); - if (result.isEmpty()) { + if (!updateZoneInfo()) { if (!ThingStatus.OFFLINE.equals(getThing().getStatus())) { logger.debug("Sonos player {} is not available in local network", getUDN()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, @@ -935,46 +973,36 @@ protected void updateRunningAlarmProperties() { } } - protected void updateZoneInfo() { + protected boolean updateZoneInfo() { Map result = service.invokeAction(this, "DeviceProperties", "GetZoneInfo", null); - Map result2 = service.invokeAction(this, "DeviceProperties", "GetZoneAttributes", null); - - result.putAll(result2); - for (String variable : result.keySet()) { this.onValueReceived(variable, result.get(variable), "DeviceProperties"); } Map properties = editProperties(); - boolean update = false; - if (StringUtils.isNotEmpty(this.stateMap.get("HardwareVersion")) - && !this.stateMap.get("HardwareVersion").equals(properties.get(Thing.PROPERTY_HARDWARE_VERSION))) { - update = true; - properties.put(Thing.PROPERTY_HARDWARE_VERSION, this.stateMap.get("HardwareVersion")); - } - if (StringUtils.isNotEmpty(this.stateMap.get("DisplaySoftwareVersion")) && !this.stateMap - .get("DisplaySoftwareVersion").equals(properties.get(Thing.PROPERTY_FIRMWARE_VERSION))) { - update = true; - properties.put(Thing.PROPERTY_FIRMWARE_VERSION, this.stateMap.get("DisplaySoftwareVersion")); + String value = stateMap.get("HardwareVersion"); + if (value != null && !value.isEmpty()) { + properties.put(Thing.PROPERTY_HARDWARE_VERSION, value); } - if (StringUtils.isNotEmpty(this.stateMap.get("SerialNumber")) - && !this.stateMap.get("SerialNumber").equals(properties.get(Thing.PROPERTY_SERIAL_NUMBER))) { - update = true; - properties.put(Thing.PROPERTY_SERIAL_NUMBER, this.stateMap.get("SerialNumber")); + value = stateMap.get("DisplaySoftwareVersion"); + if (value != null && !value.isEmpty()) { + properties.put(Thing.PROPERTY_FIRMWARE_VERSION, value); } - if (StringUtils.isNotEmpty(this.stateMap.get("MACAddress")) - && !this.stateMap.get("MACAddress").equals(properties.get(MAC_ADDRESS))) { - update = true; - properties.put(MAC_ADDRESS, this.stateMap.get("MACAddress")); + value = stateMap.get("SerialNumber"); + if (value != null && !value.isEmpty()) { + properties.put(Thing.PROPERTY_SERIAL_NUMBER, value); } - if (StringUtils.isNotEmpty(this.stateMap.get("IPAddress")) - && !this.stateMap.get("IPAddress").equals(properties.get(IP_ADDRESS))) { - update = true; - properties.put(IP_ADDRESS, this.stateMap.get("IPAddress")); + value = stateMap.get("MACAddress"); + if (value != null && !value.isEmpty()) { + properties.put(MAC_ADDRESS, value); } - if (update) { - updateProperties(properties); + value = stateMap.get("IPAddress"); + if (value != null && !value.isEmpty()) { + properties.put(IP_ADDRESS, value); } + updateProperties(properties); + + return !result.isEmpty(); } public String getCoordinator() { @@ -1027,8 +1055,8 @@ else if (isPlayingStream(currentURI) || isPlayingRadioStartedByAmazonEcho(curren String mac = getMACAddress(); if (stationID != null && !stationID.isEmpty() && mac != null && !mac.isEmpty()) { String url = opmlUrl; - url = StringUtils.replace(url, "%id", stationID); - url = StringUtils.replace(url, "%serial", mac); + url = url.replace("%id", stationID); + url = url.replace("%serial", mac); String response = null; try { @@ -1132,13 +1160,26 @@ && hasValueChanged(albumArtURI, memberHandler.stateMap.get("CurrentAlbumArtURI") private String extractStationId(String uri) { String stationID = null; if (isPlayingStream(uri)) { - stationID = StringUtils.substringBetween(uri, ":s", "?sid"); + stationID = substringBetween(uri, ":s", "?sid"); } else if (isPlayingRadioStartedByAmazonEcho(uri)) { - stationID = StringUtils.substringBetween(uri, "sid=s", "&"); + stationID = substringBetween(uri, "sid=s", "&"); } return stationID; } + private String substringBetween(String str, String open, String close) { + String result = null; + int idx1 = str.indexOf(open); + if (idx1 >= 0) { + idx1 += open.length(); + int idx2 = str.indexOf(close, idx1); + if (idx2 >= 0) { + result = str.substring(idx1, idx2); + } + } + return result; + } + public boolean isGroupCoordinator() { String value = stateMap.get("GroupCoordinatorIsLocal"); if (value != null) { @@ -1187,7 +1228,7 @@ public SonosMetaData getEnqueuedTransportURIMetaData() { } public String getMACAddress() { - if (StringUtils.isEmpty(stateMap.get("MACAddress"))) { + if (stateMap.get("MACAddress") == null || stateMap.get("MACAddress").isEmpty()) { updateZoneInfo(); } return stateMap.get("MACAddress"); @@ -1896,17 +1937,26 @@ public void removeAllTracksFromQueue() { public void playLineIn(Command command) { if (command != null && command instanceof StringType) { try { + LineInType lineInType = LineInType.ANY; String remotePlayerName = command.toString(); + if (remotePlayerName.toUpperCase().startsWith("ANALOG,")) { + lineInType = LineInType.ANALOG; + remotePlayerName = remotePlayerName.substring(7); + } else if (remotePlayerName.toUpperCase().startsWith("DIGITAL,")) { + lineInType = LineInType.DIGITAL; + remotePlayerName = remotePlayerName.substring(8); + } ZonePlayerHandler coordinatorHandler = getCoordinatorHandler(); ZonePlayerHandler remoteHandler = getHandlerByName(remotePlayerName); // check if player has a line-in connected - if (remoteHandler.isAnalogLineInConnected() || remoteHandler.isOpticalLineInConnected()) { + if ((lineInType != LineInType.DIGITAL && remoteHandler.isAnalogLineInConnected()) + || (lineInType != LineInType.ANALOG && remoteHandler.isOpticalLineInConnected())) { // stop whatever is currently playing coordinatorHandler.stop(); // set the URI - if (remoteHandler.isAnalogLineInConnected()) { + if (lineInType != LineInType.DIGITAL && remoteHandler.isAnalogLineInConnected()) { coordinatorHandler.setCurrentURI(ANALOG_LINE_IN_URI + remoteHandler.getUDN(), ""); } else { coordinatorHandler.setCurrentURI(OPTICAL_LINE_IN_URI + remoteHandler.getUDN() + SPDIF, ""); @@ -2168,12 +2218,11 @@ public void snoozeAlarm(Command command) { } public Boolean isAnalogLineInConnected() { - return ((stateMap.get("LineInConnected") != null) && stateMap.get("LineInConnected").equals("true")) ? true - : false; + return ((stateMap.get(LINEINCONNECTED) != null) && stateMap.get(LINEINCONNECTED).equals("true")) ? true : false; } public Boolean isOpticalLineInConnected() { - return ((stateMap.get("TOSLinkConnected") != null) && stateMap.get("TOSLinkConnected").equals("true")) ? true + return ((stateMap.get(TOSLINEINCONNECTED) != null) && stateMap.get(TOSLINEINCONNECTED).equals("true")) ? true : false; } @@ -2197,9 +2246,10 @@ public void addMember(Command command) { } } - public boolean publicAddress() { + public boolean publicAddress(LineInType lineInType) { // check if sourcePlayer has a line-in connected - if (isAnalogLineInConnected() || isOpticalLineInConnected()) { + if ((lineInType != LineInType.DIGITAL && isAnalogLineInConnected()) + || (lineInType != LineInType.ANALOG && isOpticalLineInConnected())) { // first remove this player from its own group if any becomeStandAlonePlayer(); @@ -2228,7 +2278,7 @@ public boolean publicAddress() { ZonePlayerHandler coordinator = getCoordinatorHandler(); // set the URI of the group to the line-in SonosEntry entry = new SonosEntry("", "", "", "", "", "", "", ANALOG_LINE_IN_URI + getUDN()); - if (isOpticalLineInConnected()) { + if (lineInType != LineInType.ANALOG && isOpticalLineInConnected()) { entry = new SonosEntry("", "", "", "", "", "", "", OPTICAL_LINE_IN_URI + getUDN() + SPDIF); } coordinator.setCurrentURI(entry); @@ -2940,11 +2990,13 @@ public String getCurrentZoneName() { @Override public void onStatusChanged(boolean status) { if (status) { + logger.info("UPnP device {} is present (thing {})", getUDN(), getThing().getUID()); if (getThing().getStatus() != ThingStatus.ONLINE) { updateStatus(ThingStatus.ONLINE); - scheduler.execute(pollingRunnable); + scheduler.execute(this::poll); } } else { + logger.info("UPnP device {} is absent (thing {})", getUDN(), getThing().getUID()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.OFFLINE.COMMUNICATION_ERROR); } } diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/binding/binding.xml index 21de6ac7e03e4..0eb2a8a2216ca 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Sonos Binding diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/config/config.xml index f72f6da12e757..2c57a3070ff24 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Amp.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Amp.xml new file mode 100644 index 0000000000000..b5c4e5876dc76 --- /dev/null +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Amp.xml @@ -0,0 +1,74 @@ + + + + + + + + Represents SONOS Amp amplifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SONOS + Amp + + + udn + + + + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Beam.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Beam.xml index 3f000589247bb..2fe0effc8c769 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Beam.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Beam.xml @@ -10,53 +10,53 @@ Represents SONOS Beam soundbar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + @@ -66,6 +66,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/CONNECT.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/CONNECT.xml index 630c329573e86..001dab4403878 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/CONNECT.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/CONNECT.xml @@ -10,51 +10,51 @@ Represents SONOS CONNECT connector - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -64,6 +64,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/CONNECTAMP.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/CONNECTAMP.xml index 87c8a9a94d67d..6222b953555ed 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/CONNECTAMP.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/CONNECTAMP.xml @@ -11,51 +11,51 @@ Represents SONOS CONNECT:AMP amplifier - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -65,6 +65,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/One.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/One.xml index d7c84281f3bb4..55886066be2f6 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/One.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/One.xml @@ -11,49 +11,50 @@ Represents SONOS One Zone Player - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -63,6 +64,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/OneSL.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/OneSL.xml new file mode 100644 index 0000000000000..9b117d88328ed --- /dev/null +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/OneSL.xml @@ -0,0 +1,68 @@ + + + + + + + + Represents SONOS One SL Zone Player + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SONOS + One SL + + + udn + + + + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY1.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY1.xml index 7c371e00e5e3f..5afa47695f6cf 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY1.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY1.xml @@ -11,49 +11,49 @@ Represents SONOS PLAY:1 Zone Player - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -63,6 +63,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY3.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY3.xml index f79d40805ee7c..90f9d24cb4b3f 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY3.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY3.xml @@ -11,49 +11,49 @@ Represents SONOS PLAY:3 Zone Player - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -63,6 +63,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY5.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY5.xml index 42456593184bb..4f1e14ac45d08 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY5.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAY5.xml @@ -11,51 +11,51 @@ Represents SONOS PLAY:5 Zone Player - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -65,6 +65,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAYBAR.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAYBAR.xml index 67b79594b0c0f..d1bd3c3e1d127 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAYBAR.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAYBAR.xml @@ -10,53 +10,53 @@ Represents SONOS PLAYBAR soundbar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + @@ -66,6 +66,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAYBASE.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAYBASE.xml index 4934ad5b7f4fc..044bd51cc6203 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAYBASE.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/PLAYBASE.xml @@ -10,53 +10,53 @@ Represents SONOS PLAYBASE soundbar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + @@ -66,6 +66,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Port.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Port.xml new file mode 100644 index 0000000000000..aec986d4975fd --- /dev/null +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/Port.xml @@ -0,0 +1,69 @@ + + + + + + + Represents SONOS Port connector + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + SONOS + Port + + + udn + + + + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/SYMFONISK.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/SYMFONISK.xml index 7442861b065a6..03122f46033ab 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/SYMFONISK.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/SYMFONISK.xml @@ -10,48 +10,48 @@ Represents IKEA SYMFONISK speaker - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -61,6 +61,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/ZonePlayer.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/ZonePlayer.xml index 4af5854f16dc2..1368dbd73e1ee 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/ZonePlayer.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/ZonePlayer.xml @@ -11,49 +11,49 @@ The Zone Player represents a Sonos Zone Player which is not known to this binding - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -63,6 +63,6 @@ udn - + diff --git a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/channels.xml index 6a81cb89ce4f2..c6281e24328d7 100644 --- a/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.sonos/src/main/resources/ESH-INF/thing/channels.xml @@ -14,21 +14,22 @@ Switch - Set the first occurring alarm either ON or OFF. Alarms first have to be defined through the Sonos Controller app + Set the first occurring alarm either ON or OFF. Alarms first have to be defined through the Sonos + Controller app String Properties of the alarm currently running - + Switch Set to ON if the alarm was triggered - + @@ -41,49 +42,49 @@ String UDN of the coordinator for the current group - + String Name of the album currently playing - + Image Cover art of the album currently playing - + String Cover art URL of the album currently playing - + String Name of the current track or radio station currently playing - + String URI of the current track - + String URI of the current AV transport - + @@ -102,7 +103,7 @@ Switch Indicator set to ON if this Zone Player is the Zone Group Coordinator - + @@ -144,7 +145,8 @@ Switch - Put all Zone Players in one group, and stream audio from the line-in from the Zone Player that triggered the command + Put all Zone Players in one group, and stream audio from the line-in from the Zone Player that triggered + the command @@ -206,14 +208,14 @@ Number Set/show the duration of the sleep timer in seconds - + Number Snooze the running alarm, if any, with the given number of minutes - + @@ -259,14 +261,14 @@ String Id of the Zone Group the Zone Player belongs to - + String Name of the Zone Group associated to the Zone Player - + @@ -274,7 +276,7 @@ Switch Indicator set to ON when the line-in of the Zone Player is connected - + diff --git a/bundles/org.openhab.binding.sonyaudio/README.md b/bundles/org.openhab.binding.sonyaudio/README.md index 9b82d5e3b238b..6e8eddbef9de0 100644 --- a/bundles/org.openhab.binding.sonyaudio/README.md +++ b/bundles/org.openhab.binding.sonyaudio/README.md @@ -63,6 +63,7 @@ The devices support the following channels: | radio#broadcastFreq | Number | R | Current radio frequency | STR-1080 | | radio#broadcastStation | Number | RW | Set or get current preset radio station | STR-1080 | | radio#broadcastSeekStation | String | W | Seek for new broadcast station, forward search "fwdSeeking" and backward "bwdSeeking" | STR-1080 | +| nightMode | Switch | RW | Set or get the Night Mode state | HT-ZF9 | ## Full Example diff --git a/bundles/org.openhab.binding.sonyaudio/pom.xml b/bundles/org.openhab.binding.sonyaudio/pom.xml index 69b0af98e1f29..7048463a347de 100644 --- a/bundles/org.openhab.binding.sonyaudio/pom.xml +++ b/bundles/org.openhab.binding.sonyaudio/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.sonyaudio diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/feature/feature.xml b/bundles/org.openhab.binding.sonyaudio/src/main/feature/feature.xml index a088f34735471..8e10571ae7e24 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.sonyaudio/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.sonyaudio/${project.version} - + + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.sonyaudio/${project.version} + diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/SonyAudioBindingConstants.java b/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/SonyAudioBindingConstants.java index fdaa6938e3b4a..ef68b2de5fb09 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/SonyAudioBindingConstants.java +++ b/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/SonyAudioBindingConstants.java @@ -90,6 +90,8 @@ public class SonyAudioBindingConstants { public static final String CHANNEL_RADIO_STATION = "radio#broadcastStation"; public static final String CHANNEL_RADIO_SEEK_STATION = "radio#broadcastSeekStation"; + public static final String CHANNEL_NIGHTMODE = "nightMode"; + // Used for Discovery service public static final String MANUFACTURER = "SONY"; public static final String UPNP_DEVICE_TYPE = "MediaRenderer"; diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/SonyAudioHandlerFactory.java b/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/SonyAudioHandlerFactory.java index 413c23947e92e..42897f40c30f6 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/SonyAudioHandlerFactory.java +++ b/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/SonyAudioHandlerFactory.java @@ -77,5 +77,4 @@ protected void setWebSocketFactory(WebSocketFactory webSocketFactory) { protected void unsetWebSocketFactory(WebSocketFactory webSocketFactory) { this.webSocketClient = null; } - } diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/handler/SonyAudioHandler.java b/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/handler/SonyAudioHandler.java index 626f7528031a3..4e2886355eb71 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/handler/SonyAudioHandler.java +++ b/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/handler/SonyAudioHandler.java @@ -233,8 +233,11 @@ public void handleCommand(ChannelUID channelUID, Command command) { case CHANNEL_RADIO_SEEK_STATION: handleRadioSeekStationCommand(command, channelUID); break; + case CHANNEL_NIGHTMODE: + handleNightMode(command, channelUID); + break; default: - logger.error("Channel {} not supported!", id); + logger.error("Command {}, {} not supported by {}!", id, command, channelUID); } } catch (IOException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); @@ -255,6 +258,20 @@ public void handleSoundSettings(Command command, ChannelUID channelUID) throws I } } + public void handleNightMode(Command command, ChannelUID channelUID) throws IOException { + if (command instanceof RefreshType) { + logger.debug("handleNightMode RefreshType"); + Map result = soundSettingsCache.getValue(); + if (result != null) { + updateState(channelUID, new StringType(result.get("nightMode"))); + } + } + if (command instanceof OnOffType) { + logger.debug("handleNightMode set {}", command); + connection.setSoundSettings("nightMode", ((OnOffType) command) == OnOffType.ON ? "on" : "off"); + } + } + public void handlePowerCommand(Command command, ChannelUID channelUID) throws IOException { handlePowerCommand(command, channelUID, 0); } diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/protocol/SonyAudioMethod.java b/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/protocol/SonyAudioMethod.java index 9b308f7ca6700..fe6aa71a77adc 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/protocol/SonyAudioMethod.java +++ b/bundles/org.openhab.binding.sonyaudio/src/main/java/org/openhab/binding/sonyaudio/internal/protocol/SonyAudioMethod.java @@ -239,7 +239,6 @@ class Param { output = "extOutput:zone?zone=" + Integer.toString(zone); } } - } SetAudioVolume(int volume, int min, int max) { diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/config/config.xml index 8f9871b9df43c..a81158e573f3e 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/config/config.xml @@ -13,7 +13,8 @@ Port for the SONY audio device to control. - Home Audio products usually use port 10000 and Personal Audio products usually use port 54480. + Home Audio products usually use port 10000 and Personal Audio + products usually use port 54480. 10000 @@ -24,7 +25,9 @@ - The refresh interval in seconds for polling the receiver (0=disable). Binding receive automatically updates from + The refresh interval in seconds for polling the receiver (0=disable). Binding receive automatically + updates from + 300 true diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-ct800.xml b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-ct800.xml index 5039cb8e62ac6..4edb3e16eb9ff 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-ct800.xml +++ b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-ct800.xml @@ -45,12 +45,12 @@ SONY Soundbar HT-CT800 - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-mt500.xml b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-mt500.xml index f56db56393664..cd2158adb3ef3 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-mt500.xml +++ b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-mt500.xml @@ -42,12 +42,12 @@ SONY Soundbar HT-MT500 - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-st5000.xml b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-st5000.xml index 8a1522409e1b0..935667df8d70a 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-st5000.xml +++ b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-st5000.xml @@ -46,12 +46,12 @@ SONY Soundbar HT-ST5000 - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-z9f-zf9.xml b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-z9f-zf9.xml index a24fae778c0a1..a4bb6331ade0c 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-z9f-zf9.xml +++ b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/ht-z9f-zf9.xml @@ -40,18 +40,24 @@ + + Switch + + Enable/Disable Night Mode + + SONY Soundbar HT-Z9F - - - - - + + + + + - + @@ -59,12 +65,13 @@ SONY Soundbar HT-ZF9 - - - - - + + + + + + - + diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/srs-zr5.xml b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/srs-zr5.xml index 9b22c0e6156dd..5cde46759fecc 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/srs-zr5.xml +++ b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/srs-zr5.xml @@ -45,12 +45,12 @@ SONY wireless Speaker SRS-ZR5 - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/str-dn1080.xml b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/str-dn1080.xml index b69a66815c252..167d40f0533c8 100644 --- a/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/str-dn1080.xml +++ b/bundles/org.openhab.binding.sonyaudio/src/main/resources/ESH-INF/thing/str-dn1080.xml @@ -7,45 +7,45 @@ - - + + - - - - + + + + - - - - + + + + - - + + - - - + + + @@ -155,13 +155,13 @@ SONY receiver STR-DN1080 - - - - - + + + + + - + diff --git a/bundles/org.openhab.binding.sonyprojector/pom.xml b/bundles/org.openhab.binding.sonyprojector/pom.xml index c2ecca418c4c3..4e02dcac466d5 100644 --- a/bundles/org.openhab.binding.sonyprojector/pom.xml +++ b/bundles/org.openhab.binding.sonyprojector/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.sonyprojector diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/feature/feature.xml b/bundles/org.openhab.binding.sonyprojector/src/main/feature/feature.xml index b6da5538c9391..6c2bd249d18dd 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.sonyprojector/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.sonyprojector/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.sonyprojector/${project.version} + diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorBindingConstants.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorBindingConstants.java index 0597772baecdb..01d49b149b035 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorBindingConstants.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorBindingConstants.java @@ -63,5 +63,4 @@ public class SonyProjectorBindingConstants { public static final String CHANNEL_OVERSCAN = "overscan"; public static final String CHANNEL_PICTURE_POSITION = "pictureposition"; public static final String CHANNEL_LAMP_USE_TIME = "lampusetime"; - } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorHandlerFactory.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorHandlerFactory.java index 73489204a547f..2d116d72004fe 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorHandlerFactory.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/SonyProjectorHandlerFactory.java @@ -28,6 +28,7 @@ import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.sonyprojector.internal.handler.SonyProjectorHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -45,9 +46,16 @@ public class SonyProjectorHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet( Stream.of(THING_TYPE_ETHERNET, THING_TYPE_SERIAL, THING_TYPE_SERIAL_OVER_IP).collect(Collectors.toSet())); - private @NonNullByDefault({}) SerialPortManager serialPortManager; + private final SerialPortManager serialPortManager; - private @NonNullByDefault({}) SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider; + private final SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider; + + @Activate + public SonyProjectorHandlerFactory(final @Reference SerialPortManager serialPortManager, + final @Reference SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider) { + this.serialPortManager = serialPortManager; + this.stateDescriptionProvider = stateDescriptionProvider; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -64,24 +72,4 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return null; } - - @Reference - protected void setSerialPortManager(final SerialPortManager serialPortManager) { - this.serialPortManager = serialPortManager; - } - - protected void unsetSerialPortManager(final SerialPortManager serialPortManager) { - this.serialPortManager = null; - } - - @Reference - protected void setDynamicStateDescriptionProvider( - SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider) { - this.stateDescriptionProvider = stateDescriptionProvider; - } - - protected void unsetDynamicStateDescriptionProvider( - SonyProjectorStateDescriptionOptionProvider stateDescriptionProvider) { - this.stateDescriptionProvider = null; - } } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/SonyProjectorItem.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/SonyProjectorItem.java index e7c8d69f321b9..f3d2956262bb9 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/SonyProjectorItem.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/SonyProjectorItem.java @@ -151,5 +151,4 @@ public byte[] getCode() { public String getName() { return name; } - } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialConnector.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialConnector.java index 30239e950e8b0..222f0850d97d2 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialConnector.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialConnector.java @@ -304,5 +304,4 @@ public void serialEvent(SerialPortEvent serialPortEvent) { } catch (InterruptedException e) { } } - } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialOverIpConnector.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialOverIpConnector.java index cbddc95ef7617..852dfb95bded8 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialOverIpConnector.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/communication/serial/SonyProjectorSerialOverIpConnector.java @@ -125,5 +125,4 @@ protected int readInput(byte[] dataBuffer) throws SonyProjectorException { throw new SonyProjectorException("readInput failed: " + e.getMessage()); } } - } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorEthernetConfiguration.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorEthernetConfiguration.java index 1163793738ed2..79e2f43e2ffb2 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorEthernetConfiguration.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorEthernetConfiguration.java @@ -28,5 +28,4 @@ public class SonyProjectorEthernetConfiguration { public @Nullable Integer port; public @Nullable String community; public @Nullable String model; - } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorSerialConfiguration.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorSerialConfiguration.java index d0997fe84852f..ff80902e349d9 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorSerialConfiguration.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorSerialConfiguration.java @@ -24,5 +24,4 @@ public class SonyProjectorSerialConfiguration { public @NonNullByDefault({}) String port; public @NonNullByDefault({}) String model; - } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorSerialOverIpConfiguration.java b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorSerialOverIpConfiguration.java index 1a9185241c987..2ce35e850db24 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorSerialOverIpConfiguration.java +++ b/bundles/org.openhab.binding.sonyprojector/src/main/java/org/openhab/binding/sonyprojector/internal/configuration/SonyProjectorSerialOverIpConfiguration.java @@ -25,5 +25,4 @@ public class SonyProjectorSerialOverIpConfiguration { public @NonNullByDefault({}) String host; public @NonNullByDefault({}) Integer port; public @NonNullByDefault({}) String model; - } diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/channels.xml index 5c5c7c66dc383..73b4e4bda426d 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/channels.xml @@ -33,35 +33,35 @@ Dimmer Adjust the contrast of the picture - + Dimmer Adjust the brightness of the picture - + Dimmer Adjust the color density - + Dimmer Adjust the color tone - + Dimmer Sharpen the outline of the picture or reduce the noise - + @@ -80,7 +80,7 @@ Dimmer Force the iris aperture to a fixed value - + diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/ethernet.xml b/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/ethernet.xml index f0cb458edfe33..bbdd1aa1618c1 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/ethernet.xml +++ b/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/ethernet.xml @@ -10,36 +10,36 @@ Ethernet connection to the Sony projector using PJ Talk - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/serial.xml b/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/serial.xml index b0bb7a4bbf4ec..d732c2e7829bb 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/serial.xml +++ b/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/serial.xml @@ -10,41 +10,42 @@ Serial connection to the Sony projector - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + serial-port + false Serial port to use for connecting to the projector diff --git a/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/serialoverip.xml b/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/serialoverip.xml index 3003419f70d5f..7fcf73fbadc5e 100644 --- a/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/serialoverip.xml +++ b/bundles/org.openhab.binding.sonyprojector/src/main/resources/ESH-INF/thing/serialoverip.xml @@ -10,36 +10,36 @@ Serial over IP connection to the Sony projector - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.spotify/pom.xml b/bundles/org.openhab.binding.spotify/pom.xml index ee59acc299aa5..8e58cb6e38d0c 100644 --- a/bundles/org.openhab.binding.spotify/pom.xml +++ b/bundles/org.openhab.binding.spotify/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.spotify diff --git a/bundles/org.openhab.binding.spotify/src/main/feature/feature.xml b/bundles/org.openhab.binding.spotify/src/main/feature/feature.xml index cc01b7a9fb061..cd2c35bcaee9d 100644 --- a/bundles/org.openhab.binding.spotify/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.spotify/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - mvn:org.openhab.addons.bundles/org.openhab.binding.spotify/${project.version} - + + openhab-runtime-base + openhab-transport-http + mvn:org.openhab.addons.bundles/org.openhab.binding.spotify/${project.version} + diff --git a/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/api/exception/SpotifyAuthorizationException.java b/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/api/exception/SpotifyAuthorizationException.java index fc1100de5bd49..6828d67bf7c59 100644 --- a/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/api/exception/SpotifyAuthorizationException.java +++ b/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/api/exception/SpotifyAuthorizationException.java @@ -39,5 +39,4 @@ public SpotifyAuthorizationException(String message) { public SpotifyAuthorizationException(String message, Throwable exception) { super(message, exception); } - } diff --git a/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/api/exception/SpotifyException.java b/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/api/exception/SpotifyException.java index e72dfab18d463..cb86e145dff0a 100644 --- a/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/api/exception/SpotifyException.java +++ b/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/api/exception/SpotifyException.java @@ -39,5 +39,4 @@ public SpotifyException(String message) { public SpotifyException(String message, Throwable cause) { super(message, cause); } - } diff --git a/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/handler/SpotifyBridgeHandler.java b/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/handler/SpotifyBridgeHandler.java index 420bba11d042b..389d2d31269a6 100644 --- a/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/handler/SpotifyBridgeHandler.java +++ b/bundles/org.openhab.binding.spotify/src/main/java/org/openhab/binding/spotify/internal/handler/SpotifyBridgeHandler.java @@ -570,7 +570,6 @@ private void updateChannelState(String channelId, State state) { if (channel != null && isLinked(channel.getUID())) { updateState(channel.getUID(), state); } - } /** diff --git a/bundles/org.openhab.binding.spotify/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.spotify/src/main/resources/ESH-INF/thing/thing-types.xml index 3d61d3c2f3602..198ed4053c39f 100644 --- a/bundles/org.openhab.binding.spotify/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.spotify/src/main/resources/ESH-INF/thing/thing-types.xml @@ -10,55 +10,55 @@ Bridge representing the Spotify Player in the context of a user account. The bridge is associated with -one specific Spotify account. If you want to control your devices in the context of different accounts you have to -register a bridge for each account. Go to http://your openHAB address::8080/connectspotify to authorize. + one specific Spotify account. If you want to control your devices in the context of different accounts you have to + register a bridge for each account. Go to http://your openHAB address::8080/connectspotify to authorize. - + - - - - - - + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - + + + + + - + clientId @@ -68,19 +68,23 @@ register a bridge for each account. Go to http://your openHAB address::8080/conn true This is the Client ID provided by Spotify when you add a new Application for openHAB to your Spotify -Account. Go to https://developer.spotify.com/ + Account. Go to https://developer.spotify.com/ true - This is the Client Secret provided by Spotify when you add a new Application for openHAB to your Spotify Account. + This is the Client Secret provided by Spotify when you add a new Application for openHAB to your + Spotify Account. true 10 - This is the frequency of the polling requests to the Spotify Connect Web API. There are limits to the number of requests -that can be sent to the Web API. The more often you poll, the better status updates - at the risk of running out of your request quota. + This is the frequency of the polling requests to the Spotify Connect Web API. There are limits to the + number of requests + that can be sent to the Web API. The more often you poll, the better status updates - at the risk + of running out of + your request quota. @@ -89,24 +93,24 @@ that can be sent to the Web API. The more often you poll, the better status upda - + Thing representing a Spotify Connect device. The device exists in the context of the bridge and the -Spotify account associated with the bride. This means the same device can be present as a thing under each Spotify -bridge you have configured. + Spotify account associated with the bride. This means the same device can be present as a thing under each Spotify + bridge you have configured. - - - - - - - - - + + + + + + + + + deviceName @@ -124,7 +128,8 @@ bridge you have configured. String - The access token used to authorize calls to the Spotify Web API. It can be used from rules or client-side scripting make call to Web API. + The access token used to authorize calls to the Spotify Web API. It can be used from rules or client-side + scripting make call to Web API. @@ -146,7 +151,7 @@ bridge you have configured. String Currently active device type, such as "Computer", "Smartphone" or "Speaker". - + Switch @@ -174,7 +179,8 @@ bridge you have configured. String - 'track' will repeat the current track. 'context' will repeat the current context. 'off' will turn repeat off. + 'track' will repeat the current track. 'context' will repeat the current context. 'off' will turn repeat + off. @@ -187,135 +193,135 @@ bridge you have configured. String Channel reports track id currently being played. - + String - + String The Spotify URI for the track currently played - + String The type of the track currently played track type - + Number The duration of the currently played track (ms) - + Number The progress of the currently played track (ms) - + String The duration currently played track formatted (m:ss) - + String The progress of the currently played track formatted (m:ss) - + Number The track number of currently played track - + Number The disk number of currently played track - + Number The popularity of the currently played track - + Switch Whether or not the track has explicit lyrics (On it does; Off it does not OR unknown) - + String The Spotify ID of the album - + String A link to the Web API endpoint providing full details of the album - + String The Spotify URI for the album - + String The name of the album - + String The object type: "album" - + Image The cover art for the album in widest size - + String The Spotify ID for the artist - + String Channel reports currently played artist href - + String A link to the Web API endpoint providing full details of the artist - + String The object type: "artist" - + @@ -327,13 +333,13 @@ bridge you have configured. String The name of the device - + String Device type, such as "Computer", "Smartphone" or "Speaker". - + Switch @@ -348,7 +354,8 @@ bridge you have configured. Switch - Whether controlling this device is restricted. At present if this is "true" then no Web API commands will be accepted by this device + Whether controlling this device is restricted. At present if this is "true" then no Web API commands will + be accepted by this device diff --git a/bundles/org.openhab.binding.squeezebox/pom.xml b/bundles/org.openhab.binding.squeezebox/pom.xml index 0c6381f8d4d4f..f20a6fc0f99b7 100644 --- a/bundles/org.openhab.binding.squeezebox/pom.xml +++ b/bundles/org.openhab.binding.squeezebox/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.squeezebox diff --git a/bundles/org.openhab.binding.squeezebox/src/main/feature/feature.xml b/bundles/org.openhab.binding.squeezebox/src/main/feature/feature.xml index f14d0edfca05e..17d41767f69b3 100644 --- a/bundles/org.openhab.binding.squeezebox/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.squeezebox/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.squeezebox/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.squeezebox/${project.version} + diff --git a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/discovery/SqueezeBoxPlayerDiscoveryParticipant.java b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/discovery/SqueezeBoxPlayerDiscoveryParticipant.java index 627623739c162..a464b827944e0 100644 --- a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/discovery/SqueezeBoxPlayerDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/discovery/SqueezeBoxPlayerDiscoveryParticipant.java @@ -91,7 +91,8 @@ public void playerAdded(SqueezeBoxPlayer player) { logger.debug("player added {} : {} ", player.getMacAddress(), player.getName()); Map properties = new HashMap<>(1); - properties.put("mac", player.getMacAddress()); + String representationPropertyName = "mac"; + properties.put(representationPropertyName, player.getMacAddress()); // Added other properties properties.put("modelId", player.getModel()); @@ -100,14 +101,15 @@ public void playerAdded(SqueezeBoxPlayer player) { properties.put("ip", player.getIpAddr()); DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) - .withBridge(bridgeUID).withLabel(player.getName()).build(); + .withRepresentationProperty(representationPropertyName).withBridge(bridgeUID) + .withLabel(player.getName()).build(); thingDiscovered(discoveryResult); } } private boolean playerThingExists(ThingUID newThingUID) { - return squeezeBoxServerHandler.getThingByUID(newThingUID) != null ? true : false; + return squeezeBoxServerHandler.getThing().getThing(newThingUID) != null ? true : false; } /** diff --git a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/discovery/SqueezeBoxServerDiscoveryParticipant.java b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/discovery/SqueezeBoxServerDiscoveryParticipant.java index d302cec96e87f..66321746b8342 100644 --- a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/discovery/SqueezeBoxServerDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/discovery/SqueezeBoxServerDiscoveryParticipant.java @@ -82,12 +82,13 @@ public DiscoveryResult createResult(RemoteDevice device) { String label = device.getDetails().getFriendlyName(); - properties.put("ipAddress", host); + String representationPropertyName = "ipAddress"; + properties.put(representationPropertyName, host); properties.put("webport", new Integer(webPort)); properties.put("cliPort", new Integer(cliPort)); - DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(label) - .build(); + DiscoveryResult result = DiscoveryResultBuilder.create(uid).withProperties(properties) + .withRepresentationProperty(representationPropertyName).withLabel(label).build(); logger.debug("Created a DiscoveryResult for device '{}' with UDN '{}'", device.getDetails().getFriendlyName(), device.getIdentity().getUdn().getIdentifierString()); @@ -109,5 +110,4 @@ public ThingUID getThingUID(RemoteDevice device) { } return null; } - } diff --git a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/handler/SqueezeBoxPlayerHandler.java b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/handler/SqueezeBoxPlayerHandler.java index 2e71c1eee8f99..855429deeb375 100644 --- a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/handler/SqueezeBoxPlayerHandler.java +++ b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/handler/SqueezeBoxPlayerHandler.java @@ -377,7 +377,6 @@ public void numberPlaylistTracksEvent(String mac, int track) { @Override public void currentPlaylistShuffleEvent(String mac, int shuffle) { updateChannel(mac, CHANNEL_CURRENT_PLAYLIST_SHUFFLE, new DecimalType(shuffle)); - } @Override @@ -388,7 +387,6 @@ public void currentPlaylistRepeatEvent(String mac, int repeat) { @Override public void titleChangeEvent(String mac, String title) { updateChannel(mac, CHANNEL_TITLE, new StringType(title)); - } @Override diff --git a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/handler/SqueezeBoxServerHandler.java b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/handler/SqueezeBoxServerHandler.java index 9e850c9d37152..acb37c1d99c23 100644 --- a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/handler/SqueezeBoxServerHandler.java +++ b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/handler/SqueezeBoxServerHandler.java @@ -867,7 +867,6 @@ public void updateListener(SqueezeBoxPlayerEventListener listener) { public void updateListener(SqueezeBoxPlayerEventListener listener) { listener.modeChangeEvent(mac, value); } - }); } @@ -880,7 +879,6 @@ private void handleSourceChangeMessage(String mac, String rawSource) { public void updateListener(SqueezeBoxPlayerEventListener listener) { listener.sourceChangeEvent(mac, source); } - }); } @@ -910,7 +908,6 @@ public void updateListener(SqueezeBoxPlayerEventListener listener) { public void updateListener(SqueezeBoxPlayerEventListener listener) { listener.absoluteVolumeChangeEvent(mac, volume); } - }); } } diff --git a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/utils/HttpUtils.java b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/utils/HttpUtils.java index 9bc78d7c649d2..69fe25ccc6081 100644 --- a/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/utils/HttpUtils.java +++ b/bundles/org.openhab.binding.squeezebox/src/main/java/org/openhab/binding/squeezebox/internal/utils/HttpUtils.java @@ -108,5 +108,4 @@ public static int getCliPort(String ip, int webPort) String cliPort = resp.getAsJsonObject().get("result").getAsJsonObject().get("_p2").getAsString(); return Integer.parseInt(cliPort); } - } diff --git a/bundles/org.openhab.binding.squeezebox/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.squeezebox/src/main/resources/ESH-INF/binding/binding.xml index 09b5cebd63fa3..dce730e9ba8c4 100644 --- a/bundles/org.openhab.binding.squeezebox/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.squeezebox/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - SqueezeBox Binding diff --git a/bundles/org.openhab.binding.squeezebox/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.squeezebox/src/main/resources/ESH-INF/thing/thing-types.xml index 09409984ebc42..be1bbbb465402 100644 --- a/bundles/org.openhab.binding.squeezebox/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.squeezebox/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -8,9 +9,11 @@ This is a SqueezeBox Server instance. - + + ipAddress + @@ -46,40 +49,40 @@ - + This is a SqueezeBox Player instance - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -90,6 +93,8 @@ + mac + @@ -183,7 +188,7 @@ Play the given HTTP or file stream (file:// or http://). - String + String Shows the source of the currently playing playlist entry. diff --git a/bundles/org.openhab.binding.synopanalyzer/pom.xml b/bundles/org.openhab.binding.synopanalyzer/pom.xml index 2293456c114e0..ab51d4e2243e9 100644 --- a/bundles/org.openhab.binding.synopanalyzer/pom.xml +++ b/bundles/org.openhab.binding.synopanalyzer/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.synopanalyzer diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/feature/feature.xml b/bundles/org.openhab.binding.synopanalyzer/src/main/feature/feature.xml index 53dfacf2df3f1..6d79467c54824 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.synopanalyzer/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.synopanalyzer/${project.version} + diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/Constants.java b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/Constants.java index e92afa0a95474..f798f49f1b9f9 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/Constants.java +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/Constants.java @@ -1,162 +1,162 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.synopanalyser.internal.synop; - -/** - * The {@link Constants} class defines common constants, which are - * used across the whole package. - * - * @author Jonarzz - Initial contribution - */ -public class Constants { - - public static final int INITIAL_VALUE = -1000; - public static final String UNKNOWN_VALUE = "/"; - - public static final String CHAPTER_3_CODE = "333"; - public static final String CHAPTER_4_CODE = "444"; - public static final String CHAPTER_5_CODE = "555"; - - public static final char PLUS_SIGN_TEMPERATURE = '0'; - public static final char MINUS_SIGN_TEMPERATURE = '1'; - - public static final String LAND_STATION_CODE = "AAXX"; - public static final String SHIP_STATION_CODE = "BBXX"; - public static final String MOBILE_LAND_STATION_CODE = "OOXX"; - - /* - * WS - WIND SPEED - */ - public static final int WS_WILDTYPE_IN_MPS = 0; - public static final int WS_ANEMOMETER_IN_MPS = 1; - public static final int WS_WILDTYPE_IN_KNOT = 3; - public static final int WS_ANEMOMETER_IN_KNOT = 4; - - public static final String WS_MPS = "m/s"; - public static final String WS_KNOTS = "knots"; - - /* - * DFG - DOWNFALL GROUP VALUES FROM '0' TO '4' - */ - public static final char DFG_IN_CHAPTER_1_AND_3 = '0'; - public static final char DFG_IN_CHAPTER_1 = '1'; - public static final char DFG_IN_CHAPTER_3 = '2'; - public static final char DFG_NO_DF = '3'; - public static final char DFG_NO_MEASUREMENT = '4'; - - /* - * ST - STATION TYPE - * A - AUTOMATIC - * N - NON-AUTOMATIC - * VALUES FROM '1' TO '6' - */ - public static final char ST_N_GROUP_7_ON = '1'; - public static final char ST_N_GROUP_7_OFF_NO_PHENOMENON = '2'; - public static final char ST_N_GROUP_7_OFF_NO_DATA = '3'; - public static final char ST_A_GROUP_7_ON = '4'; - public static final char ST_A_GROUP_7_OFF_NO_PHENOMENON = '5'; - public static final char ST_A_GROUP_7_OFF_NO_DATA = '6'; - - /* - * CH - CLOUD HEIGH [IN METERS] - * VALUES FROM '0' TO '9' - * '/' ACCEPTABLE - */ - public static final char CH_0_50 = '0'; - public static final char CH_50_100 = '1'; - public static final char CH_100_200 = '2'; - public static final char CH_200_300 = '3'; - public static final char CH_300_600 = '4'; - public static final char CH_600_1000 = '5'; - public static final char CH_1000_1500 = '6'; - public static final char CH_1500_2000 = '7'; - public static final char CH_2000_2500 = '8'; - public static final char CH_OVER_2500 = '9'; - - /* - * HV - HORIZONTAL VISIBILITY [IN KILOMETERS] - * VALUES FROM "00" TO "50" AND FROM "56" TO "99" - * 00 MEANS HV = BELOW 0,1 - * DECIMAL SCOPE MEANS HV = XX / 10 - * UNIT SCOPE MEANS HV = XX - 50 - * 89 MEANS HV = OVER 70 - * 90-99 ROUGHLY NUMBERING : - * 90 - < 0,05 km - * 91 >= 0,05 < 0,2 km - * 92 >= 0,2 < 0,5 km - * 93 >= 0,5 < 1,0 km - * 94 >= 1,0 < 2,0 km - * 95 >= 2,0 < 4,0 km - * 96 >= 4,0 < 10,0 km - * 97 >= 10,0 < 20,0 km - * 98 >= 20,0 < 50,0 km - * 99 - > 50 km - * HP - high precision - */ - public static final int HV_LESS_THAN_1_LIMIT = 10; - public static final int HV_LESS_THAN_10_LIMIT = 60; - public static final int HV_LESS_THAN_50_LIMIT = 84; - public static final int HV_HP_LIMIT = 90; - public static final int HV_LESS_THAN_1_HP_LIMIT = 93; - public static final int HV_LESS_THAN_10_HP_LIMIT = 96; - public static final int HV_LESS_THAN_50_HP_LIMIT = 98; - - public static final String HV_LESS_THAN_1_STRING = "<1"; - public static final String HV_LESS_THAN_10_STRING = "1-10"; - public static final String HV_LESS_THAN_50_STRING = "10-50"; - public static final String HV_MORE_THAN_50_STRING = ">50"; - - /* - * CLOUDINESS = x/8 - * VALUES FROM '0' TO '9' - * '/' ACCEPTABLE - */ - public static final String CLEAR_SKY = "NO CLOUDS"; - public static final String CLOUDY = "CLOUDY"; - public static final String SKY_NOT_VISIBLE = "SKY NOT VISIBLE"; - - /* - * WIND DIRECTION - * WD = FROM { 5 + (yy - 1) * 9 } TO { 5 + yy * 9 } OR: - * VALUES FROM "00" TO "36" AND "99" - * "//" ACCEPTABLE - */ - public static final String WD_NO_WIND = "00"; - public static final String WD_VARIABLE = "99"; - - /* - * PCT - PRESSURE CHANGE TYPE - * VALUES FROM '0' TO '8' - */ - public static final char PCT_INCREASE_LOWER_LIMIT = '0'; - public static final char PCT_INCREASE_UPPER_LIMIT = '3'; - public static final char PCT_NO_CHANGE = '4'; - public static final char PCT_DECREASE_LOWER_LIMIT = '5'; - public static final char PCT_DECREASE_UPPER_LIMIT = '8'; - - /* - * TD - TOTAL DOWNFALL - * SOP - SCOPE OF PROPORTIONALITY - * SOP MEANS TD = fff [IN MILIMETERS] - * SOD - SCOPE OF DECIMALS - * SOD MEANS TD = //f - * VALUES FROM "000" TO "999" - * fff = "989" MEANS 989 AND OVER - * - */ - public static final String TD_SOP_LOWER_LIMIT = "000"; - public static final String TD_SOP_UPPER_LIMIT = "989"; - public static final String TD_TRACE = "990"; - public static final String TD_SOD_LOWER_LIMIT = "991"; - public static final String TD_SOD_UPPER_LIMIT = "999"; -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.synopanalyser.internal.synop; + +/** + * The {@link Constants} class defines common constants, which are + * used across the whole package. + * + * @author Jonarzz - Initial contribution + */ +public class Constants { + + public static final int INITIAL_VALUE = -1000; + public static final String UNKNOWN_VALUE = "/"; + + public static final String CHAPTER_3_CODE = "333"; + public static final String CHAPTER_4_CODE = "444"; + public static final String CHAPTER_5_CODE = "555"; + + public static final char PLUS_SIGN_TEMPERATURE = '0'; + public static final char MINUS_SIGN_TEMPERATURE = '1'; + + public static final String LAND_STATION_CODE = "AAXX"; + public static final String SHIP_STATION_CODE = "BBXX"; + public static final String MOBILE_LAND_STATION_CODE = "OOXX"; + + /* + * WS - WIND SPEED + */ + public static final int WS_WILDTYPE_IN_MPS = 0; + public static final int WS_ANEMOMETER_IN_MPS = 1; + public static final int WS_WILDTYPE_IN_KNOT = 3; + public static final int WS_ANEMOMETER_IN_KNOT = 4; + + public static final String WS_MPS = "m/s"; + public static final String WS_KNOTS = "knots"; + + /* + * DFG - DOWNFALL GROUP VALUES FROM '0' TO '4' + */ + public static final char DFG_IN_CHAPTER_1_AND_3 = '0'; + public static final char DFG_IN_CHAPTER_1 = '1'; + public static final char DFG_IN_CHAPTER_3 = '2'; + public static final char DFG_NO_DF = '3'; + public static final char DFG_NO_MEASUREMENT = '4'; + + /* + * ST - STATION TYPE + * A - AUTOMATIC + * N - NON-AUTOMATIC + * VALUES FROM '1' TO '6' + */ + public static final char ST_N_GROUP_7_ON = '1'; + public static final char ST_N_GROUP_7_OFF_NO_PHENOMENON = '2'; + public static final char ST_N_GROUP_7_OFF_NO_DATA = '3'; + public static final char ST_A_GROUP_7_ON = '4'; + public static final char ST_A_GROUP_7_OFF_NO_PHENOMENON = '5'; + public static final char ST_A_GROUP_7_OFF_NO_DATA = '6'; + + /* + * CH - CLOUD HEIGH [IN METERS] + * VALUES FROM '0' TO '9' + * '/' ACCEPTABLE + */ + public static final char CH_0_50 = '0'; + public static final char CH_50_100 = '1'; + public static final char CH_100_200 = '2'; + public static final char CH_200_300 = '3'; + public static final char CH_300_600 = '4'; + public static final char CH_600_1000 = '5'; + public static final char CH_1000_1500 = '6'; + public static final char CH_1500_2000 = '7'; + public static final char CH_2000_2500 = '8'; + public static final char CH_OVER_2500 = '9'; + + /* + * HV - HORIZONTAL VISIBILITY [IN KILOMETERS] + * VALUES FROM "00" TO "50" AND FROM "56" TO "99" + * 00 MEANS HV = BELOW 0,1 + * DECIMAL SCOPE MEANS HV = XX / 10 + * UNIT SCOPE MEANS HV = XX - 50 + * 89 MEANS HV = OVER 70 + * 90-99 ROUGHLY NUMBERING : + * 90 - < 0,05 km + * 91 >= 0,05 < 0,2 km + * 92 >= 0,2 < 0,5 km + * 93 >= 0,5 < 1,0 km + * 94 >= 1,0 < 2,0 km + * 95 >= 2,0 < 4,0 km + * 96 >= 4,0 < 10,0 km + * 97 >= 10,0 < 20,0 km + * 98 >= 20,0 < 50,0 km + * 99 - > 50 km + * HP - high precision + */ + public static final int HV_LESS_THAN_1_LIMIT = 10; + public static final int HV_LESS_THAN_10_LIMIT = 60; + public static final int HV_LESS_THAN_50_LIMIT = 84; + public static final int HV_HP_LIMIT = 90; + public static final int HV_LESS_THAN_1_HP_LIMIT = 93; + public static final int HV_LESS_THAN_10_HP_LIMIT = 96; + public static final int HV_LESS_THAN_50_HP_LIMIT = 98; + + public static final String HV_LESS_THAN_1_STRING = "<1"; + public static final String HV_LESS_THAN_10_STRING = "1-10"; + public static final String HV_LESS_THAN_50_STRING = "10-50"; + public static final String HV_MORE_THAN_50_STRING = ">50"; + + /* + * CLOUDINESS = x/8 + * VALUES FROM '0' TO '9' + * '/' ACCEPTABLE + */ + public static final String CLEAR_SKY = "NO CLOUDS"; + public static final String CLOUDY = "CLOUDY"; + public static final String SKY_NOT_VISIBLE = "SKY NOT VISIBLE"; + + /* + * WIND DIRECTION + * WD = FROM { 5 + (yy - 1) * 9 } TO { 5 + yy * 9 } OR: + * VALUES FROM "00" TO "36" AND "99" + * "//" ACCEPTABLE + */ + public static final String WD_NO_WIND = "00"; + public static final String WD_VARIABLE = "99"; + + /* + * PCT - PRESSURE CHANGE TYPE + * VALUES FROM '0' TO '8' + */ + public static final char PCT_INCREASE_LOWER_LIMIT = '0'; + public static final char PCT_INCREASE_UPPER_LIMIT = '3'; + public static final char PCT_NO_CHANGE = '4'; + public static final char PCT_DECREASE_LOWER_LIMIT = '5'; + public static final char PCT_DECREASE_UPPER_LIMIT = '8'; + + /* + * TD - TOTAL DOWNFALL + * SOP - SCOPE OF PROPORTIONALITY + * SOP MEANS TD = fff [IN MILIMETERS] + * SOD - SCOPE OF DECIMALS + * SOD MEANS TD = //f + * VALUES FROM "000" TO "999" + * fff = "989" MEANS 989 AND OVER + * + */ + public static final String TD_SOP_LOWER_LIMIT = "000"; + public static final String TD_SOP_UPPER_LIMIT = "989"; + public static final String TD_TRACE = "990"; + public static final String TD_SOD_LOWER_LIMIT = "991"; + public static final String TD_SOD_UPPER_LIMIT = "999"; +} diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/Synop.java b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/Synop.java index 68f97c43bf3ca..1a1c173dc9009 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/Synop.java +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/Synop.java @@ -1,366 +1,366 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.synopanalyser.internal.synop; - -import java.util.List; - -/** - * The {@link Synop} is the ancestor common class for analyzing - * Synop messages - * - * @author Jonarzz - Initial contribution - */ -public abstract class Synop { - - private final int VALID_STRING_LENGTH = 5; - - protected final List stringArray; - - private String stationType; - protected String stationCode; - - private int year; - private int month; - private int day; - private int hour; - private int windIndicator; - - private String horizontalVisibility; - private float temperature; - - private String overcast; - private int octa; - private int windDirection; - private int windSpeed; - private float pressure; - - protected int horizontalVisibilityInt; - protected String temperatureString; - protected String windString; - protected String pressureString; - - public Synop(List stringArray) { - this.stringArray = stringArray; - - setStationType(); - setStationCode(); - setDateHourAndWindIndicator(); - setHorizontalVisibility(); - setTemperature(); - setWindAndOvercast(); - setPressure(); - } - - protected void setStationType() { - if (!stringArray.isEmpty()) { - if (stringArray.get(0).length() == 4) { - stationType = stringArray.get(0); - } else { - stationType = ""; - } - } - } - - protected abstract void setStationCode(); - - protected void setDateHourAndWindIndicator() { - String dayHourAndWindIndicator = ""; - - if (this instanceof SynopLand && stringArray.size() > 1) { - dayHourAndWindIndicator = stringArray.get(1); - } else if (stringArray.size() > 2) { - dayHourAndWindIndicator = stringArray.get(2); - } - - if (!isValidString(dayHourAndWindIndicator)) { - return; - } - - setHourOfObservation(dayHourAndWindIndicator); - setWindIndicator(dayHourAndWindIndicator); - } - - private void setHourOfObservation(String str) { - try { - hour = Integer.parseInt(str.substring(2, 4)); - } catch (NumberFormatException e) { - hour = Constants.INITIAL_VALUE; - } - try { - day = Integer.parseInt(str.substring(0, 2)); - } catch (NumberFormatException e) { - day = Constants.INITIAL_VALUE; - } - } - - private void setWindIndicator(String str) { - try { - windIndicator = Character.getNumericValue(str.charAt(4)); - } catch (NumberFormatException e) { - windIndicator = Constants.INITIAL_VALUE; - } - } - - private void setHorizontalVisibility() { - setHorizontalVisibilityInt(); - - if (horizontalVisibilityInt == Constants.INITIAL_VALUE) { - return; - } - - if (horizontalVisibilityInt < Constants.HV_LESS_THAN_1_LIMIT - || horizontalVisibilityInt < Constants.HV_LESS_THAN_1_HP_LIMIT) { - horizontalVisibility = Constants.HV_LESS_THAN_1_STRING; - } else if (horizontalVisibilityInt < Constants.HV_LESS_THAN_10_LIMIT - || horizontalVisibilityInt < Constants.HV_LESS_THAN_10_HP_LIMIT) { - horizontalVisibility = Constants.HV_LESS_THAN_10_STRING; - } else if (horizontalVisibilityInt < Constants.HV_LESS_THAN_50_LIMIT - || horizontalVisibilityInt < Constants.HV_LESS_THAN_50_HP_LIMIT) { - horizontalVisibility = Constants.HV_LESS_THAN_50_STRING; - } else { - horizontalVisibility = Constants.HV_MORE_THAN_50_STRING; - } - } - - protected abstract void setHorizontalVisibilityInt(); - - private void setTemperature() { - setTemperatureString(); - - if (temperatureString == null) { - temperature = Constants.INITIAL_VALUE; - return; - } - - if (temperatureString.charAt(0) == Constants.PLUS_SIGN_TEMPERATURE) { - temperature = 1; - } else if (temperatureString.charAt(0) == Constants.MINUS_SIGN_TEMPERATURE) { - temperature = -1; - } else { - temperature = Constants.INITIAL_VALUE; - return; - } - - try { - float temp = Float.parseFloat(temperatureString.substring(1, 4)) / 10; - temperature *= temp; - } catch (NumberFormatException e) { - temperature = Constants.INITIAL_VALUE; - } - } - - protected abstract void setTemperatureString(); - - private void setWindAndOvercast() { - setWindString(); - - if (windString == null) { - overcast = null; - windDirection = Constants.INITIAL_VALUE; - windSpeed = Constants.INITIAL_VALUE; - return; - } - - if (windString.substring(0, 2).equals("00")) { - setWindSpeed(true); - } else { - setOvercast(); - setWindDirection(); - setWindSpeed(false); - } - } - - private void setOvercast() { - octa = Character.getNumericValue(windString.charAt(0)); - - if (octa < 0 || octa > 9) { - return; - } - - if (octa == 0) { - overcast = Constants.CLEAR_SKY; - } else if (octa > 0 && octa < 8) { - overcast = Constants.CLOUDY; - } else { - overcast = Constants.SKY_NOT_VISIBLE; - } - } - - private void setWindDirection() { - String windDirectionString = windString.substring(1, 3); - - if (windDirectionString.equals("99") || windDirectionString.equals("||")) { - windDirection = Constants.INITIAL_VALUE; - return; - } - - try { - windDirection = Integer.parseInt(windDirectionString) * 10; - } catch (NumberFormatException e) { - windDirection = Constants.INITIAL_VALUE; - } - } - - private void setWindSpeed(boolean gustyWind) { - String speedString = null; - - if (gustyWind) { - speedString = windString.substring(2, 5); - } else { - speedString = windString.substring(3, 5); - } - - try { - windSpeed = Integer.parseInt(speedString); - } catch (NumberFormatException e) { - windSpeed = Constants.INITIAL_VALUE; - } - } - - protected abstract void setWindString(); - - private void setPressure() { - setPressureString(); - - if (pressureString == null) { - return; - } - - String pressureTemp = pressureString.substring(1, 5); - - if (pressureTemp.charAt(0) == '0') { - pressureTemp = '1' + pressureTemp; - } - - try { - pressure = (float) Integer.parseInt(pressureTemp) / 10; - } catch (NumberFormatException e) { - pressure = Constants.INITIAL_VALUE; - } - } - - protected abstract void setPressureString(); - - protected boolean isValidString(String str) { - return (str.length() == VALID_STRING_LENGTH); - } - - public String getStationType() { - return stationType; - } - - public String getStationCode() { - return stationCode; - } - - public int getYear() { - return year; - } - - public int getMonth() { - return month; - } - - public int getDay() { - return day; - } - - public int getHour() { - return hour; - } - - public int getWindIndicator() { - return windIndicator; - } - - public String getHorizontalVisibility() { - return horizontalVisibility; - } - - public float getTemperature() { - return temperature; - } - - public String getOvercast() { - return overcast; - } - - public int getWindDirection() { - return windDirection; - } - - public int getWindSpeed() { - return windSpeed; - } - - public float getPressure() { - return pressure; - } - - public int getOcta() { - return octa; - } - - public String getWindUnit() { - if (getWindIndicator() == Constants.WS_WILDTYPE_IN_MPS - || getWindIndicator() == Constants.WS_ANEMOMETER_IN_MPS) { - return Constants.WS_MPS; - } else { - return Constants.WS_KNOTS; - } - } - - public String getWindSource() { - if (getWindIndicator() == Constants.WS_WILDTYPE_IN_MPS || getWindIndicator() == Constants.WS_WILDTYPE_IN_KNOT) { - return "estimated"; - } else { - return "anemometer"; - } - } - - /** - * display synop data in a human-readable format - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder("station type : " + this.getStationType()); - sb.append("\nstation code : " + this.getStationCode()); - sb.append("\nobservation timestamp (y/m/d h) : " + this.getYear() + "/" + this.getMonth() + "/" + this.getDay() - + " " + this.getHour() + ":00 UTC"); - - sb.append("\nwind indicator : " + this.getWindIndicator()); - sb.append( - "\nwind speed : " + this.getWindSpeed() + " " + this.getWindUnit() + " (" + this.getWindSource() + ")"); - sb.append("\nwind dir : " + getWindDirection() + " degrees"); - - sb.append("\novercast : " + this.getOvercast()); - sb.append("\novercast in Octa : " + this.getOcta() + "/8"); - - sb.append("\nhorizontal visibility : " + this.getHorizontalVisibility()); - sb.append("\ntemperature : " + this.getTemperature()); - - sb.append("\npressure : " + getPressure() + " in hPa"); - - return sb.toString(); - } - - /** - * Retrieve the full report string value. This is the report in its original - * form - * - * @return The original report string. - */ - public String getReportString() { - return String.join(" ", stringArray); - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.synopanalyser.internal.synop; + +import java.util.List; + +/** + * The {@link Synop} is the ancestor common class for analyzing + * Synop messages + * + * @author Jonarzz - Initial contribution + */ +public abstract class Synop { + + private final int VALID_STRING_LENGTH = 5; + + protected final List stringArray; + + private String stationType; + protected String stationCode; + + private int year; + private int month; + private int day; + private int hour; + private int windIndicator; + + private String horizontalVisibility; + private float temperature; + + private String overcast; + private int octa; + private int windDirection; + private int windSpeed; + private float pressure; + + protected int horizontalVisibilityInt; + protected String temperatureString; + protected String windString; + protected String pressureString; + + public Synop(List stringArray) { + this.stringArray = stringArray; + + setStationType(); + setStationCode(); + setDateHourAndWindIndicator(); + setHorizontalVisibility(); + setTemperature(); + setWindAndOvercast(); + setPressure(); + } + + protected void setStationType() { + if (!stringArray.isEmpty()) { + if (stringArray.get(0).length() == 4) { + stationType = stringArray.get(0); + } else { + stationType = ""; + } + } + } + + protected abstract void setStationCode(); + + protected void setDateHourAndWindIndicator() { + String dayHourAndWindIndicator = ""; + + if (this instanceof SynopLand && stringArray.size() > 1) { + dayHourAndWindIndicator = stringArray.get(1); + } else if (stringArray.size() > 2) { + dayHourAndWindIndicator = stringArray.get(2); + } + + if (!isValidString(dayHourAndWindIndicator)) { + return; + } + + setHourOfObservation(dayHourAndWindIndicator); + setWindIndicator(dayHourAndWindIndicator); + } + + private void setHourOfObservation(String str) { + try { + hour = Integer.parseInt(str.substring(2, 4)); + } catch (NumberFormatException e) { + hour = Constants.INITIAL_VALUE; + } + try { + day = Integer.parseInt(str.substring(0, 2)); + } catch (NumberFormatException e) { + day = Constants.INITIAL_VALUE; + } + } + + private void setWindIndicator(String str) { + try { + windIndicator = Character.getNumericValue(str.charAt(4)); + } catch (NumberFormatException e) { + windIndicator = Constants.INITIAL_VALUE; + } + } + + private void setHorizontalVisibility() { + setHorizontalVisibilityInt(); + + if (horizontalVisibilityInt == Constants.INITIAL_VALUE) { + return; + } + + if (horizontalVisibilityInt < Constants.HV_LESS_THAN_1_LIMIT + || horizontalVisibilityInt < Constants.HV_LESS_THAN_1_HP_LIMIT) { + horizontalVisibility = Constants.HV_LESS_THAN_1_STRING; + } else if (horizontalVisibilityInt < Constants.HV_LESS_THAN_10_LIMIT + || horizontalVisibilityInt < Constants.HV_LESS_THAN_10_HP_LIMIT) { + horizontalVisibility = Constants.HV_LESS_THAN_10_STRING; + } else if (horizontalVisibilityInt < Constants.HV_LESS_THAN_50_LIMIT + || horizontalVisibilityInt < Constants.HV_LESS_THAN_50_HP_LIMIT) { + horizontalVisibility = Constants.HV_LESS_THAN_50_STRING; + } else { + horizontalVisibility = Constants.HV_MORE_THAN_50_STRING; + } + } + + protected abstract void setHorizontalVisibilityInt(); + + private void setTemperature() { + setTemperatureString(); + + if (temperatureString == null) { + temperature = Constants.INITIAL_VALUE; + return; + } + + if (temperatureString.charAt(0) == Constants.PLUS_SIGN_TEMPERATURE) { + temperature = 1; + } else if (temperatureString.charAt(0) == Constants.MINUS_SIGN_TEMPERATURE) { + temperature = -1; + } else { + temperature = Constants.INITIAL_VALUE; + return; + } + + try { + float temp = Float.parseFloat(temperatureString.substring(1, 4)) / 10; + temperature *= temp; + } catch (NumberFormatException e) { + temperature = Constants.INITIAL_VALUE; + } + } + + protected abstract void setTemperatureString(); + + private void setWindAndOvercast() { + setWindString(); + + if (windString == null) { + overcast = null; + windDirection = Constants.INITIAL_VALUE; + windSpeed = Constants.INITIAL_VALUE; + return; + } + + if (windString.substring(0, 2).equals("00")) { + setWindSpeed(true); + } else { + setOvercast(); + setWindDirection(); + setWindSpeed(false); + } + } + + private void setOvercast() { + octa = Character.getNumericValue(windString.charAt(0)); + + if (octa < 0 || octa > 9) { + return; + } + + if (octa == 0) { + overcast = Constants.CLEAR_SKY; + } else if (octa > 0 && octa < 8) { + overcast = Constants.CLOUDY; + } else { + overcast = Constants.SKY_NOT_VISIBLE; + } + } + + private void setWindDirection() { + String windDirectionString = windString.substring(1, 3); + + if (windDirectionString.equals("99") || windDirectionString.equals("||")) { + windDirection = Constants.INITIAL_VALUE; + return; + } + + try { + windDirection = Integer.parseInt(windDirectionString) * 10; + } catch (NumberFormatException e) { + windDirection = Constants.INITIAL_VALUE; + } + } + + private void setWindSpeed(boolean gustyWind) { + String speedString = null; + + if (gustyWind) { + speedString = windString.substring(2, 5); + } else { + speedString = windString.substring(3, 5); + } + + try { + windSpeed = Integer.parseInt(speedString); + } catch (NumberFormatException e) { + windSpeed = Constants.INITIAL_VALUE; + } + } + + protected abstract void setWindString(); + + private void setPressure() { + setPressureString(); + + if (pressureString == null) { + return; + } + + String pressureTemp = pressureString.substring(1, 5); + + if (pressureTemp.charAt(0) == '0') { + pressureTemp = '1' + pressureTemp; + } + + try { + pressure = (float) Integer.parseInt(pressureTemp) / 10; + } catch (NumberFormatException e) { + pressure = Constants.INITIAL_VALUE; + } + } + + protected abstract void setPressureString(); + + protected boolean isValidString(String str) { + return (str.length() == VALID_STRING_LENGTH); + } + + public String getStationType() { + return stationType; + } + + public String getStationCode() { + return stationCode; + } + + public int getYear() { + return year; + } + + public int getMonth() { + return month; + } + + public int getDay() { + return day; + } + + public int getHour() { + return hour; + } + + public int getWindIndicator() { + return windIndicator; + } + + public String getHorizontalVisibility() { + return horizontalVisibility; + } + + public float getTemperature() { + return temperature; + } + + public String getOvercast() { + return overcast; + } + + public int getWindDirection() { + return windDirection; + } + + public int getWindSpeed() { + return windSpeed; + } + + public float getPressure() { + return pressure; + } + + public int getOcta() { + return octa; + } + + public String getWindUnit() { + if (getWindIndicator() == Constants.WS_WILDTYPE_IN_MPS + || getWindIndicator() == Constants.WS_ANEMOMETER_IN_MPS) { + return Constants.WS_MPS; + } else { + return Constants.WS_KNOTS; + } + } + + public String getWindSource() { + if (getWindIndicator() == Constants.WS_WILDTYPE_IN_MPS || getWindIndicator() == Constants.WS_WILDTYPE_IN_KNOT) { + return "estimated"; + } else { + return "anemometer"; + } + } + + /** + * display synop data in a human-readable format + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder("station type : " + this.getStationType()); + sb.append("\nstation code : " + this.getStationCode()); + sb.append("\nobservation timestamp (y/m/d h) : " + this.getYear() + "/" + this.getMonth() + "/" + this.getDay() + + " " + this.getHour() + ":00 UTC"); + + sb.append("\nwind indicator : " + this.getWindIndicator()); + sb.append( + "\nwind speed : " + this.getWindSpeed() + " " + this.getWindUnit() + " (" + this.getWindSource() + ")"); + sb.append("\nwind dir : " + getWindDirection() + " degrees"); + + sb.append("\novercast : " + this.getOvercast()); + sb.append("\novercast in Octa : " + this.getOcta() + "/8"); + + sb.append("\nhorizontal visibility : " + this.getHorizontalVisibility()); + sb.append("\ntemperature : " + this.getTemperature()); + + sb.append("\npressure : " + getPressure() + " in hPa"); + + return sb.toString(); + } + + /** + * Retrieve the full report string value. This is the report in its original + * form + * + * @return The original report string. + */ + public String getReportString() { + return String.join(" ", stringArray); + } +} diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopLand.java b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopLand.java index c36b700ef7ecf..8d255d54b7c63 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopLand.java +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopLand.java @@ -1,130 +1,130 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.synopanalyser.internal.synop; - -import java.util.List; - -/** - * The {@link SynopLand} is responsible for analyzing Land station - * specifics Synop messages - * - * @author Jonarzz - Initial contribution - */ -public class SynopLand extends Synop { - - private String temp; - - private int rainfall; - private String rainfallString; - - public SynopLand(List stringArray) { - super(stringArray); - - setRainfall(); - } - - @Override - protected void setStationCode() { - if (stringArray.size() < 3 || (temp = stringArray.get(2)).length() > 10 || temp.contains("/")) { - return; - } - - stationCode = temp; - } - - @Override - protected void setHorizontalVisibilityInt() { - if (stringArray.size() < 4 || !isValidString((temp = stringArray.get(3)))) { - horizontalVisibilityInt = Constants.INITIAL_VALUE; - return; - } - - try { - horizontalVisibilityInt = Integer.parseInt(temp.substring(3, 5)); - } catch (NumberFormatException e) { - horizontalVisibilityInt = Constants.INITIAL_VALUE; - } - } - - @Override - protected void setTemperatureString() { - if (stringArray.size() < 6 || !isValidString(stringArray.get(5))) { - return; - } - - if (stringArray.get(5).charAt(0) == '0') { - if (stringArray.size() < 7 || !isValidString(stringArray.get(6))) { - return; - } - - temperatureString = stringArray.get(6).substring(1, 5); - } else if (isValidString(stringArray.get(5))) { - temperatureString = stringArray.get(5).substring(1, 5); - } - } - - @Override - protected void setWindString() { - if (stringArray.size() < 5 || !isValidString((temp = stringArray.get(4)))) { - return; - } - - windString = temp; - } - - @Override - protected void setPressureString() { - if (stringArray.size() < 8 || stringArray.get(7).charAt(0) != '3' - || !isValidString((temp = stringArray.get(7)))) { - return; - } - - pressureString = temp; - } - - private void setRainfall() { - setRainfallString(); - - if (rainfallString == null) { - rainfall = Constants.INITIAL_VALUE; - return; - } - - try { - rainfall = Integer.parseInt(rainfallString.substring(1, 4)); - if (rainfall >= 990) { - rainfall = 0; - } - } catch (NumberFormatException e) { - rainfall = Constants.INITIAL_VALUE; - } - } - - protected void setRainfallString() { - if (stringArray.size() < 11 || stringArray.get(10).charAt(0) != '6' - || !isValidString((temp = stringArray.get(10)))) { - return; - } - - rainfallString = temp; - } - - @Override - public String getStationCode() { - return stationCode; - } - - public int getRainfall() { - return rainfall; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.synopanalyser.internal.synop; + +import java.util.List; + +/** + * The {@link SynopLand} is responsible for analyzing Land station + * specifics Synop messages + * + * @author Jonarzz - Initial contribution + */ +public class SynopLand extends Synop { + + private String temp; + + private int rainfall; + private String rainfallString; + + public SynopLand(List stringArray) { + super(stringArray); + + setRainfall(); + } + + @Override + protected void setStationCode() { + if (stringArray.size() < 3 || (temp = stringArray.get(2)).length() > 10 || temp.contains("/")) { + return; + } + + stationCode = temp; + } + + @Override + protected void setHorizontalVisibilityInt() { + if (stringArray.size() < 4 || !isValidString((temp = stringArray.get(3)))) { + horizontalVisibilityInt = Constants.INITIAL_VALUE; + return; + } + + try { + horizontalVisibilityInt = Integer.parseInt(temp.substring(3, 5)); + } catch (NumberFormatException e) { + horizontalVisibilityInt = Constants.INITIAL_VALUE; + } + } + + @Override + protected void setTemperatureString() { + if (stringArray.size() < 6 || !isValidString(stringArray.get(5))) { + return; + } + + if (stringArray.get(5).charAt(0) == '0') { + if (stringArray.size() < 7 || !isValidString(stringArray.get(6))) { + return; + } + + temperatureString = stringArray.get(6).substring(1, 5); + } else if (isValidString(stringArray.get(5))) { + temperatureString = stringArray.get(5).substring(1, 5); + } + } + + @Override + protected void setWindString() { + if (stringArray.size() < 5 || !isValidString((temp = stringArray.get(4)))) { + return; + } + + windString = temp; + } + + @Override + protected void setPressureString() { + if (stringArray.size() < 8 || stringArray.get(7).charAt(0) != '3' + || !isValidString((temp = stringArray.get(7)))) { + return; + } + + pressureString = temp; + } + + private void setRainfall() { + setRainfallString(); + + if (rainfallString == null) { + rainfall = Constants.INITIAL_VALUE; + return; + } + + try { + rainfall = Integer.parseInt(rainfallString.substring(1, 4)); + if (rainfall >= 990) { + rainfall = 0; + } + } catch (NumberFormatException e) { + rainfall = Constants.INITIAL_VALUE; + } + } + + protected void setRainfallString() { + if (stringArray.size() < 11 || stringArray.get(10).charAt(0) != '6' + || !isValidString((temp = stringArray.get(10)))) { + return; + } + + rainfallString = temp; + } + + @Override + public String getStationCode() { + return stationCode; + } + + public int getRainfall() { + return rainfall; + } +} diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopMobile.java b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopMobile.java index 726192b854740..ac4b69e284d75 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopMobile.java +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopMobile.java @@ -1,164 +1,164 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.synopanalyser.internal.synop; - -import java.util.List; - -/** - * The {@link SynopMobile} is responsible for analyzing Mobile station - * specifics Synop messages - * - * @author Jonarzz - Initial contribution - */ -public abstract class SynopMobile extends Synop { - - private String temp; - - private float latitude; - private float longitude; - - private int verticalQuadrantMultiplier; - private int horizontalQuadrantMultiplier; - - public SynopMobile(List stringArray) { - super(stringArray); - - setLatitude(); - setLongitudeAndQuadrant(); - } - - @Override - protected void setStationCode() { - if (stringArray.size() < 2 || (temp = stringArray.get(1)).length() > 10 || temp.contains("/")) { - return; - } - - stationCode = temp; - } - - @Override - protected void setHorizontalVisibilityInt() { - if (stringArray.size() < 6 || !isValidString((temp = stringArray.get(5)))) { - horizontalVisibilityInt = Constants.INITIAL_VALUE; - return; - } - - try { - horizontalVisibilityInt = Integer.parseInt(temp.substring(3, 5)); - } catch (NumberFormatException e) { - horizontalVisibilityInt = Constants.INITIAL_VALUE; - } - } - - @Override - protected void setTemperatureString() { - if (stringArray.size() < 8 || !isValidString((temp = stringArray.get(7)))) { - return; - } - - temperatureString = temp.substring(1, 5); - } - - @Override - protected void setWindString() { - if (stringArray.size() < 7 || !isValidString((temp = stringArray.get(6)))) { - return; - } - - windString = temp; - } - - @Override - protected abstract void setPressureString(); - - protected void setLatitude() { - if (stringArray.size() < 4 || !isValidString((temp = stringArray.get(3)))) { - return; - } - - String latitudeString = temp.substring(2, 5); - int tempInt = 0; - - try { - tempInt = Integer.parseInt(latitudeString); - } catch (NumberFormatException e) { - latitude = Constants.INITIAL_VALUE; - return; - } - - latitude = (float) tempInt / 10; - } - - protected void setLongitudeAndQuadrant() { - if (stringArray.size() < 5 || !isValidString((temp = stringArray.get(4)))) { - return; - } - - setQuadrantMultipliers(temp.charAt(0)); - setLongitude(temp.substring(1, 5)); - } - - protected void setQuadrantMultipliers(char q) { - switch (q) { - case '1': - verticalQuadrantMultiplier = 1; - horizontalQuadrantMultiplier = 1; - break; - case '3': - verticalQuadrantMultiplier = -1; - horizontalQuadrantMultiplier = 1; - break; - case '5': - verticalQuadrantMultiplier = -1; - horizontalQuadrantMultiplier = -1; - break; - case '7': - verticalQuadrantMultiplier = 1; - horizontalQuadrantMultiplier = -1; - break; - default: - verticalQuadrantMultiplier = 0; - horizontalQuadrantMultiplier = 0; - break; - } - } - - protected void setLongitude(String str) { - int tempInt = 0; - - try { - tempInt = Integer.parseInt(str); - } catch (NumberFormatException e) { - longitude = Constants.INITIAL_VALUE; - return; - } - - longitude = (float) tempInt / 10; - } - - public float getLatitude() { - return latitude; - } - - public float getLongitude() { - return longitude; - } - - public int getVerticalQuadrantMultiplier() { - return verticalQuadrantMultiplier; - } - - public int getHorizontalQuadrantMultiplier() { - return horizontalQuadrantMultiplier; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.synopanalyser.internal.synop; + +import java.util.List; + +/** + * The {@link SynopMobile} is responsible for analyzing Mobile station + * specifics Synop messages + * + * @author Jonarzz - Initial contribution + */ +public abstract class SynopMobile extends Synop { + + private String temp; + + private float latitude; + private float longitude; + + private int verticalQuadrantMultiplier; + private int horizontalQuadrantMultiplier; + + public SynopMobile(List stringArray) { + super(stringArray); + + setLatitude(); + setLongitudeAndQuadrant(); + } + + @Override + protected void setStationCode() { + if (stringArray.size() < 2 || (temp = stringArray.get(1)).length() > 10 || temp.contains("/")) { + return; + } + + stationCode = temp; + } + + @Override + protected void setHorizontalVisibilityInt() { + if (stringArray.size() < 6 || !isValidString((temp = stringArray.get(5)))) { + horizontalVisibilityInt = Constants.INITIAL_VALUE; + return; + } + + try { + horizontalVisibilityInt = Integer.parseInt(temp.substring(3, 5)); + } catch (NumberFormatException e) { + horizontalVisibilityInt = Constants.INITIAL_VALUE; + } + } + + @Override + protected void setTemperatureString() { + if (stringArray.size() < 8 || !isValidString((temp = stringArray.get(7)))) { + return; + } + + temperatureString = temp.substring(1, 5); + } + + @Override + protected void setWindString() { + if (stringArray.size() < 7 || !isValidString((temp = stringArray.get(6)))) { + return; + } + + windString = temp; + } + + @Override + protected abstract void setPressureString(); + + protected void setLatitude() { + if (stringArray.size() < 4 || !isValidString((temp = stringArray.get(3)))) { + return; + } + + String latitudeString = temp.substring(2, 5); + int tempInt = 0; + + try { + tempInt = Integer.parseInt(latitudeString); + } catch (NumberFormatException e) { + latitude = Constants.INITIAL_VALUE; + return; + } + + latitude = (float) tempInt / 10; + } + + protected void setLongitudeAndQuadrant() { + if (stringArray.size() < 5 || !isValidString((temp = stringArray.get(4)))) { + return; + } + + setQuadrantMultipliers(temp.charAt(0)); + setLongitude(temp.substring(1, 5)); + } + + protected void setQuadrantMultipliers(char q) { + switch (q) { + case '1': + verticalQuadrantMultiplier = 1; + horizontalQuadrantMultiplier = 1; + break; + case '3': + verticalQuadrantMultiplier = -1; + horizontalQuadrantMultiplier = 1; + break; + case '5': + verticalQuadrantMultiplier = -1; + horizontalQuadrantMultiplier = -1; + break; + case '7': + verticalQuadrantMultiplier = 1; + horizontalQuadrantMultiplier = -1; + break; + default: + verticalQuadrantMultiplier = 0; + horizontalQuadrantMultiplier = 0; + break; + } + } + + protected void setLongitude(String str) { + int tempInt = 0; + + try { + tempInt = Integer.parseInt(str); + } catch (NumberFormatException e) { + longitude = Constants.INITIAL_VALUE; + return; + } + + longitude = (float) tempInt / 10; + } + + public float getLatitude() { + return latitude; + } + + public float getLongitude() { + return longitude; + } + + public int getVerticalQuadrantMultiplier() { + return verticalQuadrantMultiplier; + } + + public int getHorizontalQuadrantMultiplier() { + return horizontalQuadrantMultiplier; + } +} diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopMobileLand.java b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopMobileLand.java index a2444a436d02c..21583f2ef08c7 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopMobileLand.java +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopMobileLand.java @@ -1,33 +1,33 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.synopanalyser.internal.synop; - -import java.util.List; - -/** - * The {@link SynopMobileLand} is responsible for analyzing Mobile Land - * station specifics Synop messages - * - * @author Jonarzz - Initial contribution - */ -public class SynopMobileLand extends SynopMobile { - - public SynopMobileLand(List stringArray) { - super(stringArray); - } - - @Override - protected void setPressureString() { - return; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.synopanalyser.internal.synop; + +import java.util.List; + +/** + * The {@link SynopMobileLand} is responsible for analyzing Mobile Land + * station specifics Synop messages + * + * @author Jonarzz - Initial contribution + */ +public class SynopMobileLand extends SynopMobile { + + public SynopMobileLand(List stringArray) { + super(stringArray); + } + + @Override + protected void setPressureString() { + return; + } +} diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopShip.java b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopShip.java index 55798c57aafc1..7e16b618df724 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopShip.java +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyser/internal/synop/SynopShip.java @@ -1,39 +1,39 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.synopanalyser.internal.synop; - -import java.util.List; - -/** - * The {@link SynopMobile} is responsible for analyzing Mobile station - * specifics Synop messages - * - * @author Jonarzz - Initial contribution - */ -public class SynopShip extends SynopMobile { - - public SynopShip(List stringArray) { - super(stringArray); - } - - @Override - protected void setPressureString() { - String temp; - if (stringArray.size() < 10 || !isValidString((temp = stringArray.get(9))) || temp.charAt(0) != '4' - || temp.charAt(1) != '0' || temp.charAt(1) != '9') { - return; - } - - pressureString = temp; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.synopanalyser.internal.synop; + +import java.util.List; + +/** + * The {@link SynopMobile} is responsible for analyzing Mobile station + * specifics Synop messages + * + * @author Jonarzz - Initial contribution + */ +public class SynopShip extends SynopMobile { + + public SynopShip(List stringArray) { + super(stringArray); + } + + @Override + protected void setPressureString() { + String temp; + if (stringArray.size() < 10 || !isValidString((temp = stringArray.get(9))) || temp.charAt(0) != '4' + || temp.charAt(1) != '0' || temp.charAt(1) != '9') { + return; + } + + pressureString = temp; + } +} diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyzer/internal/handler/SynopAnalyzerHandler.java b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyzer/internal/handler/SynopAnalyzerHandler.java index 0b53fffe0c964..cf2a3bf234382 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyzer/internal/handler/SynopAnalyzerHandler.java +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/java/org/openhab/binding/synopanalyzer/internal/handler/SynopAnalyzerHandler.java @@ -229,5 +229,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { updateSynopChannels(); } } - } diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.synopanalyzer/src/main/resources/ESH-INF/binding/binding.xml index cce3bbb004916..cc03e590db49b 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Synop Analyzer Binding This is the binding to download and interpret Synop messages diff --git a/bundles/org.openhab.binding.synopanalyzer/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.synopanalyzer/src/main/resources/ESH-INF/thing/thing-types.xml index 461525fe6c6e1..a361e9b27c70b 100644 --- a/bundles/org.openhab.binding.synopanalyzer/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.synopanalyzer/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,25 +1,25 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> The Synop Analyzer binding decodes Synop messages - - - - - - - - - - - + + + + + + + + + + + @@ -42,7 +42,7 @@ Wind speed in Beaufort Scale Wind - + diff --git a/bundles/org.openhab.binding.systeminfo/pom.xml b/bundles/org.openhab.binding.systeminfo/pom.xml index e4086477cb14b..2f27f2b6c47a7 100644 --- a/bundles/org.openhab.binding.systeminfo/pom.xml +++ b/bundles/org.openhab.binding.systeminfo/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.systeminfo diff --git a/bundles/org.openhab.binding.systeminfo/src/main/feature/feature.xml b/bundles/org.openhab.binding.systeminfo/src/main/feature/feature.xml index a5b1a395730ff..6b8275687f5fc 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.systeminfo/src/main/feature/feature.xml @@ -1,12 +1,12 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:net.java.dev.jna/jna/5.5.0 - mvn:net.java.dev.jna/jna-platform/5.5.0 - mvn:com.github.oshi/oshi-core/4.5.2 - mvn:org.openhab.addons.bundles/org.openhab.binding.systeminfo/${project.version} - + + openhab-runtime-base + mvn:net.java.dev.jna/jna/5.5.0 + mvn:net.java.dev.jna/jna-platform/5.5.0 + mvn:com.github.oshi/oshi-core/4.5.2 + mvn:org.openhab.addons.bundles/org.openhab.binding.systeminfo/${project.version} + diff --git a/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/SysteminfoBindingConstants.java b/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/SysteminfoBindingConstants.java index ef94b2bc88592..005d274545cbf 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/SysteminfoBindingConstants.java +++ b/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/SysteminfoBindingConstants.java @@ -330,5 +330,4 @@ public class SysteminfoBindingConstants { * */ public static final String PID_PARAM = "pid"; - } diff --git a/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/handler/SysteminfoHandler.java b/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/handler/SysteminfoHandler.java index 73217314feee4..afae9a3d41939 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/handler/SysteminfoHandler.java +++ b/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/handler/SysteminfoHandler.java @@ -234,7 +234,6 @@ private void scheduleUpdates() { scheduler.schedule(() -> { publishData(lowPriorityChannels); }, WAIT_TIME_CHANNEL_ITEM_LINK_INIT, TimeUnit.SECONDS); - } private void publishData(Set channels) { @@ -601,5 +600,4 @@ private void stopScheduledUpdates() { public void dispose() { stopScheduledUpdates(); } - } diff --git a/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java b/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java index ea3eee02dbe86..c24142f64f9d0 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java +++ b/bundles/org.openhab.binding.systeminfo/src/main/java/org/openhab/binding/systeminfo/internal/model/SysteminfoInterface.java @@ -437,5 +437,4 @@ public interface SysteminfoInterface { * @throws DeviceNotFoundException - thrown if process with this PID can not be found */ public @Nullable DecimalType getProcessThreads(int pid) throws DeviceNotFoundException; - } diff --git a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/binding/binding.xml index c90deb5d77b78..630ff0e51046d 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Systeminfo Binding diff --git a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/config/channelConfig.xml b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/config/channelConfig.xml index b270f5b486fe1..3eec01987b4d1 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/config/channelConfig.xml +++ b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/config/channelConfig.xml @@ -1,12 +1,14 @@ - - diff --git a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/config/computerConfig.xml b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/config/computerConfig.xml index 16dff923bb951..9efa478ad93d9 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/config/computerConfig.xml +++ b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/config/computerConfig.xml @@ -1,10 +1,11 @@ - - @@ -20,7 +21,7 @@ 60 - diff --git a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/thing/channels.xml index 555bd961bb040..ec6a44c2bba26 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/thing/channels.xml @@ -1,20 +1,21 @@ - - Physical memory information - - - - - + + + + + @@ -22,11 +23,11 @@ Swap memory information - - - - - + + + + + @@ -34,14 +35,14 @@ Logical storage information - - - - - - - - + + + + + + + + @@ -49,9 +50,9 @@ Drive information - - - + + + @@ -59,14 +60,14 @@ Network parameters - - - - - - - - + + + + + + + + @@ -74,7 +75,7 @@ Display parameters - + @@ -82,9 +83,9 @@ Sensor parameters - - - + + + @@ -92,9 +93,9 @@ Battery parameters - - - + + + @@ -102,13 +103,13 @@ CPU parameters - - - - - - - + + + + + + + @@ -116,11 +117,11 @@ System process information - - - - - + + + + + @@ -128,256 +129,256 @@ String The full path - - + + Number Available size in MB - - + + Number Used size in MB - - + + Number Used size in MB - - + + Number Total size in MB - - + + Number Available size in percent - - + + Number Used size in percent - - + + String Name of the device (process) - - + + String Name of the device (process) - - + + String The model of the device - - + + String The serial number of the device - - + + String Description of the device - - + + String Storage type - - + + Number CPU Temperature in Celsius degrees - - + + Number CPU Voltage in V - - + + Number Fan speed in rpm - - + + Number Remaining time in minutes - - + + Number Remaining capacity in percent - - + + Number Load in percent - - + + Number Load as a number of processes for the last 1,5 or 15 minutes - - + + Number System uptime (time after start) in minutes - - + + Number Number of threads currently running - - + + Number Number of threads currently running - - + + String Product, manufacturer, SN, width and height of the display in cm - - + + String Host IP address of the network - - + + String Mac address of the network - - + + String The name of the network. - - + + String The display name of the network - - + + Number Number of packets sent - - + + Number Number of packets received - - + + Number Data sent in MB - - + + Number Data received in MB - - + + diff --git a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/thing/computer.xml b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/thing/computer.xml index cb94477da88c6..ef680220dc7a4 100644 --- a/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/thing/computer.xml +++ b/bundles/org.openhab.binding.systeminfo/src/main/resources/ESH-INF/thing/computer.xml @@ -1,27 +1,28 @@ - - The computer operating system and hardware information - - - - + + + + - - - - - - + + + + + + @@ -32,7 +33,7 @@ Not available - + diff --git a/bundles/org.openhab.binding.tado/pom.xml b/bundles/org.openhab.binding.tado/pom.xml index 5141a78bac363..7595f12c0829b 100644 --- a/bundles/org.openhab.binding.tado/pom.xml +++ b/bundles/org.openhab.binding.tado/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.tado diff --git a/bundles/org.openhab.binding.tado/src/main/feature/feature.xml b/bundles/org.openhab.binding.tado/src/main/feature/feature.xml index 9a72b91a7c383..c0d0c5df6afba 100644 --- a/bundles/org.openhab.binding.tado/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.tado/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.tado/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.tado/${project.version} + diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/adapter/TadoZoneStateAdapter.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/adapter/TadoZoneStateAdapter.java index 56a1ffab91c86..13e9fb7059215 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/adapter/TadoZoneStateAdapter.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/adapter/TadoZoneStateAdapter.java @@ -24,7 +24,6 @@ import org.eclipse.smarthome.core.library.unit.SIUnits; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; - import org.openhab.binding.tado.internal.TadoBindingConstants.HvacMode; import org.openhab.binding.tado.internal.TadoBindingConstants.OperationMode; import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit; @@ -49,7 +48,7 @@ * * @author Dennis Frommknecht - Initial contribution * @author Andrew Fiddian-Green - Added Low Battery Alarm, A/C Power and Open Window channels - * + * */ public class TadoZoneStateAdapter { private ZoneState zoneState; @@ -235,5 +234,4 @@ public State getOpenWindowDetected() { } return OnOffType.OFF; } - } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/api/TadoApiTypeUtils.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/api/TadoApiTypeUtils.java index 4e4ea0e9c9def..8fc6d549786c1 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/api/TadoApiTypeUtils.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/api/TadoApiTypeUtils.java @@ -169,5 +169,4 @@ public static AcModeCapabilities getModeCapabilities(AirConditioningCapabilities return modeCapabilities != null ? modeCapabilities : new AcModeCapabilities(); } - } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/TerminationConditionBuilder.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/TerminationConditionBuilder.java index 40f13dc374e3f..df600666421aa 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/TerminationConditionBuilder.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/builder/TerminationConditionBuilder.java @@ -57,8 +57,7 @@ public TerminationConditionBuilder withTimerDurationInSeconds(Integer timerDurat return this; } - public OverlayTerminationCondition build(ZoneStateProvider zoneStateProvider) - throws IOException, ApiException { + public OverlayTerminationCondition build(ZoneStateProvider zoneStateProvider) throws IOException, ApiException { OverlayTerminationCondition terminationCondition = null; if (terminationType != null) { diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoBatteryChecker.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoBatteryChecker.java index 24492db360c6c..aa32cb82261d9 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoBatteryChecker.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoBatteryChecker.java @@ -24,7 +24,6 @@ import org.eclipse.smarthome.core.types.UnDefType; import org.openhab.binding.tado.internal.api.ApiException; import org.openhab.binding.tado.internal.api.model.ControlDevice; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -76,5 +75,4 @@ public State getBatteryLowAlarm(long zoneId) { refreshZoneList(); return zoneList.getOrDefault(zoneId, UnDefType.UNDEF); } - } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHandlerFactory.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHandlerFactory.java index 051be2bb1077a..359fdd4fb30b7 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHandlerFactory.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHandlerFactory.java @@ -92,5 +92,4 @@ protected synchronized void removeHandler(ThingHandler thingHandler) { } } } - } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHomeHandler.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHomeHandler.java index ea8bcef9be677..ea166521681f1 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHomeHandler.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoHomeHandler.java @@ -21,10 +21,8 @@ import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; - import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.State; - import org.openhab.binding.tado.internal.TadoBindingConstants; import org.openhab.binding.tado.internal.TadoBindingConstants.TemperatureUnit; import org.openhab.binding.tado.internal.api.ApiException; @@ -33,7 +31,6 @@ import org.openhab.binding.tado.internal.api.model.HomeInfo; import org.openhab.binding.tado.internal.api.model.User; import org.openhab.binding.tado.internal.config.TadoHomeConfig; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -133,9 +130,8 @@ public Long getHomeId() { public void handleCommand(ChannelUID channelUID, Command command) { // Nothing to do for a bridge } - + public State getBatteryLowAlarm(long zoneId) { - return batteryChecker.getBatteryLowAlarm(zoneId); + return batteryChecker.getBatteryLowAlarm(zoneId); } - } diff --git a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoZoneHandler.java b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoZoneHandler.java index 11a11703e0d8c..605b688c82daf 100644 --- a/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoZoneHandler.java +++ b/bundles/org.openhab.binding.tado/src/main/java/org/openhab/binding/tado/internal/handler/TadoZoneHandler.java @@ -235,7 +235,7 @@ private void updateZoneState(boolean forceUpdate) { TadoZoneStateAdapter state = new TadoZoneStateAdapter(zoneState, getTemperatureUnit()); updateStateIfNotNull(TadoBindingConstants.CHANNEL_ZONE_CURRENT_TEMPERATURE, state.getInsideTemperature()); updateStateIfNotNull(TadoBindingConstants.CHANNEL_ZONE_HUMIDITY, state.getHumidity()); - + updateStateIfNotNull(TadoBindingConstants.CHANNEL_ZONE_HEATING_POWER, state.getHeatingPower()); updateStateIfNotNull(TadoBindingConstants.CHANNEL_ZONE_AC_POWER, state.getAcPower()); @@ -257,7 +257,7 @@ private void updateZoneState(boolean forceUpdate) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Could not connect to server due to " + e.getMessage()); } - + TadoHomeHandler home = getHomeHandler(); if (home != null) { updateState(TadoBindingConstants.CHANNEL_ZONE_BATTERY_LOW_ALARM, home.getBatteryLowAlarm(getZoneId())); @@ -307,5 +307,4 @@ private void updateStateIfNotNull(String channelID, State state) { updateState(channelID, state); } } - } diff --git a/bundles/org.openhab.binding.tado/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.tado/src/main/resources/ESH-INF/binding/binding.xml index 57cd17a5de5e9..c46317ab023ac 100644 --- a/bundles/org.openhab.binding.tado/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.tado/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - tado° Binding diff --git a/bundles/org.openhab.binding.tado/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.tado/src/main/resources/ESH-INF/thing/thing-types.xml index 4615a260ffa20..90c6da3120ff0 100644 --- a/bundles/org.openhab.binding.tado/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.tado/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,5 +1,6 @@ - @@ -24,7 +25,7 @@ - + @@ -45,7 +46,7 @@ - + ON if one or more devices in the zone have a low battery @@ -83,7 +84,7 @@ - + @@ -199,7 +200,7 @@ DateTime Time until when the overlay is active. Null if no overlay is set or overlay type is manual. - + @@ -214,7 +215,7 @@ Indicates if the air-conditioning is Off or On - + Switch diff --git a/bundles/org.openhab.binding.tankerkoenig/pom.xml b/bundles/org.openhab.binding.tankerkoenig/pom.xml index 8f671d9af569c..8bfce1aa46680 100644 --- a/bundles/org.openhab.binding.tankerkoenig/pom.xml +++ b/bundles/org.openhab.binding.tankerkoenig/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.tankerkoenig diff --git a/bundles/org.openhab.binding.tankerkoenig/src/main/feature/feature.xml b/bundles/org.openhab.binding.tankerkoenig/src/main/feature/feature.xml index ec5018cae257d..4fe51490d072f 100644 --- a/bundles/org.openhab.binding.tankerkoenig/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.tankerkoenig/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.tankerkoenig/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.tankerkoenig/${project.version} + diff --git a/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/TankerkoenigBindingConstants.java b/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/TankerkoenigBindingConstants.java index 8ae5c917fe8d2..efc0e6256de58 100644 --- a/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/TankerkoenigBindingConstants.java +++ b/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/TankerkoenigBindingConstants.java @@ -51,5 +51,4 @@ public class TankerkoenigBindingConstants { // String used Identify unsucessful web-return public static final String NO_VALID_RESPONSE = "No valid response from the web-request!"; - } diff --git a/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/config/LittleStation.java b/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/config/LittleStation.java index 1a3b0418e3d32..c51ea43a7de3f 100644 --- a/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/config/LittleStation.java +++ b/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/config/LittleStation.java @@ -75,5 +75,4 @@ public Boolean isOpen() { public void setOpen(Boolean isOpen) { this.open = isOpen; } - } diff --git a/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/config/OpeningTimes.java b/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/config/OpeningTimes.java index 575bee9e59d70..dfcea57a70372 100644 --- a/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/config/OpeningTimes.java +++ b/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/config/OpeningTimes.java @@ -64,5 +64,4 @@ public String toString() { } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/handler/WebserviceHandler.java b/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/handler/WebserviceHandler.java index bb52860fcb53e..5023c562233cc 100644 --- a/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/handler/WebserviceHandler.java +++ b/bundles/org.openhab.binding.tankerkoenig/src/main/java/org/openhab/binding/tankerkoenig/internal/handler/WebserviceHandler.java @@ -367,5 +367,4 @@ public void setModeOpeningTime(boolean modeOpeningTime) { public String getUserAgent() { return userAgent; } - } diff --git a/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/binding/binding.xml index c60ca2fc36fcf..236f4c4a57f05 100644 --- a/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/binding/binding.xml @@ -1,9 +1,11 @@ - Tankerkönig Binding - The Tankerkönig Binding allows to poll fuel prices of German gas stations by using the Tankerkoenig.de API. + The Tankerkönig Binding allows to poll fuel prices of German gas stations by using the Tankerkoenig.de + API. Dennis Dollinger / Jürgen Baginski diff --git a/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/thing/station.xml b/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/thing/station.xml index c570dcead8650..10abd89033caf 100644 --- a/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/thing/station.xml +++ b/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/thing/station.xml @@ -5,15 +5,16 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + - Provides the prices of gas types E5-, E10- and Diesel of that station and if that station reports as opened. + Provides the prices of gas types E5-, E10- and Diesel of that station and if that station reports as + opened. - - - - + + + + diff --git a/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/thing/webservice.xml b/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/thing/webservice.xml index 16663200e13d2..12fe9b586fdce 100644 --- a/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/thing/webservice.xml +++ b/bundles/org.openhab.binding.tankerkoenig/src/main/resources/ESH-INF/thing/webservice.xml @@ -7,7 +7,7 @@ The Tankerkönig Webservice can handle 1 to 10 gas stations. - + diff --git a/bundles/org.openhab.binding.telegram/.project b/bundles/org.openhab.binding.telegram/.project index bdbfb24eed036..ddc5d14058dbf 100644 --- a/bundles/org.openhab.binding.telegram/.project +++ b/bundles/org.openhab.binding.telegram/.project @@ -1,23 +1,23 @@ - - - org.openhab.binding.telegram - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - + + + org.openhab.binding.telegram + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/bundles/org.openhab.binding.telegram/README.md b/bundles/org.openhab.binding.telegram/README.md index 023be024e2671..661a583d254bd 100644 --- a/bundles/org.openhab.binding.telegram/README.md +++ b/bundles/org.openhab.binding.telegram/README.md @@ -68,6 +68,11 @@ telegram.thing (no proxy): Thing telegram:telegramBot:Telegram_Bot [ chatIds="< ID >", botToken="< TOKEN >" ] ``` +telegram.thing (multiple chat ids and markdown format): + +``` +Thing telegram:telegramBot:Telegram_Bot [ chatIds="< ID1 >","< ID2 >", botToken="< TOKEN >", parseMode ="Markdown" ] +``` telegram.thing (SOCKS5 proxy server is used): diff --git a/bundles/org.openhab.binding.telegram/pom.xml b/bundles/org.openhab.binding.telegram/pom.xml index 533df85850bf1..35bfb4c30dc64 100644 --- a/bundles/org.openhab.binding.telegram/pom.xml +++ b/bundles/org.openhab.binding.telegram/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.telegram diff --git a/bundles/org.openhab.binding.telegram/src/main/feature/feature.xml b/bundles/org.openhab.binding.telegram/src/main/feature/feature.xml index 5c00437fa9dfe..e1c406e026ba8 100644 --- a/bundles/org.openhab.binding.telegram/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.telegram/src/main/feature/feature.xml @@ -1,6 +1,5 @@ - + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features diff --git a/bundles/org.openhab.binding.telegram/src/main/java/org/openhab/binding/telegram/internal/TelegramHandler.java b/bundles/org.openhab.binding.telegram/src/main/java/org/openhab/binding/telegram/internal/TelegramHandler.java index 10381cab18a0e..430b5dade4639 100644 --- a/bundles/org.openhab.binding.telegram/src/main/java/org/openhab/binding/telegram/internal/TelegramHandler.java +++ b/bundles/org.openhab.binding.telegram/src/main/java/org/openhab/binding/telegram/internal/TelegramHandler.java @@ -333,5 +333,4 @@ public R execute(BaseRequestThing to receive the latest message send to a Telegram Bot. - - - - - - + + + + + + @@ -41,7 +41,7 @@ Enter your proxy host. It will be used for telegram binding only and doesn't affect entire system. - + Enter your proxy port. @@ -61,35 +61,35 @@ String Contains the latest message text as a string - + DateTime Contains the latest message date as a DateTime - + String Contains the latest message senders name as a string - + String Contains the latest message senders username as a string - + String Contains the id of chat from where the message was received. - + @@ -97,7 +97,7 @@ Contains the id of the reply which was passed to sendTelegram() as replyId. This id can be used to have an unambiguous assignment of the user reply to the message which was sent by the bot. - + diff --git a/bundles/org.openhab.binding.tellstick/pom.xml b/bundles/org.openhab.binding.tellstick/pom.xml index d2ca9d4ee59e2..94fd74411c598 100644 --- a/bundles/org.openhab.binding.tellstick/pom.xml +++ b/bundles/org.openhab.binding.tellstick/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.tellstick diff --git a/bundles/org.openhab.binding.tellstick/src/main/feature/feature.xml b/bundles/org.openhab.binding.tellstick/src/main/feature/feature.xml index 6e3ce9620eb5d..7fc59a9d82b68 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.tellstick/src/main/feature/feature.xml @@ -1,14 +1,14 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - openhab.tp-netty - openhab.tp-jaxb - mvn:net.java.dev.jna/jna/4.5.2 - mvn:net.java.dev.jna/jna-platform/4.5.2 - mvn:org.openhab.addons.bundles/org.openhab.binding.tellstick/${project.version} - + + openhab-runtime-base + openhab-transport-serial + openhab.tp-netty + openhab.tp-jaxb + mvn:net.java.dev.jna/jna/4.5.2 + mvn:net.java.dev.jna/jna-platform/4.5.2 + mvn:org.openhab.addons.bundles/org.openhab.binding.tellstick/${project.version} + diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TelldusBindingException.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TelldusBindingException.java index 4fc944e526579..dc9ecf434558a 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TelldusBindingException.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TelldusBindingException.java @@ -35,5 +35,4 @@ public TelldusBindingException(String message) { public String getMessage() { return msg; } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickBindingConstants.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickBindingConstants.java index 545a6949762d6..01ae2d5bed8a0 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickBindingConstants.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickBindingConstants.java @@ -106,5 +106,4 @@ public class TellstickBindingConstants { .of(DIMMER_THING_TYPE, SWITCH_THING_TYPE, SENSOR_THING_TYPE, RAINSENSOR_THING_TYPE, WINDSENSOR_THING_TYPE, POWERSENSOR_THING_TYPE, TELLDUSCOREBRIDGE_THING_TYPE, TELLDUSLIVEBRIDGE_THING_TYPE) .collect(Collectors.toSet())); - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/core/TelldusCoreBridgeHandler.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/core/TelldusCoreBridgeHandler.java index ab3793e64afda..2690532963e5e 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/core/TelldusCoreBridgeHandler.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/core/TelldusCoreBridgeHandler.java @@ -169,7 +169,6 @@ public void rescanTelldusDevices() { private synchronized void setupListeners() { eventHandler = new TellstickEventHandler(deviceList); eventHandler.addListener(this); - } public void onConnectionLost() { @@ -278,5 +277,4 @@ public Device getSensor(String deviceUUId) { public TelldusDeviceController getController() { return this.deviceController; } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/core/TelldusCoreDeviceController.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/core/TelldusCoreDeviceController.java index 358191e33e11c..5d4994a7a78c3 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/core/TelldusCoreDeviceController.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/core/TelldusCoreDeviceController.java @@ -143,7 +143,6 @@ public void onRequest(TellstickSensorEvent newDevices) { @Override public void onRequest(TellstickDeviceEvent newDevices) { setLastSend(newDevices.getTimestamp()); - } private void sendEvent(Device device, int resendCount, boolean isdimmer, Command command) diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickBridgeDiscovery.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickBridgeDiscovery.java index a49b6723b152c..4b11e673f5ff7 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickBridgeDiscovery.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickBridgeDiscovery.java @@ -103,5 +103,4 @@ private void discoveryResultSubmission(TellstickController controller) { .withLabel(controller.getType().name() + ": " + controller.getName()).build()); } } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/DeviceStatusListener.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/DeviceStatusListener.java index 4fe94b49e923a..b1fe6f87a4bff 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/DeviceStatusListener.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/DeviceStatusListener.java @@ -54,5 +54,4 @@ public interface DeviceStatusListener { * The device which is added. */ public void onDeviceAdded(Bridge bridge, Device device); - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusBridgeHandler.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusBridgeHandler.java index 0b77d53eb163c..bab4dcea32c48 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusBridgeHandler.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusBridgeHandler.java @@ -76,5 +76,4 @@ public interface TelldusBridgeHandler { * @param command */ void handleCommand(ChannelUID channelUID, Command command); - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDeviceController.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDeviceController.java index 4338a32c1d1d2..dcb841bc60c5c 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDeviceController.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDeviceController.java @@ -59,5 +59,4 @@ public interface TelldusDeviceController { * */ void dispose(); - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDevicesHandler.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDevicesHandler.java index 23f59a6a9b0d1..c4220d87bbd0c 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDevicesHandler.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDevicesHandler.java @@ -371,5 +371,4 @@ public void onDeviceRemoved(Bridge bridge, Device device) { @Override public void onDeviceAdded(Bridge bridge, Device device) { } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/TelldusLiveDeviceController.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/TelldusLiveDeviceController.java index 5ceef791489c6..03b9d6a20fdcd 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/TelldusLiveDeviceController.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/TelldusLiveDeviceController.java @@ -137,7 +137,6 @@ public void handleSendEvent(Device device, int resendCount, boolean isdimmer, Co } else { logger.warn("Cannot send to {}", device); } - } private void increaseDecrease(Device dev, IncreaseDecreaseType increaseDecreaseType) throws TellstickException { @@ -273,7 +272,6 @@ public void onRequest(TellstickSensorEvent newDevices) { @Override public void onRequest(TellstickDeviceEvent newDevices) { setLastSend(newDevices.getTimestamp()); - } T callRestMethod(String uri, Class response) throws TelldusLiveException { diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/TelldusLiveException.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/TelldusLiveException.java index bb22e54ca16bf..2860b772e904e 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/TelldusLiveException.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/TelldusLiveException.java @@ -33,5 +33,4 @@ public TelldusLiveException(Exception source) { public String getMessage() { return getCause().getMessage(); } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/NameToDataType.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/NameToDataType.java index 975250fb3cc29..309e559c785a9 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/NameToDataType.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/NameToDataType.java @@ -29,5 +29,4 @@ public LiveDataType unmarshal(String v) throws Exception { public String marshal(LiveDataType v) throws Exception { return v.toString(); } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/NumberToBooleanMapper.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/NumberToBooleanMapper.java index 2b1050d1f5dc1..4767e1846a598 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/NumberToBooleanMapper.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/NumberToBooleanMapper.java @@ -30,5 +30,4 @@ public Boolean unmarshal(Integer v) throws Exception { public Integer marshal(Boolean v) throws Exception { return v ? 1 : 0; } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/TelldusLiveResponse.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/TelldusLiveResponse.java index 09b6faf9dab65..60286e5e2e43d 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/TelldusLiveResponse.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/TelldusLiveResponse.java @@ -31,5 +31,4 @@ public class TelldusLiveResponse { public String toString() { return "TelldusLiveResponse [status=" + status + ", error=" + error + "]"; } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/TellstickNetDevice.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/TellstickNetDevice.java index 45bb179ed22a4..69d3cae28f6e6 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/TellstickNetDevice.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/TellstickNetDevice.java @@ -170,5 +170,4 @@ public String toString() { return "TellstickNetDevice [deviceId=" + deviceId + ", name=" + name + ", online=" + online + ", state=" + state + ", statevalue=" + statevalue + ", updated=" + updated + "]"; } - } diff --git a/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/binding/binding.xml index 7e9a8f54e094a..1188315de52ea 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Tellstick Binding diff --git a/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/config/config.xml index 585983fb89eb3..35e46e1535cf8 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/thing/devices.xml b/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/thing/devices.xml index c76f9b42704c3..3e2fa9f1bc596 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/thing/devices.xml +++ b/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/thing/devices.xml @@ -7,17 +7,17 @@ - - + + This is a Dimmable device - - - + + + @@ -52,15 +52,15 @@ - + This Thing defines a Switch Device - - + + @@ -88,7 +88,8 @@ - Is this a dimmer without absolute setting (e.g. you press on to start dim and then on again to stop it). + Is this a dimmer without absolute setting (e.g. you press on to start dim and then on again to stop + it). false false diff --git a/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/thing/sensor.xml b/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/thing/sensor.xml index f1c6df8112585..4a598a43244ec 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/thing/sensor.xml +++ b/bundles/org.openhab.binding.tellstick/src/main/resources/ESH-INF/thing/sensor.xml @@ -6,67 +6,67 @@ - - + + This Thing defines a Sensor - - - - + + + + - + - - + + This Thing defines a Rain Sensor - - - + + + - + - + This Thing defines a Power Sensor - - - + + + - + - - + + This Thing defines a Wind Sensor - - - - + + + + - + @@ -91,7 +91,7 @@ Number:Length The current rain rate - + @@ -121,7 +121,7 @@ Current wind direction Wind - + @@ -136,7 +136,7 @@ Number:Illuminance Current lumination - + diff --git a/bundles/org.openhab.binding.tesla/pom.xml b/bundles/org.openhab.binding.tesla/pom.xml index b1b36a584cc3d..70e1ed58374ad 100644 --- a/bundles/org.openhab.binding.tesla/pom.xml +++ b/bundles/org.openhab.binding.tesla/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.tesla diff --git a/bundles/org.openhab.binding.tesla/src/main/feature/feature.xml b/bundles/org.openhab.binding.tesla/src/main/feature/feature.xml index 523caf20e1d77..a6a257ccb6632 100644 --- a/bundles/org.openhab.binding.tesla/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.tesla/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.tesla/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.tesla/${project.version} + diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java index 4b1a59f42a088..81aab3d2ac37b 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaBindingConstants.java @@ -103,5 +103,4 @@ public enum EventKeys { public static final String CONFIG_REFRESHTOKEN = "refreshToken"; public static final String CONFIG_USERNAME = "username"; public static final String CONFIG_PASSWORD = "password"; - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaChannelSelectorProxy.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaChannelSelectorProxy.java index f553ffa473691..11e612aa5b731 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaChannelSelectorProxy.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaChannelSelectorProxy.java @@ -1087,5 +1087,4 @@ public static TeslaChannelSelector getValueSelectorFromRESTID(String valueSelect public State getState(String s, TeslaChannelSelector selector, Map properties) { return selector.getState(s, this, properties); } - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaHandlerFactory.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaHandlerFactory.java index f1d3a2b2097ce..acdef688a93db 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaHandlerFactory.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/TeslaHandlerFactory.java @@ -18,6 +18,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.ws.rs.client.ClientBuilder; + import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; @@ -27,6 +29,8 @@ import org.openhab.binding.tesla.internal.handler.TeslaAccountHandler; import org.openhab.binding.tesla.internal.handler.TeslaVehicleHandler; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; /** * The {@link TeslaHandlerFactory} is responsible for creating things and thing @@ -39,10 +43,26 @@ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.tesla") public class TeslaHandlerFactory extends BaseThingHandlerFactory { + // TODO: Those constants are Jersey specific - once we move away from Jersey, + // this can be removed and the client builder creation simplified. + public static final String READ_TIMEOUT_JERSEY = "jersey.config.client.readTimeout"; + public static final String CONNECT_TIMEOUT_JERSEY = "jersey.config.client.connectTimeout"; + + public static final String READ_TIMEOUT = "http.receive.timeout"; + public static final String CONNECT_TIMEOUT = "http.connection.timeout"; + + private static final int EVENT_STREAM_CONNECT_TIMEOUT = 3000; + private static final int EVENT_STREAM_READ_TIMEOUT = 200000; + public static final Set SUPPORTED_THING_TYPES_UIDS = Stream .of(THING_TYPE_ACCOUNT, THING_TYPE_MODELS, THING_TYPE_MODEL3, THING_TYPE_MODELX, THING_TYPE_MODELY) .collect(Collectors.toSet()); + @Reference(cardinality = ReferenceCardinality.OPTIONAL) + private ClientBuilder injectedClientBuilder; + + private ClientBuilder clientBuilder; + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); @@ -53,9 +73,29 @@ protected ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(THING_TYPE_ACCOUNT)) { - return new TeslaAccountHandler((Bridge) thing); + return new TeslaAccountHandler((Bridge) thing, getClientBuilder().build()); } else { - return new TeslaVehicleHandler(thing); + return new TeslaVehicleHandler(thing, getClientBuilder()); + } + } + + private synchronized ClientBuilder getClientBuilder() { + if (clientBuilder == null) { + try { + clientBuilder = ClientBuilder.newBuilder(); + clientBuilder.property(CONNECT_TIMEOUT_JERSEY, EVENT_STREAM_CONNECT_TIMEOUT); + clientBuilder.property(READ_TIMEOUT_JERSEY, EVENT_STREAM_READ_TIMEOUT); + } catch (Exception e) { + // we seem to have no Jersey, so let's hope for an injected builder by CXF + if (this.injectedClientBuilder != null) { + clientBuilder = injectedClientBuilder; + clientBuilder.property(CONNECT_TIMEOUT, EVENT_STREAM_CONNECT_TIMEOUT); + clientBuilder.property(READ_TIMEOUT, EVENT_STREAM_READ_TIMEOUT); + } else { + throw new IllegalStateException("No JAX RS Client Builder available."); + } + } } + return clientBuilder; } } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java index 4429ac18f29a8..a094c9b420310 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaAccountHandler.java @@ -32,7 +32,6 @@ import javax.ws.rs.ProcessingException; import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientRequestContext; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.Entity; @@ -86,14 +85,13 @@ public class TeslaAccountHandler extends BaseBridgeHandler { private final Logger logger = LoggerFactory.getLogger(TeslaAccountHandler.class); // REST Client API variables - private final Client teslaClient = ClientBuilder.newClient(); - private final WebTarget teslaTarget = teslaClient.target(URI_OWNERS); - private final WebTarget tokenTarget = teslaTarget.path(URI_ACCESS_TOKEN); - final WebTarget vehiclesTarget = teslaTarget.path(API_VERSION).path(VEHICLES); - final WebTarget vehicleTarget = vehiclesTarget.path(PATH_VEHICLE_ID); - final WebTarget dataRequestTarget = vehicleTarget.path(PATH_DATA_REQUEST); - final WebTarget commandTarget = vehicleTarget.path(PATH_COMMAND); - final WebTarget wakeUpTarget = vehicleTarget.path(PATH_WAKE_UP); + private final WebTarget teslaTarget; + private final WebTarget tokenTarget; + WebTarget vehiclesTarget; // this cannot be marked final as it is used in the runnable + final WebTarget vehicleTarget; + final WebTarget dataRequestTarget; + final WebTarget commandTarget; + final WebTarget wakeUpTarget; // Threading and Job related variables protected ScheduledFuture connectJob; @@ -111,8 +109,15 @@ public class TeslaAccountHandler extends BaseBridgeHandler { private TokenResponse logonToken; private final Set vehicleListeners = new HashSet<>(); - public TeslaAccountHandler(Bridge bridge) { + public TeslaAccountHandler(Bridge bridge, Client teslaClient) { super(bridge); + this.teslaTarget = teslaClient.target(URI_OWNERS); + this.tokenTarget = teslaTarget.path(URI_ACCESS_TOKEN); + this.vehiclesTarget = teslaTarget.path(API_VERSION).path(VEHICLES); + this.vehicleTarget = vehiclesTarget.path(PATH_VEHICLE_ID); + this.dataRequestTarget = vehicleTarget.path(PATH_DATA_REQUEST); + this.commandTarget = vehicleTarget.path(PATH_COMMAND); + this.wakeUpTarget = vehicleTarget.path(PATH_WAKE_UP); } @Override @@ -528,7 +533,6 @@ public void run() { logger.error("An exception occurred while executing a request to the vehicle: '{}'", e.getMessage(), e); } } - } public Request newRequest(TeslaVehicleHandler teslaVehicleHandler, String command, String payLoad, @@ -540,5 +544,4 @@ public Request newRequest(TeslaVehicleHandler teslaVehicleHandler, String comman public Collection> getServices() { return Collections.singletonList(TeslaVehicleDiscoveryService.class); } - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java index a98587339b023..2c450b06b93dc 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/handler/TeslaVehicleHandler.java @@ -55,7 +55,6 @@ import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; -import org.glassfish.jersey.client.ClientProperties; import org.openhab.binding.tesla.internal.TeslaBindingConstants; import org.openhab.binding.tesla.internal.TeslaBindingConstants.EventKeys; import org.openhab.binding.tesla.internal.TeslaChannelSelectorProxy; @@ -87,8 +86,6 @@ */ public class TeslaVehicleHandler extends BaseThingHandler { - private static final int EVENT_STREAM_CONNECT_TIMEOUT = 3000; - private static final int EVENT_STREAM_READ_TIMEOUT = 200000; private static final int EVENT_STREAM_PAUSE = 5000; private static final int EVENT_TIMESTAMP_AGE_LIMIT = 3000; private static final int EVENT_TIMESTAMP_MAX_DELTA = 10000; @@ -132,7 +129,8 @@ public class TeslaVehicleHandler extends BaseThingHandler { protected TeslaAccountHandler account; protected QueueChannelThrottler stateThrottler; - protected Client eventClient = ClientBuilder.newClient(); + protected ClientBuilder clientBuilder; + protected Client eventClient; protected TeslaChannelSelectorProxy teslaChannelSelectorProxy = new TeslaChannelSelectorProxy(); protected Thread eventThread; protected ScheduledFuture fastStateJob; @@ -141,8 +139,9 @@ public class TeslaVehicleHandler extends BaseThingHandler { private final Gson gson = new Gson(); private final JsonParser parser = new JsonParser(); - public TeslaVehicleHandler(Thing thing) { + public TeslaVehicleHandler(Thing thing, ClientBuilder clientBuilder) { super(thing); + this.clientBuilder = clientBuilder; } @SuppressWarnings("null") @@ -214,7 +213,9 @@ public void dispose() { lock.unlock(); } - eventClient.close(); + if (eventClient != null) { + eventClient.close(); + } } /** @@ -987,9 +988,7 @@ protected boolean establishEventStream() { if (!isEstablished) { eventBufferedReader = null; - eventClient = ClientBuilder.newClient() - .property(ClientProperties.CONNECT_TIMEOUT, EVENT_STREAM_CONNECT_TIMEOUT) - .property(ClientProperties.READ_TIMEOUT, EVENT_STREAM_READ_TIMEOUT) + eventClient = clientBuilder.build() .register(new Authenticator((String) getConfig().get(CONFIG_USERNAME), vehicle.tokens[0])); eventTarget = eventClient.target(URI_EVENT).path(vehicle.vehicle_id + "/").queryParam("values", StringUtils.join(EventKeys.values(), ',', 1, EventKeys.values().length)); @@ -1145,5 +1144,4 @@ public void run() { } } }; - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/ChargeState.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/ChargeState.java index 217166f9c4388..4fbc8724eba84 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/ChargeState.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/ChargeState.java @@ -65,5 +65,4 @@ public class ChargeState { ChargeState() { } - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/DriveState.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/DriveState.java index 205c95539b1d2..72c75bddb057f 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/DriveState.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/DriveState.java @@ -33,5 +33,4 @@ public class DriveState { DriveState() { } - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/GUIState.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/GUIState.java index b287eb3a86153..451ce82fd9339 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/GUIState.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/GUIState.java @@ -28,5 +28,4 @@ public class GUIState { public GUIState() { } - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/TokenRequest.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/TokenRequest.java index 5ef00a9774ff1..713648a267b4b 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/TokenRequest.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/TokenRequest.java @@ -66,5 +66,4 @@ public abstract class TokenRequest { throw e; } } - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/TokenRequestPassword.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/TokenRequestPassword.java index 6931c65868c96..a45dfccd1515f 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/TokenRequestPassword.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/TokenRequestPassword.java @@ -35,5 +35,4 @@ public TokenRequestPassword(String email, String password) throws GeneralSecurit this.email = email; this.password = password; } - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/VehicleConfig.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/VehicleConfig.java index 4e303e97734a3..6d11672184bfd 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/VehicleConfig.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/VehicleConfig.java @@ -41,5 +41,4 @@ public class VehicleConfig { public String third_row_seats; public String trim_badging; public String wheel_type; - } diff --git a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/VehicleState.java b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/VehicleState.java index 8c06b6064777a..bd6cda0a3c9df 100644 --- a/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/VehicleState.java +++ b/bundles/org.openhab.binding.tesla/src/main/java/org/openhab/binding/tesla/internal/protocol/VehicleState.java @@ -57,5 +57,4 @@ public class VehicleState { VehicleState() { } - } diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/binding/binding.xml index 2d7b436c93725..9461320635e8d 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Tesla Binding This is the binding for Tesla Electric Vehicles. diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/channels.xml index 26395a998a9c9..9c7d1b8308813 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/channels.xml @@ -595,8 +595,9 @@ Number:Temperature - Combined average temperature of the driver and passenger autoconditioning settings. The temperature for the - driver and passenger will be synced when set. + Combined average temperature of the driver and passenger autoconditioning settings. The temperature for + the + driver and passenger will be synced when set. diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/model3.xml b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/model3.xml index caa4f64812231..1ceca7a8416dc 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/model3.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/model3.xml @@ -7,113 +7,113 @@ - + A Tesla Model 3 Vehicle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/models.xml b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/models.xml index 3859eec9fa90e..7d394f86604e1 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/models.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/models.xml @@ -7,120 +7,120 @@ - + A Tesla Model S Vehicle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/modelx.xml b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/modelx.xml index 00bb0367b1048..df139b3a2ac1e 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/modelx.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/modelx.xml @@ -7,120 +7,120 @@ - + A Tesla Model X Vehicle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/modely.xml b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/modely.xml index ec2be2850f67e..61fda3be9908f 100644 --- a/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/modely.xml +++ b/bundles/org.openhab.binding.tesla/src/main/resources/ESH-INF/thing/modely.xml @@ -7,115 +7,115 @@ - + A Tesla Model Y Vehicle - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.tibber/pom.xml b/bundles/org.openhab.binding.tibber/pom.xml index ac1d3bd5e7a3b..0355d82c97d74 100644 --- a/bundles/org.openhab.binding.tibber/pom.xml +++ b/bundles/org.openhab.binding.tibber/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.tibber diff --git a/bundles/org.openhab.binding.tibber/src/main/feature/feature.xml b/bundles/org.openhab.binding.tibber/src/main/feature/feature.xml index 3b03fd0f77f6b..f171273bd2fc4 100755 --- a/bundles/org.openhab.binding.tibber/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.tibber/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.tibber/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.tibber/${project.version} + diff --git a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/TibberBindingConstants.java b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/TibberBindingConstants.java index 1384b183ec6f0..a9bf7967631f8 100755 --- a/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/TibberBindingConstants.java +++ b/bundles/org.openhab.binding.tibber/src/main/java/org/openhab/binding/tibber/internal/TibberBindingConstants.java @@ -77,5 +77,4 @@ public class TibberBindingConstants { public static final Set SUPPORTED_THING_TYPES_UIDS = Stream.of(TIBBER_THING_TYPE) .collect(Collectors.toSet()); - } diff --git a/bundles/org.openhab.binding.tibber/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.tibber/src/main/resources/ESH-INF/binding/binding.xml index d718100643266..76d6db88f46ba 100755 --- a/bundles/org.openhab.binding.tibber/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.tibber/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,7 @@ - + Tibber Binding This binding retrieves price and consumption data from Tibber API using queries and live subscription diff --git a/bundles/org.openhab.binding.tibber/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.tibber/src/main/resources/ESH-INF/thing/thing-types.xml index 2bf97614b4752..0a7bd7ebca0e5 100755 --- a/bundles/org.openhab.binding.tibber/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.tibber/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,56 +1,56 @@ - - - + + Tibber API connector - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Tibber - + Tibber Personal Token - + Tibber Home ID - + 1 Manually Set Polling Frequency (minutes) diff --git a/bundles/org.openhab.binding.tplinksmarthome/pom.xml b/bundles/org.openhab.binding.tplinksmarthome/pom.xml index fe33f221a84c1..d9ad26e2d4995 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/pom.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.tplinksmarthome diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/feature/feature.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/feature/feature.xml index ea22be47f8643..795f14fec687e 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.tplinksmarthome/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.tplinksmarthome/${project.version} + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/CryptUtil.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/CryptUtil.java index 8b9789404ee3d..4b62333cbec68 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/CryptUtil.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/CryptUtil.java @@ -114,5 +114,4 @@ public static byte[] encrypt(String string) { } return buffer; } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/device/DimmerDevice.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/device/DimmerDevice.java index dab23fa26c727..d618b2d74a3b6 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/device/DimmerDevice.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/device/DimmerDevice.java @@ -12,6 +12,10 @@ */ package org.openhab.binding.tplinksmarthome.internal.device; +import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeBindingConstants.CHANNEL_BRIGHTNESS; + +import java.io.IOException; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; @@ -21,10 +25,6 @@ import org.eclipse.smarthome.core.types.State; import org.openhab.binding.tplinksmarthome.internal.model.HasErrorResponse; -import java.io.IOException; - -import static org.openhab.binding.tplinksmarthome.internal.TPLinkSmartHomeBindingConstants.CHANNEL_BRIGHTNESS; - /** * TP-Link Smart Home device with a dimmer (HS220). * @@ -40,9 +40,8 @@ public class DimmerDevice extends SwitchDevice { @Override public boolean handleCommand(ChannelUID channelUid, Command command) throws IOException { - return CHANNEL_BRIGHTNESS.equals(channelUid.getId()) ? - handleBrightnessChannel(channelUid, command) : - super.handleCommand(channelUid, command); + return CHANNEL_BRIGHTNESS.equals(channelUid.getId()) ? handleBrightnessChannel(channelUid, command) + : super.handleCommand(channelUid, command); } /** @@ -82,9 +81,8 @@ private boolean handleBrightnessChannel(ChannelUID channelUid, Command command) @Override public State updateChannel(ChannelUID channelUid, DeviceState deviceState) { if (CHANNEL_BRIGHTNESS.equals(channelUid.getId())) { - return deviceState.getSysinfo().getRelayState() == OnOffType.OFF ? - PercentType.ZERO : - new PercentType(deviceState.getSysinfo().getBrightness()); + return deviceState.getSysinfo().getRelayState() == OnOffType.OFF ? PercentType.ZERO + : new PercentType(deviceState.getSysinfo().getBrightness()); } else { return super.updateChannel(channelUid, deviceState); } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/device/RangeExtenderDevice.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/device/RangeExtenderDevice.java index 2ca3d0c2cd041..7d17e3d8cb98a 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/device/RangeExtenderDevice.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/device/RangeExtenderDevice.java @@ -35,8 +35,7 @@ protected State getOnOffState(DeviceState deviceState) { } @Override - protected @Nullable SetRelayState setOnOffState(ChannelUID channelUid, OnOffType onOff) - throws IOException { + protected @Nullable SetRelayState setOnOffState(ChannelUID channelUid, OnOffType onOff) throws IOException { // It's unknown what the command is to send to the device so it's not supported. return null; } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/LightState.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/LightState.java index c962dfcb6a1f6..3a4935498fc1b 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/LightState.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/LightState.java @@ -70,5 +70,4 @@ public String toString() { + ignoreDefault + ", mode:" + mode + ", on_off:" + onOff + ", saturation:" + saturation + super.toString(); } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/Realtime.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/Realtime.java index 9e1963bc217a3..2959dd92c2415 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/Realtime.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/Realtime.java @@ -57,5 +57,4 @@ public String toString() { return "current:" + getCurrent() + ", power:" + getPower() + ", total:" + getTotal() + ", voltage:" + getVoltage() + super.toString(); } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/SetLedOff.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/SetLedOff.java index ff424abe86788..948b263ba74ed 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/SetLedOff.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/SetLedOff.java @@ -64,5 +64,4 @@ public void setLed(OnOffType onOff) { public String toString() { return "SetLedOff {system:{" + system + "}"; } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/TransitionLightState.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/TransitionLightState.java index 69c782abfd949..0b914a06a5ee3 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/TransitionLightState.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/TransitionLightState.java @@ -78,7 +78,6 @@ public void setBrightness(int brightness) { public String toString() { return "brightness:" + brightness + ", " + super.toString(); } - } public static class LightOnOff { diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/TransitionLightStateResponse.java b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/TransitionLightStateResponse.java index 40634cf02d72f..29816b7fbc268 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/TransitionLightStateResponse.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/java/org/openhab/binding/tplinksmarthome/internal/model/TransitionLightStateResponse.java @@ -43,5 +43,4 @@ public ErrorResponse getErrorResponse() { public String toString() { return "TransitionLightStateResponse {service:{" + service + "}"; } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS100.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS100.xml index cdc4247ab8b98..ec42efde893b2 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS100.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS100.xml @@ -10,13 +10,13 @@ PowerOutlet - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS103.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS103.xml index 153eb2bbf2d6a..0e0446186376d 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS103.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS103.xml @@ -10,13 +10,13 @@ PowerOutlet - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS105.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS105.xml index 32e174d00c8c1..69497aa2ddb5b 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS105.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS105.xml @@ -10,13 +10,13 @@ PowerOutlet - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS107.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS107.xml index 452caec2571de..521d9cc553bce 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS107.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS107.xml @@ -10,7 +10,7 @@ PowerOutlet - + @@ -21,6 +21,6 @@ deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS110.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS110.xml index 79a36c47f0f5a..56bd39362711e 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS110.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS110.xml @@ -10,17 +10,17 @@ PowerOutlet - - - - - - - + + + + + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS200.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS200.xml index 701a22d18c64c..23e17898a6864 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS200.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS200.xml @@ -10,13 +10,13 @@ WallSwitch - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS210.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS210.xml index c2f3d6008e3c3..2631284ea563a 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS210.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS210.xml @@ -10,13 +10,13 @@ WallSwitch - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS220.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS220.xml index fb81a32448d45..35a96820163bb 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS220.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS220.xml @@ -10,13 +10,13 @@ WallSwitch - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS300.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS300.xml index 57779f37a8925..bc1f3fac75ec5 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS300.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/HS300.xml @@ -10,7 +10,7 @@ PowerOutlet - + @@ -33,7 +33,7 @@ deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KB100.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KB100.xml index 91dafed80b70f..5494f65e15166 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KB100.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KB100.xml @@ -10,12 +10,12 @@ Lightbulb - - + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KB130.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KB130.xml index 34fb5bc804c3e..4d310319c4c3f 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KB130.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KB130.xml @@ -10,14 +10,14 @@ Lightbulb - - - - + + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL110.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL110.xml index 81a0c507cb4d7..56f967cdb7624 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL110.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL110.xml @@ -10,13 +10,13 @@ Lightbulb - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL120.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL120.xml index 610f28df3a6b8..7d070479eb31e 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL120.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL120.xml @@ -10,15 +10,15 @@ Lightbulb - - - - - + + + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL130.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL130.xml index 2a57f9cfe7110..8b66463801c9e 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL130.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL130.xml @@ -10,15 +10,15 @@ Lightbulb - - - - - + + + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL50.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL50.xml index bd41e2bdb79b7..4eb5cba2e6648 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL50.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL50.xml @@ -10,13 +10,13 @@ Lightbulb - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL60.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL60.xml index d9fd18363e0f8..4f0d1cacef55b 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL60.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KL60.xml @@ -10,13 +10,13 @@ Lightbulb - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP100.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP100.xml index faf7dc3d2fb5e..019693b027e02 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP100.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP100.xml @@ -10,13 +10,13 @@ PowerOutlet - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP200.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP200.xml index 0a96fb11f526b..204da7a0150ca 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP200.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP200.xml @@ -10,7 +10,7 @@ PowerOutlet - + @@ -21,6 +21,6 @@ deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP303.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP303.xml index 4b9601a8a2fb0..13087e1f5e81f 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP303.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP303.xml @@ -10,7 +10,7 @@ PowerOutlet - + @@ -24,7 +24,7 @@ deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP400.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP400.xml index d2fd8122dc7ba..2127b755f7849 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP400.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/KP400.xml @@ -10,7 +10,7 @@ PowerOutlet - + @@ -21,6 +21,6 @@ deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB100.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB100.xml index a59aca5102835..1e0b74cc04439 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB100.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB100.xml @@ -10,13 +10,13 @@ Lightbulb - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB110.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB110.xml index 49c46808cdc53..05676b9dff903 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB110.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB110.xml @@ -10,13 +10,13 @@ Lightbulb - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB120.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB120.xml index c190375c1efe1..aea43a495c289 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB120.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB120.xml @@ -10,15 +10,15 @@ Lightbulb - - - - - + + + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB130.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB130.xml index 988b7a8003e1d..65d0e8bd4d3df 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB130.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB130.xml @@ -10,15 +10,15 @@ Lightbulb - - - - - + + + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB200.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB200.xml index f0501b352a5a1..93ae2f03cf441 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB200.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB200.xml @@ -10,13 +10,13 @@ Lightbulb - - - + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB230.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB230.xml index 2cab092343fe0..46c6e1352298f 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB230.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/LB230.xml @@ -10,15 +10,15 @@ Lightbulb - - - - - + + + + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/RE270K.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/RE270K.xml index 9f10a59173d0b..fc2c8d2abef02 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/RE270K.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/RE270K.xml @@ -10,12 +10,12 @@ PowerOutlet - - + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/RE370K.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/RE370K.xml index 19838ad31c8eb..fcb3b31b23a86 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/RE370K.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/RE370K.xml @@ -10,12 +10,12 @@ PowerOutlet - - + + deviceId - + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/channels.xml index 75029365c66cd..ba74f5f3bc724 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.tplinksmarthome/src/main/resources/ESH-INF/thing/channels.xml @@ -10,7 +10,7 @@ Shows the switch state of the Smart Home device. Switch - + Switch @@ -25,7 +25,7 @@ This channel supports adjusting the color temperature from 2700K to 6500K. ColorLight - + @@ -33,7 +33,7 @@ This channel supports adjusting the color temperature from 2500K to 9000K. ColorLight - + @@ -80,27 +80,27 @@ PowerOutlet - - - + + + PowerOutlet - + PowerOutlet - - - - - + + + + + diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/CryptUtilTest.java b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/CryptUtilTest.java index 8c7f1b3248bc5..b08bf56a1b97b 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/CryptUtilTest.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/CryptUtilTest.java @@ -50,5 +50,4 @@ public void testCryptWithLength() throws IOException { assertEquals("Crypting should result in same string", TEST_STRING, CryptUtil.decryptWithLength(is)); } } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryServiceTest.java b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryServiceTest.java index 9b36d3b9ab5f5..b0def724e5ffc 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryServiceTest.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/TPLinkSmartHomeDiscoveryServiceTest.java @@ -92,7 +92,6 @@ public Void answer(InvocationOnMock invocation) throws Throwable { packet.setData(CryptUtil.encrypt(ModelTestUtil.readJson(filename))); return null; } - }).when(discoverSocket).receive(any()); discoveryService.addDiscoveryListener(discoveryListener); } @@ -111,5 +110,4 @@ public void testScan() { assertEquals("Check if expected number of properties found", propertiesSize, discoveryResult.getProperties().size()); } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/BulbDeviceTest.java b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/BulbDeviceTest.java index a54d5fd362993..fd8d067574522 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/BulbDeviceTest.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/BulbDeviceTest.java @@ -168,5 +168,4 @@ public void testUpdateChannelPower() { assertEquals("Power values should be set", new DecimalType(10.8), device.updateChannel(CHANNEL_UID_ENERGY_POWER, deviceState)); } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/DimmerDeviceTest.java b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/DimmerDeviceTest.java index 4697ba68206ea..3a3a397a00590 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/DimmerDeviceTest.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/DimmerDeviceTest.java @@ -57,7 +57,7 @@ public void testHandleCommandBrightnessZero() throws IOException { @Test public void testHandleCommandBrightness() throws IOException { assertInput("dimmer_set_brightness", "dimmer_set_switch_state_on"); - setSocketReturnAssert( "dimmer_set_brightness_response","dimmer_set_switch_state_on"); + setSocketReturnAssert("dimmer_set_brightness_response", "dimmer_set_switch_state_on"); assertTrue("Brightness channel should be handled", device.handleCommand(CHANNEL_UID_BRIGHTNESS, new PercentType(17))); } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/EnergySwitchDeviceTest.java b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/EnergySwitchDeviceTest.java index 98afb1e46c1df..960a53683fd2f 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/EnergySwitchDeviceTest.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/EnergySwitchDeviceTest.java @@ -83,5 +83,4 @@ public void testUpdateChannelOther() { assertSame("Unknown channel should return UNDEF", UnDefType.UNDEF, device.updateChannel(CHANNEL_UID_OTHER, deviceState)); } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/RangeExtenderDeviceTest.java b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/RangeExtenderDeviceTest.java index fcea0700f06c8..08c173ae7be94 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/RangeExtenderDeviceTest.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/device/RangeExtenderDeviceTest.java @@ -55,5 +55,4 @@ public void testUpdateChannelOther() { assertSame("Unknown channel should return UNDEF", UnDefType.UNDEF, device.updateChannel(CHANNEL_UID_OTHER, deviceState)); } - } diff --git a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/model/ModelTestUtil.java b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/model/ModelTestUtil.java index 8a7f24fb5ee70..106f2346009a2 100644 --- a/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/model/ModelTestUtil.java +++ b/bundles/org.openhab.binding.tplinksmarthome/src/test/java/org/openhab/binding/tplinksmarthome/internal/model/ModelTestUtil.java @@ -62,5 +62,4 @@ public static String readJson(String filename) throws IOException { .toString(ModelTestUtil.class.getResourceAsStream(filename + ".json"), StandardCharsets.UTF_8.name()) .replaceAll("[\n\r\t ]", ""); } - } diff --git a/bundles/org.openhab.binding.tradfri/pom.xml b/bundles/org.openhab.binding.tradfri/pom.xml index 9680566f63677..375773f8238d1 100644 --- a/bundles/org.openhab.binding.tradfri/pom.xml +++ b/bundles/org.openhab.binding.tradfri/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.tradfri diff --git a/bundles/org.openhab.binding.tradfri/src/main/feature/feature.xml b/bundles/org.openhab.binding.tradfri/src/main/feature/feature.xml index 9eed501971973..6f1c1689b84d7 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.tradfri/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-coap - openhab-transport-mdns - mvn:org.openhab.addons.bundles/org.openhab.binding.tradfri/${project.version} - + + openhab-runtime-base + openhab-transport-coap + openhab-transport-mdns + mvn:org.openhab.addons.bundles/org.openhab.binding.tradfri/${project.version} + diff --git a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriHandlerFactory.java b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriHandlerFactory.java index d35795d589823..197faea3190d8 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriHandlerFactory.java +++ b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/TradfriHandlerFactory.java @@ -66,5 +66,4 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } return null; } - } diff --git a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriGatewayHandler.java b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriGatewayHandler.java index b002bb7eb0014..b9d129471ee1c 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriGatewayHandler.java +++ b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriGatewayHandler.java @@ -15,7 +15,6 @@ import static org.openhab.binding.tradfri.internal.TradfriBindingConstants.*; import java.io.IOException; -import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; import java.util.Collection; @@ -352,10 +351,9 @@ private synchronized void requestDeviceDetails(String instanceId) { public void setStatus(ThingStatus status, ThingStatusDetail statusDetail) { // to fix connection issues after a gateway reboot, a session resume is forced for the next command if (status == ThingStatus.OFFLINE && statusDetail == ThingStatusDetail.COMMUNICATION_ERROR) { - logger.debug("Gateway communication error. Forcing session resume on next command."); - TradfriGatewayConfig configuration = getConfigAs(TradfriGatewayConfig.class); - InetSocketAddress peerAddress = new InetSocketAddress(configuration.host, configuration.port); - this.dtlsConnector.forceResumeSessionFor(peerAddress); + logger.debug("Gateway communication error. Forcing a re-initialization!"); + dispose(); + initialize(); } // are we still connected at all? diff --git a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriPlugHandler.java b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriPlugHandler.java index f687305fed8ed..a6aa3127da5a9 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriPlugHandler.java +++ b/bundles/org.openhab.binding.tradfri/src/main/java/org/openhab/binding/tradfri/internal/handler/TradfriPlugHandler.java @@ -80,5 +80,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { } } } - } diff --git a/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/thing/thing-types.xml index 123b3228a9aeb..f767acec7cd5e 100644 --- a/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.tradfri/src/main/resources/ESH-INF/thing/thing-types.xml @@ -10,170 +10,170 @@ host - + - + A plug that can be switched on and off. - + id - + - + A light that has continuous brightness control. - + id - + - + A dimmable light that supports different color temperature settings. - - + + id - + - + A dimmable light that supports full colors and color temperature settings. - - + + id - + - + This represents the motion sensor capable of reporting the battery level. - - + + id - + - + This represents the wireless dimmer sensor capable of reporting the battery level. - - + + id - + - + This represents the remote control capable of reporting the battery level. - - + + id - + - + This represents a blind or curtain that can be moved up and down. Also reports current battery level. - - - + + + id - + - + This represents the wireless open/close remote capable of reporting the battery level. - - + + id - + diff --git a/bundles/org.openhab.binding.tradfri/src/test/java/org/openhab/binding/tradfri/internal/TradfriColorTest.java b/bundles/org.openhab.binding.tradfri/src/test/java/org/openhab/binding/tradfri/internal/TradfriColorTest.java index 1f37eaf694770..4a94f6891a651 100644 --- a/bundles/org.openhab.binding.tradfri/src/test/java/org/openhab/binding/tradfri/internal/TradfriColorTest.java +++ b/bundles/org.openhab.binding.tradfri/src/test/java/org/openhab/binding/tradfri/internal/TradfriColorTest.java @@ -186,5 +186,4 @@ public void testCalculateColorTemperature() { PercentType mixed2 = new TradfriColor(1000000, 0, null).getColorTemperature(); assertEquals(100, mixed2.intValue()); } - } diff --git a/bundles/org.openhab.binding.unifi/pom.xml b/bundles/org.openhab.binding.unifi/pom.xml index 3ec2165f730c3..4a5fb1cc4c0b4 100644 --- a/bundles/org.openhab.binding.unifi/pom.xml +++ b/bundles/org.openhab.binding.unifi/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.unifi diff --git a/bundles/org.openhab.binding.unifi/src/main/feature/feature.xml b/bundles/org.openhab.binding.unifi/src/main/feature/feature.xml index ceb9e45eb6fae..b59b299efce85 100644 --- a/bundles/org.openhab.binding.unifi/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.unifi/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.unifi/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.unifi/${project.version} + diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiBindingConstants.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiBindingConstants.java index 2e31c78aa45af..438aadfaef147 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiBindingConstants.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiBindingConstants.java @@ -55,5 +55,4 @@ public class UniFiBindingConstants { public static final String PARAMETER_PASSWORD = "password"; public static final String PARAMETER_SITE = "site"; public static final String PARAMETER_CID = "cid"; - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiClientThingConfig.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiClientThingConfig.java index 8159e992b5b98..ee37c428647ed 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiClientThingConfig.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiClientThingConfig.java @@ -55,5 +55,4 @@ public boolean isValid() { public String toString() { return String.format("UniFiClientConfig{cid: '%s', site: '%s', considerHome: %d}", cid, site, considerHome); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiThingHandlerFactory.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiThingHandlerFactory.java index 63bc707846521..808301c99325b 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiThingHandlerFactory.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/UniFiThingHandlerFactory.java @@ -72,5 +72,4 @@ public void setHttpClientFactory(HttpClientFactory httpClientFactory) { public void unsetHttpClientFactory(HttpClientFactory httpClientFactory) { // nop } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiCommunicationException.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiCommunicationException.java index d50e68db6feba..cbadfcc35971f 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiCommunicationException.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiCommunicationException.java @@ -24,5 +24,4 @@ public class UniFiCommunicationException extends UniFiException { public UniFiCommunicationException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiException.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiException.java index 7716b94573b13..ec71f10eb89d9 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiException.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiException.java @@ -32,5 +32,4 @@ public UniFiException(String message, Throwable cause) { public UniFiException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiExpiredSessionException.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiExpiredSessionException.java index 8dded35fc3855..26c1e5ab1d7c4 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiExpiredSessionException.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiExpiredSessionException.java @@ -24,5 +24,4 @@ public class UniFiExpiredSessionException extends UniFiException { public UniFiExpiredSessionException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiInvalidCredentialsException.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiInvalidCredentialsException.java index 94896bd4a811f..4b7a00db08efc 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiInvalidCredentialsException.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiInvalidCredentialsException.java @@ -25,5 +25,4 @@ public class UniFiInvalidCredentialsException extends UniFiException { public UniFiInvalidCredentialsException(String message) { super(message); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiInvalidHostException.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiInvalidHostException.java index 7470eb0b4f5a7..5b334eb18aee1 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiInvalidHostException.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiInvalidHostException.java @@ -32,5 +32,4 @@ public UniFiInvalidHostException(String message, Throwable cause) { public UniFiInvalidHostException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiNotAuthorizedException.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiNotAuthorizedException.java index 7567fbdbec1cf..fc88d166c54b3 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiNotAuthorizedException.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiNotAuthorizedException.java @@ -32,5 +32,4 @@ public UniFiNotAuthorizedException(String message, Throwable cause) { public UniFiNotAuthorizedException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiSSLException.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiSSLException.java index 9dc691a110446..21b0d1abf1b61 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiSSLException.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/UniFiSSLException.java @@ -32,5 +32,4 @@ public UniFiSSLException(String message, Throwable cause) { public UniFiSSLException(Throwable cause) { super(cause); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiCache.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiCache.java index d483956511d4e..665a5db1533ac 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiCache.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiCache.java @@ -93,5 +93,4 @@ public final Collection values() { } protected abstract String getSuffix(T value, String prefix); - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiClientCache.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiClientCache.java index 75485a10f6c22..c8ed856f35d8e 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiClientCache.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiClientCache.java @@ -43,5 +43,4 @@ protected String getSuffix(UniFiClient client, String prefix) { } return null; } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiDeviceCache.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiDeviceCache.java index 0f993e434d220..72c64799c4747 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiDeviceCache.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiDeviceCache.java @@ -36,5 +36,4 @@ protected String getSuffix(UniFiDevice device, String prefix) { } return null; } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiSiteCache.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiSiteCache.java index 9b8fb800bc2e9..f35a7c6fb6289 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiSiteCache.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/cache/UniFiSiteCache.java @@ -40,5 +40,4 @@ protected String getSuffix(UniFiSite site, String prefix) { } return null; } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiClient.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiClient.java index 8616e5519f84c..e41ffb7e0450f 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiClient.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiClient.java @@ -124,5 +124,4 @@ public String toString() { "UniFiClient{mac: '%s', ip: '%s', hostname: '%s', alias: '%s', wired: %b, blocked: %b, device: %s}", mac, ip, hostname, alias, isWired(), blocked, getDevice()); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiController.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiController.java index b764ab8c5e8fc..fb2b334696588 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiController.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiController.java @@ -301,8 +301,6 @@ public String toString() { } return value; } - }; } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiControllerRequest.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiControllerRequest.java index 94cbd99dadae1..29e6a85e7e8c5 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiControllerRequest.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiControllerRequest.java @@ -222,5 +222,4 @@ private static String prettyPrintJson(String content) { Gson prettyGson = new GsonBuilder().setPrettyPrinting().create(); return prettyGson.toJson(json); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiSite.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiSite.java index 054b444851a8b..aeb10bd07b819 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiSite.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiSite.java @@ -57,5 +57,4 @@ public boolean matchesName(String siteName) { public String toString() { return String.format("UniFiSite{name: '%s', desc: '%s'}", name, desc); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiUnknownClient.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiUnknownClient.java index 97946cd52bfad..a8d482f815421 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiUnknownClient.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiUnknownClient.java @@ -35,5 +35,4 @@ public Boolean isWired() { public String getDeviceMac() { return null; // mgb: no device mac in the json } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiWiredClient.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiWiredClient.java index edb2388d134fc..82e568fb2d199 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiWiredClient.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiWiredClient.java @@ -36,5 +36,4 @@ public Boolean isWired() { public String getDeviceMac() { return swMac; } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiWirelessClient.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiWirelessClient.java index b6a105ea1ac8c..1a123f84e8547 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiWirelessClient.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/model/UniFiWirelessClient.java @@ -53,5 +53,4 @@ public String getEssid() { public Integer getRssi() { return rssi; } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiClientDeserializer.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiClientDeserializer.java index bf9c026903f76..4f1487a256138 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiClientDeserializer.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiClientDeserializer.java @@ -52,5 +52,4 @@ public UniFiClient deserialize(JsonElement json, Type type, JsonDeserializationC } return context.deserialize(json, UniFiWirelessClient.class); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiClientInstanceCreator.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiClientInstanceCreator.java index caab536eabb9a..1a4961f6e5ccd 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiClientInstanceCreator.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiClientInstanceCreator.java @@ -49,5 +49,4 @@ public UniFiClient createInstance(Type type) { } return null; } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiDeviceInstanceCreator.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiDeviceInstanceCreator.java index f5aadd94a284e..ad0a74fb70819 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiDeviceInstanceCreator.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiDeviceInstanceCreator.java @@ -38,5 +38,4 @@ public UniFiDeviceInstanceCreator(UniFiController controller) { public UniFiDevice createInstance(Type type) { return new UniFiDevice(controller); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiSiteInstanceCreator.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiSiteInstanceCreator.java index f0a100e9cc4de..aac2ac866a47e 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiSiteInstanceCreator.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiSiteInstanceCreator.java @@ -38,5 +38,4 @@ public UniFiSiteInstanceCreator(UniFiController controller) { public UniFiSite createInstance(Type type) { return new UniFiSite(controller); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiTidyLowerCaseStringDeserializer.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiTidyLowerCaseStringDeserializer.java index 7a4d89c053dab..7a5a84b69de88 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiTidyLowerCaseStringDeserializer.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiTidyLowerCaseStringDeserializer.java @@ -36,5 +36,4 @@ public String deserialize(JsonElement json, Type type, JsonDeserializationContex String s = json.getAsJsonPrimitive().getAsString(); return StringUtils.lowerCase(StringUtils.strip(s)); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiTimestampDeserializer.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiTimestampDeserializer.java index 64b4a738dd6ab..69c1824b5164c 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiTimestampDeserializer.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/api/util/UniFiTimestampDeserializer.java @@ -35,5 +35,4 @@ public Calendar deserialize(JsonElement json, Type type, JsonDeserializationCont cal.setTimeInMillis(millis); return cal; } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiBaseThingHandler.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiBaseThingHandler.java index 885d4642f73d5..da9e3e692daff 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiBaseThingHandler.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiBaseThingHandler.java @@ -129,5 +129,4 @@ protected final void refresh() { protected abstract void refreshChannel(E entity, ChannelUID channelUID); protected abstract void handleCommand(E entity, ChannelUID channelUID, Command command) throws UniFiException; - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiClientThingHandler.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiClientThingHandler.java index 64c9517c9bfc6..f4e05c28ee562 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiClientThingHandler.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiClientThingHandler.java @@ -296,5 +296,4 @@ private void handleReconnectCommand(UniFiClient client, ChannelUID channelUID, C command, channelUID); } } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiControllerThingHandler.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiControllerThingHandler.java index a296b4fdc55d2..c01baa244b292 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiControllerThingHandler.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/handler/UniFiControllerThingHandler.java @@ -196,5 +196,4 @@ private void refresh() throws UniFiException { }); } } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/ssl/UniFiTrustManager.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/ssl/UniFiTrustManager.java index 6b99faee7ad21..e8154c268b2b9 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/ssl/UniFiTrustManager.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/ssl/UniFiTrustManager.java @@ -73,5 +73,4 @@ public void checkServerTrusted(X509Certificate[] chain, String authType, Socket public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) throws CertificateException { } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/ssl/UniFiTrustManagerProvider.java b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/ssl/UniFiTrustManagerProvider.java index 195ff33a76567..45df1eeb935c9 100644 --- a/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/ssl/UniFiTrustManagerProvider.java +++ b/bundles/org.openhab.binding.unifi/src/main/java/org/openhab/binding/unifi/internal/ssl/UniFiTrustManagerProvider.java @@ -36,5 +36,4 @@ public String getHostName() { public X509ExtendedTrustManager getTrustManager() { return UniFiTrustManager.getInstance(); } - } diff --git a/bundles/org.openhab.binding.unifi/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.unifi/src/main/resources/ESH-INF/binding/binding.xml index cc2b3014041f2..74259a2f8cc88 100644 --- a/bundles/org.openhab.binding.unifi/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.unifi/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,11 @@ - + UniFi Binding - The UniFi binding integrates the UniFi controller from Ubiquiti Networks to facilitate tracking of Wi-Fi clients. + The UniFi binding integrates the UniFi controller from Ubiquiti Networks to facilitate tracking of Wi-Fi + clients. Matthew Bowman diff --git a/bundles/org.openhab.binding.unifi/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.unifi/src/main/resources/ESH-INF/thing/thing-types.xml index eab2c216b12d6..4ceb58792d606 100644 --- a/bundles/org.openhab.binding.unifi/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.unifi/src/main/resources/ESH-INF/thing/thing-types.xml @@ -44,25 +44,25 @@ - + A wireless client connected to a UniFi wireless network - - - - - - - + + + + + + + - - - - + + + + cid diff --git a/bundles/org.openhab.binding.urtsi/pom.xml b/bundles/org.openhab.binding.urtsi/pom.xml index 105a8a0a287ea..6bf9467f38317 100644 --- a/bundles/org.openhab.binding.urtsi/pom.xml +++ b/bundles/org.openhab.binding.urtsi/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.urtsi diff --git a/bundles/org.openhab.binding.urtsi/src/main/feature/feature.xml b/bundles/org.openhab.binding.urtsi/src/main/feature/feature.xml index 359df10d4b70f..d48f9f8d0ff97 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.urtsi/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.urtsi/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.urtsi/${project.version} + diff --git a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/UrtsiBindingConstants.java b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/UrtsiBindingConstants.java index 8d27e7d70c4bb..f521432fdf3fd 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/UrtsiBindingConstants.java +++ b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/UrtsiBindingConstants.java @@ -41,5 +41,4 @@ public class UrtsiBindingConstants { * Rollershutter's position */ public static final String POSITION = "position"; - } diff --git a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/UrtsiHandlerFactory.java b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/UrtsiHandlerFactory.java index a95399a2c087c..81148ce3dbb26 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/UrtsiHandlerFactory.java +++ b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/UrtsiHandlerFactory.java @@ -17,15 +17,20 @@ import java.util.Arrays; import java.util.List; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.urtsi.internal.handler.RtsDeviceHandler; import org.openhab.binding.urtsi.internal.handler.UrtsiDeviceHandler; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link UrtsiHandlerFactory} is responsible for creating things and thing @@ -33,23 +38,31 @@ * * @author Oliver Libutzki - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.urtsi") public class UrtsiHandlerFactory extends BaseThingHandlerFactory { private static final List SUPPORTED_THING_TYPES_UIDS = Arrays.asList(URTSI_DEVICE_THING_TYPE, RTS_DEVICE_THING_TYPE); + private final SerialPortManager serialPortManager; + + @Activate + public UrtsiHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(URTSI_DEVICE_THING_TYPE) && thing instanceof Bridge) { - return new UrtsiDeviceHandler((Bridge) thing); + return new UrtsiDeviceHandler((Bridge) thing, serialPortManager); } else if (thingTypeUID.equals(RTS_DEVICE_THING_TYPE)) { return new RtsDeviceHandler(thing); } diff --git a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/RtsCommand.java b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/RtsCommand.java index 3a31a3f1cd3b7..b6b22b7f1d538 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/RtsCommand.java +++ b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/RtsCommand.java @@ -37,5 +37,4 @@ private RtsCommand(String actionKey) { public String getActionKey() { return actionKey; } - } diff --git a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/RtsDeviceHandler.java b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/RtsDeviceHandler.java index 3363bbec7062f..8174d276db8d7 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/RtsDeviceHandler.java +++ b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/RtsDeviceHandler.java @@ -91,5 +91,4 @@ public void initialize() { } } - } diff --git a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/UrtsiDeviceHandler.java b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/UrtsiDeviceHandler.java index 3c2b3f339fd9e..9ee2ee8314842 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/UrtsiDeviceHandler.java +++ b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/handler/UrtsiDeviceHandler.java @@ -16,14 +16,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.TooManyListenersException; import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; @@ -31,18 +27,19 @@ import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.urtsi.internal.config.RtsDeviceConfig; import org.openhab.binding.urtsi.internal.config.UrtsiDeviceConfig; import org.openhab.binding.urtsi.internal.mapping.UrtsiChannelMapping; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.CommPortIdentifier; -import gnu.io.NoSuchPortException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; - /** * The {@link UrtsiDeviceHandler} is responsible for handling commands, which are * sent to one of the channels. @@ -53,8 +50,6 @@ public class UrtsiDeviceHandler extends BaseBridgeHandler { private final Logger logger = LoggerFactory.getLogger(UrtsiDeviceHandler.class); - private static final String GNU_IO_RXTX_SERIAL_PORTS = "gnu.io.rxtx.SerialPorts"; - private static final int BAUD = 9600; private static final int DATABITS = SerialPort.DATABITS_8; private static final int STOPBIT = SerialPort.STOPBITS_1; @@ -65,13 +60,15 @@ public class UrtsiDeviceHandler extends BaseBridgeHandler { private long lastCommandTime; - private CommPortIdentifier portId; + private SerialPortIdentifier portId; private SerialPort serialPort; + private final SerialPortManager serialPortManager; private OutputStream outputStream; private InputStream inputStream; - public UrtsiDeviceHandler(Bridge bridge) { + public UrtsiDeviceHandler(Bridge bridge, SerialPortManager serialPortManager) { super(bridge); + this.serialPortManager = serialPortManager; } @Override @@ -162,7 +159,7 @@ public void serialEvent(SerialPortEvent event) { Thread.sleep(100); } return !listenerResult.isEmpty(); - } catch (Exception e) { + } catch (IOException | TooManyListenersException | InterruptedException e) { logger.error("Error writing '{}' to serial port {}: {}", msg, portId.getName(), e.getMessage()); } finally { serialPort.removeEventListener(); @@ -170,73 +167,65 @@ public void serialEvent(SerialPortEvent event) { return false; } - /** - * Registers the given port as system property {@value #GNU_IO_RXTX_SERIAL_PORTS}. The method is capable of - * extending the system property, if any other ports are already registered. - * - * @param port the port to be registered - */ - private void initSerialPort(String port) { - String serialPortsProperty = System.getProperty(GNU_IO_RXTX_SERIAL_PORTS); - Set serialPorts = null; - - if (serialPortsProperty != null) { - serialPorts = Stream.of(serialPortsProperty.split(":")).collect(Collectors.toSet()); - } else { - serialPorts = new HashSet<>(); - } - if (serialPorts.add(port)) { - logger.debug("Added {} to the {} system property.", port, GNU_IO_RXTX_SERIAL_PORTS); - System.setProperty(GNU_IO_RXTX_SERIAL_PORTS, serialPorts.stream().collect(Collectors.joining(":"))); - } - } - @Override public void initialize() { address = getThing().getProperties().get("address"); UrtsiDeviceConfig urtsiDeviceConfig = getConfigAs(UrtsiDeviceConfig.class); commandInterval = urtsiDeviceConfig.commandInterval; String port = urtsiDeviceConfig.port; - initSerialPort(port); + + portId = serialPortManager.getIdentifier(port); + + if (portId == null) { + String availablePorts = serialPortManager.getIdentifiers().map(id -> id.getName()) + .collect(Collectors.joining(System.lineSeparator())); + String description = String.format("Serial port '%s' could not be found. Available ports are:%n%s", port, + availablePorts); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, description); + return; + } + try { - portId = CommPortIdentifier.getPortIdentifier(port); - // initialize serial port serialPort = portId.open("openHAB", 2000); - // set port parameters serialPort.setSerialPortParams(BAUD, DATABITS, STOPBIT, PARITY); inputStream = serialPort.getInputStream(); outputStream = serialPort.getOutputStream(); updateStatus(ThingStatus.ONLINE); - } catch (NoSuchPortException e) { - // enumerate the port identifiers in the exception to be helpful - final StringBuilder sb = new StringBuilder(); - @SuppressWarnings("unchecked") - Enumeration portList = CommPortIdentifier.getPortIdentifiers(); - while (portList.hasMoreElements()) { - final CommPortIdentifier id = portList.nextElement(); - if (id.getPortType() == CommPortIdentifier.PORT_SERIAL) { - sb.append(id.getName() + "\n"); - } - } - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Serial port '" + port + "' could not be found. Available ports are:\n" + sb.toString()); - } catch (Exception e) { - if (logger.isErrorEnabled()) { - logger.error("An error occurred while initializing the Urtsi II connection.", e); - } + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error: " + e.getMessage()); + } catch (PortInUseException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Port already used: " + port); + } catch (UnsupportedCommOperationException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "An error occurred while initializing the Urtsi II connection: " + e.getMessage()); + "Unsupported operation on port '" + port + "': " + e.getMessage()); } } @Override public void dispose() { super.dispose(); - IOUtils.closeQuietly(outputStream); - IOUtils.closeQuietly(inputStream); if (serialPort != null) { serialPort.removeEventListener(); + } + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + logger.debug("Error while closing the output stream: {}", e.getMessage()); + } + } + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + logger.debug("Error while closing the input stream: {}", e.getMessage()); + } + } + if (serialPort != null) { serialPort.close(); } + outputStream = null; + inputStream = null; + serialPort = null; } } diff --git a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/mapping/UrtsiChannelMapping.java b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/mapping/UrtsiChannelMapping.java index 613f1f4fcbf3e..d01e0a9d44d66 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/mapping/UrtsiChannelMapping.java +++ b/bundles/org.openhab.binding.urtsi/src/main/java/org/openhab/binding/urtsi/internal/mapping/UrtsiChannelMapping.java @@ -38,5 +38,4 @@ public static String getMappedChannel(String configuredChannel) { } return String.format("%02d", channel); } - } diff --git a/bundles/org.openhab.binding.urtsi/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.urtsi/src/main/resources/ESH-INF/binding/binding.xml index def0a2330d5fd..d5955efc143f2 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.urtsi/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Somfy URTSI II Binding @text/bindingDescription diff --git a/bundles/org.openhab.binding.urtsi/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.urtsi/src/main/resources/ESH-INF/thing/thing-types.xml index 1a69feef58ac3..1358fd3898ff0 100644 --- a/bundles/org.openhab.binding.urtsi/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.urtsi/src/main/resources/ESH-INF/thing/thing-types.xml @@ -1,8 +1,8 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" + xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> @@ -14,6 +14,7 @@ serial-port + false @text/urtsiDevicePortDescription @@ -24,9 +25,9 @@ - + - + @text/rtsDeviceDescription diff --git a/bundles/org.openhab.binding.valloxmv/pom.xml b/bundles/org.openhab.binding.valloxmv/pom.xml index 6c39322249e0c..56bfce35f5d58 100644 --- a/bundles/org.openhab.binding.valloxmv/pom.xml +++ b/bundles/org.openhab.binding.valloxmv/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.valloxmv diff --git a/bundles/org.openhab.binding.valloxmv/src/main/feature/feature.xml b/bundles/org.openhab.binding.valloxmv/src/main/feature/feature.xml index 09cede85d31fc..d0cecf6a468cf 100644 --- a/bundles/org.openhab.binding.valloxmv/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.valloxmv/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.valloxmv/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.valloxmv/${project.version} + diff --git a/bundles/org.openhab.binding.valloxmv/src/main/java/org/openhab/binding/valloxmv/internal/ValloxMVHandler.java b/bundles/org.openhab.binding.valloxmv/src/main/java/org/openhab/binding/valloxmv/internal/ValloxMVHandler.java index 549e7e6a36f75..19f8745b8b147 100644 --- a/bundles/org.openhab.binding.valloxmv/src/main/java/org/openhab/binding/valloxmv/internal/ValloxMVHandler.java +++ b/bundles/org.openhab.binding.valloxmv/src/main/java/org/openhab/binding/valloxmv/internal/ValloxMVHandler.java @@ -90,7 +90,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { || (cmd == ValloxMVBindingConstants.STATE_ATHOME) || (cmd == ValloxMVBindingConstants.STATE_AWAY) || (cmd == ValloxMVBindingConstants.STATE_BOOST)) { - //logger.debug("Changing state to: {}", command); + // logger.debug("Changing state to: {}", command); strUpdateValue = command.toString(); } } catch (NumberFormatException nfe) { @@ -146,7 +146,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override public void initialize() { logger.debug("Initializing thing {}", getThing().getUID()); - + updateStatus(ThingStatus.UNKNOWN); String ip = getConfigAs(ValloxMVConfig.class).getIp(); @@ -160,10 +160,12 @@ public void initialize() { } private void scheduleReadDataJob(int initialDelay) { - if (initialDelay < 0) initialDelay = 0; + if (initialDelay < 0) + initialDelay = 0; readDataInterval = getConfigAs(ValloxMVConfig.class).getUpdateinterval(); - if (readDataInterval < 15) readDataInterval = 60; + if (readDataInterval < 15) + readDataInterval = 60; logger.debug("Data table request interval {} seconds, Request in {} seconds", readDataInterval, initialDelay); @@ -178,7 +180,7 @@ private void cancelReadDataJob() { if (!readDataJob.isDone()) { readDataJob.cancel(true); logger.debug("Scheduled data table requests cancelled"); - } + } } } diff --git a/bundles/org.openhab.binding.valloxmv/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.valloxmv/src/main/resources/ESH-INF/binding/binding.xml index cdd8c4cec3cbc..eda8bfbc1557c 100644 --- a/bundles/org.openhab.binding.valloxmv/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.valloxmv/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,5 @@ - diff --git a/bundles/org.openhab.binding.valloxmv/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.valloxmv/src/main/resources/ESH-INF/thing/thing-types.xml index 18d9241e816cc..66fccd0d11da1 100644 --- a/bundles/org.openhab.binding.valloxmv/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.valloxmv/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,43 +7,43 @@ Interface to online interface of Vallox ventilation unit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -84,7 +84,7 @@ Number:Dimensionless Fan speed in % (0-100) - + @@ -106,7 +106,7 @@ Current temperature inside the building. Temperature - + @@ -114,7 +114,7 @@ Current temperature outside the building. Temperature - + @@ -122,7 +122,7 @@ Current temperature of the air flow exhausting the building. Temperature - + @@ -133,7 +133,7 @@ included in ventilation unit). Temperature - + @@ -141,14 +141,14 @@ Current temperature of the air flow incoming to the building. Temperature - + Number:Dimensionless Current humidity of the air flow exhausting the building. - + @@ -169,70 +169,70 @@ Number Total uptime in years (+ uptime in hours = total uptime) - + Number Total uptime in hours (+ uptime in years = total uptime) - + Number Current uptime in hours - + DateTime Date filter was changed last time - + Number:Time Days until filter has to be changed - + Number:Dimensionless Extract fan base speed in % (0-100) - + Number:Dimensionless Supply fan base speed in % (0-100) - + Number:Dimensionless Home fan speed in % (0-100) - + Number:Dimensionless Away fan speed in % (0-100) - + Number:Dimensionless Boost fan speed in % (0-100) - + @@ -240,7 +240,7 @@ Target temperature in home state Temperature - + @@ -248,7 +248,7 @@ Target temperature in away state Temperature - + @@ -256,14 +256,14 @@ Target temperature in boost state Temperature - + Number:Dimensionless Boost profile timer value in minutes - + @@ -276,21 +276,21 @@ Number:Dimensionless Fireplace profile extract fan speed in % (0-100) - + Number:Dimensionless Fireplace profile supply fan speed in % (0-100) - + Number:Dimensionless Fireplace profile timer value in minutes - + @@ -304,28 +304,28 @@ Target temperature in extra profile Temperature - + Number:Dimensionless Extra profile extract fan speed in % (0-100) - + Number:Dimensionless Extra profile supply fan speed in % (0-100) - + Number:Dimensionless Extra profile timer value in minutes - + diff --git a/bundles/org.openhab.binding.vektiva/pom.xml b/bundles/org.openhab.binding.vektiva/pom.xml index f9d4e7b8e953f..0b3625ec21fef 100644 --- a/bundles/org.openhab.binding.vektiva/pom.xml +++ b/bundles/org.openhab.binding.vektiva/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.reactor.bundles org.openhab.addons.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.vektiva diff --git a/bundles/org.openhab.binding.vektiva/src/main/feature/feature.xml b/bundles/org.openhab.binding.vektiva/src/main/feature/feature.xml index 62fdca5de94bd..2e50910e1885e 100644 --- a/bundles/org.openhab.binding.vektiva/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.vektiva/src/main/feature/feature.xml @@ -1,11 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-http - mvn:org.openhab.addons.bundles/org.openhab.binding.vektiva/${project.version} - + + openhab-runtime-base + openhab-transport-http + mvn:org.openhab.addons.bundles/org.openhab.binding.vektiva/${project.version} + - diff --git a/bundles/org.openhab.binding.vektiva/src/main/java/org/openhab/binding/vektiva/internal/VektivaHandlerFactory.java b/bundles/org.openhab.binding.vektiva/src/main/java/org/openhab/binding/vektiva/internal/VektivaHandlerFactory.java index 74b3700b12eb5..1e35fd59e1fb8 100644 --- a/bundles/org.openhab.binding.vektiva/src/main/java/org/openhab/binding/vektiva/internal/VektivaHandlerFactory.java +++ b/bundles/org.openhab.binding.vektiva/src/main/java/org/openhab/binding/vektiva/internal/VektivaHandlerFactory.java @@ -56,7 +56,8 @@ public class VektivaHandlerFactory extends BaseThingHandlerFactory { private @NonNullByDefault({}) WebSocketClient webSocketClient; @Activate - public VektivaHandlerFactory(@Reference HttpClientFactory httpClientFactory, @Reference WebSocketFactory webSocketFactory) { + public VektivaHandlerFactory(@Reference HttpClientFactory httpClientFactory, + @Reference WebSocketFactory webSocketFactory) { this.httpClient = httpClientFactory.getCommonHttpClient(); this.webSocketClient = webSocketFactory.getCommonWebSocketClient(); } diff --git a/bundles/org.openhab.binding.vektiva/src/main/java/org/openhab/binding/vektiva/internal/handler/VektivaSmarwiHandler.java b/bundles/org.openhab.binding.vektiva/src/main/java/org/openhab/binding/vektiva/internal/handler/VektivaSmarwiHandler.java index 51a82113cfc78..6757ade3ca7b3 100644 --- a/bundles/org.openhab.binding.vektiva/src/main/java/org/openhab/binding/vektiva/internal/handler/VektivaSmarwiHandler.java +++ b/bundles/org.openhab.binding.vektiva/src/main/java/org/openhab/binding/vektiva/internal/handler/VektivaSmarwiHandler.java @@ -12,6 +12,15 @@ */ package org.openhab.binding.vektiva.internal.handler; +import static org.openhab.binding.vektiva.internal.VektivaBindingConstants.*; + +import java.io.IOException; +import java.net.URI; +import java.util.Map; +import java.util.concurrent.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jetty.client.HttpClient; @@ -35,15 +44,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.net.URI; -import java.util.Map; -import java.util.concurrent.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static org.openhab.binding.vektiva.internal.VektivaBindingConstants.*; - /** * The {@link VektivaSmarwiHandler} is responsible for handling commands, which are * sent to one of the channels. @@ -143,14 +143,16 @@ private String getSmarwiCommand(Command command) { return response; } catch (InterruptedException e) { logger.debug("API execution has been interrupted", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "API execution has been interrupted"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "API execution has been interrupted"); Thread.currentThread().interrupt(); } catch (TimeoutException e) { logger.debug("Timeout during API execution", e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Timeout during API execution"); } catch (ExecutionException e) { logger.debug("Exception during API execution", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Exception during API execution: " + e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Exception during API execution: " + e.getMessage()); } return null; } @@ -195,14 +197,16 @@ private void checkStatus() { } } catch (InterruptedException e) { logger.debug("API execution has been interrupted", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "API execution has been interrupted"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "API execution has been interrupted"); Thread.currentThread().interrupt(); } catch (TimeoutException e) { logger.debug("Timeout during status update", e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Timeout during status update"); } catch (ExecutionException e) { logger.debug("Exception during status update", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Exception during status update: " + e.getMessage()); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Exception during status update: " + e.getMessage()); } session = null; } @@ -212,8 +216,8 @@ public synchronized void processStatusResponse(String content) { updateStatus(ThingStatus.ONLINE); } - Map values = Stream.of(content.split("\n")).map(s -> s.split(":")) - .filter(s -> s.length == 2).collect(Collectors.toMap(s -> s[0], s -> s[1])); + Map values = Stream.of(content.split("\n")).map(s -> s.split(":")).filter(s -> s.length == 2) + .collect(Collectors.toMap(s -> s[0], s -> s[1])); updateProperty("Product type", values.getOrDefault("t", NA)); updateProperty(Thing.PROPERTY_FIRMWARE_VERSION, values.getOrDefault("fw", NA)); @@ -254,17 +258,14 @@ public synchronized void processStatusResponse(String content) { return fut.get(); } catch (IOException ex) { logger.debug("Cannot connect websocket client", ex); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Cannot connect websocket client"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Cannot connect websocket client"); } catch (InterruptedException ex) { logger.debug("Cannot create websocket session", ex); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Cannot create websocket session"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Cannot create websocket session"); Thread.currentThread().interrupt(); } catch (ExecutionException ex) { logger.debug("Cannot create websocket session", ex); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Cannot create websocket session"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Cannot create websocket session"); } return null; } diff --git a/bundles/org.openhab.binding.vektiva/src/main/resources/ESH-INF/thing/smarwi.xml b/bundles/org.openhab.binding.vektiva/src/main/resources/ESH-INF/thing/smarwi.xml index d000f479048f6..99bcf9352c674 100644 --- a/bundles/org.openhab.binding.vektiva/src/main/resources/ESH-INF/thing/smarwi.xml +++ b/bundles/org.openhab.binding.vektiva/src/main/resources/ESH-INF/thing/smarwi.xml @@ -10,8 +10,8 @@ Smarwi thing for Vektiva Binding - - + + diff --git a/bundles/org.openhab.binding.velbus/pom.xml b/bundles/org.openhab.binding.velbus/pom.xml index 9b01f6624929f..26c28580f3533 100644 --- a/bundles/org.openhab.binding.velbus/pom.xml +++ b/bundles/org.openhab.binding.velbus/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.velbus diff --git a/bundles/org.openhab.binding.velbus/src/main/feature/feature.xml b/bundles/org.openhab.binding.velbus/src/main/feature/feature.xml index fca4915fd350d..2690835d96e31 100644 --- a/bundles/org.openhab.binding.velbus/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.velbus/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.openhab.addons.bundles/org.openhab.binding.velbus/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.openhab.addons.bundles/org.openhab.binding.velbus/${project.version} + diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/VelbusHandlerFactory.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/VelbusHandlerFactory.java index ac63ea5d2c7fc..6e6a832c471ec 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/VelbusHandlerFactory.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/VelbusHandlerFactory.java @@ -18,6 +18,8 @@ import java.util.Hashtable; import java.util.Map; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; @@ -26,6 +28,7 @@ import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; import org.openhab.binding.velbus.internal.discovery.VelbusThingDiscoveryService; import org.openhab.binding.velbus.internal.handler.VelbusBlindsHandler; import org.openhab.binding.velbus.internal.handler.VelbusBridgeHandler; @@ -36,7 +39,9 @@ import org.openhab.binding.velbus.internal.handler.VelbusVMBGPOHandler; import org.openhab.binding.velbus.internal.handler.VelbusVMBPIROHandler; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link VelbusHandlerFactory} is responsible for creating things and thing @@ -44,9 +49,16 @@ * * @author Cedric Boon - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.velbus") public class VelbusHandlerFactory extends BaseThingHandlerFactory { - private Map> discoveryServiceRegs = new HashMap<>(); + private final Map> discoveryServiceRegs = new HashMap<>(); + private final SerialPortManager serialPortManager; + + @Activate + public VelbusHandlerFactory(final @Reference SerialPortManager serialPortManager) { + this.serialPortManager = serialPortManager; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -54,12 +66,12 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); ThingHandler thingHandler = null; if (BRIDGE_THING_TYPES_UIDS.contains(thingTypeUID)) { - VelbusBridgeHandler velbusBridgeHandler = new VelbusBridgeHandler((Bridge) thing); + VelbusBridgeHandler velbusBridgeHandler = new VelbusBridgeHandler((Bridge) thing, serialPortManager); registerDiscoveryService(velbusBridgeHandler); thingHandler = velbusBridgeHandler; } else if (VelbusRelayHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) { diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusBridgeHandler.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusBridgeHandler.java index ee8ab4e860047..51728f981fafd 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusBridgeHandler.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusBridgeHandler.java @@ -27,15 +27,18 @@ import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.types.Command; +import org.eclipse.smarthome.io.transport.serial.PortInUseException; +import org.eclipse.smarthome.io.transport.serial.SerialPort; +import org.eclipse.smarthome.io.transport.serial.SerialPortEvent; +import org.eclipse.smarthome.io.transport.serial.SerialPortEventListener; +import org.eclipse.smarthome.io.transport.serial.SerialPortIdentifier; +import org.eclipse.smarthome.io.transport.serial.SerialPortManager; +import org.eclipse.smarthome.io.transport.serial.UnsupportedCommOperationException; import org.openhab.binding.velbus.internal.VelbusPacketInputStream; import org.openhab.binding.velbus.internal.VelbusPacketListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import gnu.io.NRSerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; - /** * {@link VelbusBridgeHandler} is the handler for a Velbus Serial-interface and connects it to * the framework. @@ -47,16 +50,18 @@ public class VelbusBridgeHandler extends BaseBridgeHandler implements SerialPort private Logger logger = LoggerFactory.getLogger(VelbusBridgeHandler.class); private static final int BAUD = 9600; - private NRSerialPort serialPort; + private SerialPort serialPort; + private final SerialPortManager serialPortManager; private OutputStream outputStream; private VelbusPacketInputStream inputStream; private long lastPacketTimeMillis; private VelbusPacketListener defaultPacketListener; - private Map packetListeners = new HashMap<>(); + private final Map packetListeners = new HashMap<>(); - public VelbusBridgeHandler(Bridge velbusBridge) { + public VelbusBridgeHandler(Bridge velbusBridge, SerialPortManager serialPortManager) { super(velbusBridge); + this.serialPortManager = serialPortManager; } @Override @@ -69,31 +74,38 @@ public void initialize() { logger.debug("Initializing velbus bridge handler."); String port = (String) getConfig().get(PORT); - if (port != null) { - serialPort = new NRSerialPort(port, BAUD); - if (serialPort.connect()) { - updateStatus(ThingStatus.ONLINE); - logger.debug("Bridge online on serial port {}", port); - - outputStream = serialPort.getOutputStream(); - inputStream = new VelbusPacketInputStream(serialPort.getInputStream()); - - try { - serialPort.addEventListener(this); - serialPort.notifyOnDataAvailable(true); - } catch (TooManyListenersException e) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Failed to register event listener on serial port " + port); - logger.debug("Failed to register event listener on serial port {}", port); - } - } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Failed to connect to serial port " + port); - logger.debug("Failed to connect to serial port {}", port); - } - } else { + if (port == null) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Serial port name not configured"); - logger.debug("Serial port name not configured"); + return; + } + + SerialPortIdentifier serialPortIdentifier = serialPortManager.getIdentifier(port); + if (serialPortIdentifier == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Serial port not found: " + port); + return; + } + + try { + serialPort = serialPortIdentifier.open(VelbusBridgeHandler.class.getCanonicalName(), 2000); + serialPort.setSerialPortParams(BAUD, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); + + inputStream = new VelbusPacketInputStream(serialPort.getInputStream()); + outputStream = serialPort.getOutputStream(); + + serialPort.addEventListener(this); + serialPort.notifyOnDataAvailable(true); + + updateStatus(ThingStatus.ONLINE); + } catch (IOException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Error: " + e.getMessage()); + } catch (PortInUseException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Port already used: " + port); + } catch (TooManyListenersException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Failed to register event listener on serial port: " + port); + } catch (UnsupportedCommOperationException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Unsupported operation on port '" + port + "': " + e.getMessage()); } } @@ -141,7 +153,8 @@ public void unregisterRelayStatusListener(byte address, VelbusPacketListener pac @Override public void dispose() { if (serialPort != null) { - serialPort.disconnect(); + serialPort.removeEventListener(); + serialPort.close(); serialPort = null; } } diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusTemperatureSensorHandler.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusTemperatureSensorHandler.java index 67d1d297f91ea..2f185ff9d11ee 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusTemperatureSensorHandler.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/handler/VelbusTemperatureSensorHandler.java @@ -93,9 +93,9 @@ public void handleCommand(ChannelUID channelUID, Command command) { if (command instanceof RefreshType) { if (channelUID.equals(temperatureChannel)) { sendSensorTemperatureRequest(velbusBridgeHandler); + } } } - } protected void sendSensorTemperatureRequest(VelbusBridgeHandler velbusBridgeHandler) { VelbusSensorTemperatureRequestPacket packet = new VelbusSensorTemperatureRequestPacket( diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindOffPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindOffPacket.java index ecdc4fffc398c..26821e9d25ddc 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindOffPacket.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindOffPacket.java @@ -35,5 +35,4 @@ public VelbusBlindOffPacket(VelbusChannelIdentifier velbusChannelIdentifier) { protected byte[] getDataBytes() { return new byte[] { COMMAND_SWITCH_BLIND_OFF, channel }; } - } diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindPositionPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindPositionPacket.java index f46d190f2fa3b..a111c6cbb7654 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindPositionPacket.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindPositionPacket.java @@ -37,5 +37,4 @@ public VelbusBlindPositionPacket(VelbusChannelIdentifier velbusChannelIdentifier protected byte[] getDataBytes() { return new byte[] { COMMAND_BLIND_POS, channel, percentage }; } - } diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindUpDownPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindUpDownPacket.java index b35637e6ec208..340c9f393c22b 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindUpDownPacket.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusBlindUpDownPacket.java @@ -39,5 +39,4 @@ public VelbusBlindUpDownPacket(VelbusChannelIdentifier velbusChannelIdentifier, protected byte[] getDataBytes() { return new byte[] { command, channel, timeoutHighByte, timeoutMidByte, timeoutLowByte }; } - } diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusChannelNameRequestPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusChannelNameRequestPacket.java index 8e9f61f91d3db..8df7cab1dacf8 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusChannelNameRequestPacket.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusChannelNameRequestPacket.java @@ -31,5 +31,4 @@ public VelbusChannelNameRequestPacket(byte address) { protected byte[] getDataBytes() { return new byte[] { COMMAND_MODULE_NAME_REQUEST, ALL_CHANNELS }; } - } diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusDimmerPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusDimmerPacket.java index fd5be5bb41296..6fb534078acd8 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusDimmerPacket.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusDimmerPacket.java @@ -40,5 +40,4 @@ public VelbusDimmerPacket(VelbusChannelIdentifier velbusChannelIdentifier, byte protected byte[] getDataBytes() { return new byte[] { command, channel, percentage, dimspeedHighByte, dimspeedLowByte }; } - } diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusRelayPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusRelayPacket.java index 8aa299d2f2c3f..89cae62a7cd93 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusRelayPacket.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusRelayPacket.java @@ -35,5 +35,4 @@ public VelbusRelayPacket(VelbusChannelIdentifier velbusChannelIdentifier, byte c protected byte[] getDataBytes() { return new byte[] { command, channel }; } - } diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusScanPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusScanPacket.java index f0cb90b918154..7bf421dc5bd07 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusScanPacket.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusScanPacket.java @@ -29,5 +29,4 @@ public VelbusScanPacket(byte address) { protected byte[] getDataBytes() { return new byte[0]; } - } diff --git a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusStatusRequestPacket.java b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusStatusRequestPacket.java index df8182bfdb488..1fcc54c51af65 100644 --- a/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusStatusRequestPacket.java +++ b/bundles/org.openhab.binding.velbus/src/main/java/org/openhab/binding/velbus/internal/packets/VelbusStatusRequestPacket.java @@ -41,5 +41,4 @@ public VelbusStatusRequestPacket(VelbusChannelIdentifier velbusChannelIdentifier protected byte[] getDataBytes() { return new byte[] { COMMAND_STATUS_REQUEST, channel }; } - } diff --git a/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/binding/binding.xml index 0091815bc7e91..9e5afc0333bb4 100644 --- a/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - Velbus Binding diff --git a/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/config/config.xml index 9eac44d9345cf..72ba8a2cd8f34 100644 --- a/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/config/config.xml @@ -7,6 +7,7 @@ serial-port + false Select serial port (COM1, /dev/ttyS0, ...) true @@ -267,7 +268,8 @@ - Refresh interval for the temperature sensor (in seconds), default 300. If set to 0 or left empty, no refresh will be scheduled. + Refresh interval for the temperature sensor (in seconds), default 300. If set to 0 or left empty, no + refresh will be scheduled. 300 true @@ -334,7 +336,8 @@ - Refresh interval for the temperature sensor (in seconds), default 300. If set to 0 or left empty, no refresh will be scheduled. + Refresh interval for the temperature sensor (in seconds), default 300. If set to 0 or left empty, no + refresh will be scheduled. 300 true diff --git a/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/thing/thing-types.xml index 7234660255c28..52942d194e21f 100644 --- a/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.velbus/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,620 +7,613 @@ This bridge represents a Velbus Serial-interface - + - + 1-channel blind control module for universal mounting - + - + - + Dimmer module for inductive/resistive and capacitive load - + - + - + 1-channel 0-10V controlled PWM dimmer for led strips - + - + - + 1-channel relay module - + - + - + 1-channel relay module with potential-free changeover contact - - - - - + + + + + - + - + 1-channel relay module with potential-free changeover contact - - - - - + + + + + - + - + 2-channel blind control module with extended possibilities - - + + - + - + Push-button interface for Niko 1- or 2-fold push-buttons - - - - - - - - + + + + + + + + - + - + 4-channel 0/1-10V dimmer controller - - - - + + + + - + - + 4-channel relay module - - - - + + + + - + - + 4-channel relay module with voltage outputs - - - - - + + + + + - + - + 4-channel relay module with potential-free contacts - - - - - + + + + + - + - + 6-channel input module - - - - - - + + + + + + - + - + Push-button interface module for Niko 4- or 6-fold push-button - - - - - - - - + + + + + + + + - + - + 7-channel input module (potentialfree + pulse) - - - - - - - - + + + + + + + + - + - + Infrared remote control receiver module - - - - - - - - + + + + + + + + - + - + 8-Channel Push Button module - - - - - - - - + + + + + + + + - + - + Push-button interface with 8 channels for universal mounting - - - - - - - - + + + + + + + + - + - + Dimmer for electronic/resistive load - + - + - + Single channel triac dimmer for resistive and inductive loads - + - + - + Single channel triac dimmer for resistive and inductive loads - + - + - + Glass control module with 1 touch key - - - - - - - - - + + + + + + + + + - + - + Glass control module with 2 touch keys - - - - - - - - - + + + + + + + + + - + - + Glass control module with 4 touch keys - - - - - - - - - + + + + + + + + + - + - + Glass control module with 4 touch keys and built-in motion and twilight sensor - - - - - - - - - + + + + + + + + + - + - + Glass control module with oled display - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + Glass control module with oled display and temperature controller - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + Motion and twilight sensor for ceiling mounting - - - - - - - + + + + + + + - + - + Mini motion and twilight sensor for recessed or surface mounting - - - - - - - + + + + + + + - + - + Outdoor motion, twilight and temperature sensor, Theben - - - - - - - - - + + + + + + + + + - + diff --git a/bundles/org.openhab.binding.velux/pom.xml b/bundles/org.openhab.binding.velux/pom.xml index 6ab9eca28fe7e..b59b8040830f0 100644 --- a/bundles/org.openhab.binding.velux/pom.xml +++ b/bundles/org.openhab.binding.velux/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.velux diff --git a/bundles/org.openhab.binding.velux/src/main/feature/feature.xml b/bundles/org.openhab.binding.velux/src/main/feature/feature.xml index 75a556b51b850..a810424efdfad 100644 --- a/bundles/org.openhab.binding.velux/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.velux/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.velux/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.velux/${project.version} + diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBinding.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBinding.java index fbcdaa68abbc0..c213dffc2b6f0 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBinding.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBinding.java @@ -120,5 +120,4 @@ public VeluxBridgeConfiguration checked() { logger.trace("checked() done."); return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConfig.java index f05d437a2df41..a8a21e9238fe9 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConfig.java @@ -86,5 +86,4 @@ public VeluxItemType getBindingItemType() { public String getBindingConfig() { return this.bindingConfig; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java index 6992a5bd05577..349c0b67f8965 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingConstants.java @@ -145,5 +145,4 @@ public class VeluxBindingConstants { // Critical issues to be reported will use the following message public static final String LOGGING_CONTACT = "Please report to maintainer: "; - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingProperties.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingProperties.java index 1e71a932214a6..5d1f041c5f3c2 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingProperties.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxBindingProperties.java @@ -57,5 +57,4 @@ public class VeluxBindingProperties { public static final String PROPERTY_VSHUTTER_SCENELEVELS = "sceneLevels"; public static final String PROPERTY_VSHUTTER_CURRENTLEVEL = "currentLevel"; - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxItemType.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxItemType.java index 25e83042a2d21..76266d5f4f569 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxItemType.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxItemType.java @@ -495,5 +495,4 @@ public static boolean isToBeRefreshedNow(int refreshCycleCounter, ThingTypeUID t } return false; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxRSBindingConfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxRSBindingConfig.java index 1469dd1b38320..4932027213367 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxRSBindingConfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/VeluxRSBindingConfig.java @@ -18,7 +18,6 @@ import java.util.TreeMap; import org.eclipse.jdt.annotation.NonNullByDefault; -//import org.openhab.model.item.binding.BindingConfigParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -153,7 +152,6 @@ public Integer getNextAscendingLevel() { } logger.trace("getNextAscendingLevel() returning {}.", this.rollershutterLevel); return this.rollershutterLevel; - } /** @@ -172,7 +170,6 @@ public Integer getNextDescendingLevel() { } logger.trace("getNextDescendingLevel() returning {}.", this.rollershutterLevel); return this.rollershutterLevel; - } /** diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridge.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridge.java index 6471e33f06f4a..4aef0887da169 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridge.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridge.java @@ -280,5 +280,4 @@ public long lastSuccessfulCommunication() { */ protected abstract boolean bridgeDirectCommunicate(BridgeCommunicationProtocol communication, boolean useAuthentication); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeActuators.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeActuators.java index 8193fd2af431f..b09ddbf56844e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeActuators.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeActuators.java @@ -164,5 +164,4 @@ public boolean autoRefresh(VeluxBridge bridge) { } return (numberOfActuators > 0); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeDeviceStatus.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeDeviceStatus.java index 303bd36b1e2ef..2fb4583711e44 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeDeviceStatus.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeDeviceStatus.java @@ -105,5 +105,4 @@ public Channel retrieve(VeluxBridge bridge) { } return channel; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetFirmware.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetFirmware.java index ae3d62f36d1b9..441c6206cf70e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetFirmware.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetFirmware.java @@ -101,5 +101,4 @@ public Channel retrieve(VeluxBridge bridge) { } return channel; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetHouseStatus.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetHouseStatus.java index 745ae6694b781..c7e8256e5ec30 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetHouseStatus.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetHouseStatus.java @@ -58,5 +58,4 @@ public boolean evaluateState(VeluxBridge bridge) { logger.debug("evaluateState() finished {}.", (success ? "successfully" : "with failure")); return success; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetLimitation.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetLimitation.java index 2e7a05fbafac1..e4dc30913223b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetLimitation.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeGetLimitation.java @@ -100,5 +100,4 @@ public boolean getMaximumLimitation(VeluxBridge bridge, int nodeId) { public VeluxProductPosition getLimitation() { return limitationResult; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeInstance.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeInstance.java index edac94e74c4ae..3ba678ba3bd35 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeInstance.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeInstance.java @@ -65,5 +65,4 @@ public interface VeluxBridgeInstance { * @return VeluxExistingScenes containing all registered scenes, or null in case of any error. */ public VeluxExistingScenes existingScenes(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeProvider.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeProvider.java index 5339554b6bfa3..f1cb151c98488 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeProvider.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeProvider.java @@ -55,5 +55,4 @@ public interface VeluxBridgeProvider { * containing all API methods. */ public @Nullable BridgeAPI bridgeAPI(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeRunProductCommand.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeRunProductCommand.java index 91c98bdc2c091..968af79899e4a 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeRunProductCommand.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeRunProductCommand.java @@ -60,5 +60,4 @@ public boolean sendCommand(VeluxBridge bridge, int nodeId, VeluxProductPosition logger.debug("sendCommand() finished {}.", (success ? "successfully" : "with failure")); return success; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeRunScene.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeRunScene.java index c4509699b3f8c..926caa0d17952 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeRunScene.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeRunScene.java @@ -74,5 +74,4 @@ public boolean execute(VeluxBridge bridge, int sceneNo, int velocity) { return false; } } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeScenes.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeScenes.java index 4cee44d2b7864..ae82277c19728 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeScenes.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeScenes.java @@ -126,5 +126,4 @@ public boolean autoRefresh(VeluxBridge bridge) { } return (channel.existingScenes.getNoMembers() > 0); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeSetHouseStatusMonitor.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeSetHouseStatusMonitor.java index 6e508b981e27f..f6e67bf671b2e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeSetHouseStatusMonitor.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeSetHouseStatusMonitor.java @@ -59,5 +59,4 @@ public boolean modifyHSM(VeluxBridge bridge, boolean enableService) { logger.debug("modifyHSM() finished {}.", (success ? "successfully" : "with failure")); return success; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeSetLimitation.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeSetLimitation.java index ffae910c35f42..d6a1264bd1750 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeSetLimitation.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeSetLimitation.java @@ -90,5 +90,4 @@ public boolean setMaximumLimitation(VeluxBridge bridge, int nodeId, VeluxProduct logger.trace("setMaximumLimitation() finished with failure."); return false; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeWLANConfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeWLANConfig.java index 7949844d47b11..88703030a82de 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeWLANConfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/VeluxBridgeWLANConfig.java @@ -105,5 +105,4 @@ public Channel retrieve(VeluxBridge bridge) { } return channel; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/BridgeAPI.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/BridgeAPI.java index fe89f92816c61..2807983fbac44 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/BridgeAPI.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/BridgeAPI.java @@ -104,5 +104,4 @@ public interface BridgeAPI { SetSceneVelocity setSceneVelocity(); RunScene runScene(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/BridgeCommunicationProtocol.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/BridgeCommunicationProtocol.java index c71e26b602379..3f458549b18ef 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/BridgeCommunicationProtocol.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/BridgeCommunicationProtocol.java @@ -48,5 +48,4 @@ public interface BridgeCommunicationProtocol { * @return true if the communication was successful, and false otherwise. */ public boolean isCommunicationSuccessful(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetFirmware.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetFirmware.java index b1e1fc6398b49..a04a226934a21 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetFirmware.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetFirmware.java @@ -39,5 +39,4 @@ public abstract class GetFirmware implements BridgeCommunicationProtocol { * @return firmware as VeluxGwFirmware describing the current software of the bridge. */ public abstract VeluxGwFirmware getFirmware(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetLANConfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetLANConfig.java index f65d55d49822f..8ef2a64ca0795 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetLANConfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetLANConfig.java @@ -39,5 +39,4 @@ public abstract class GetLANConfig implements BridgeCommunicationProtocol { * @return lanConfig as VeluxGwLAN describing the current status of the bridge. */ public abstract VeluxGwLAN getLANConfig(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProduct.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProduct.java index 43fc41f0bc208..b3a2baf7b185a 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProduct.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProduct.java @@ -47,5 +47,4 @@ public abstract class GetProduct implements BridgeCommunicationProtocol { * @return veluxProduct as VeluxProduct. */ public abstract VeluxProduct getProduct(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProductLimitation.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProductLimitation.java index 7c4d464633aa8..b8ad49a35bf9b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProductLimitation.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProductLimitation.java @@ -47,5 +47,4 @@ public abstract class GetProductLimitation implements BridgeCommunicationProtoco * @return limitation as int. */ public abstract int getLimitation(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProducts.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProducts.java index 73f5d31661f42..73612f45082d8 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProducts.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetProducts.java @@ -40,5 +40,4 @@ public abstract class GetProducts implements BridgeCommunicationProtocol { * @return arrayOfVeluxProducts as Array of VeluxProduct. */ public abstract VeluxProduct[] getProducts(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetScenes.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetScenes.java index eb94d8d0eec16..5d84410d9afad 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetScenes.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/GetScenes.java @@ -39,5 +39,4 @@ public abstract class GetScenes implements BridgeCommunicationProtocol { * @return arrayOfScenes as Array of VeluxScene describing the current scene configuration of the bridge. */ public abstract VeluxScene[] getScenes(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/Login.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/Login.java index d2eefeb074d0c..2e3c0f086a616 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/Login.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/Login.java @@ -49,5 +49,4 @@ public void setPassword(String thisPassword) { public String getAuthToken() { return ""; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunProductCommand.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunProductCommand.java index e70247b0a9913..990500c05486d 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunProductCommand.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunProductCommand.java @@ -40,5 +40,4 @@ public abstract class RunProductCommand implements BridgeCommunicationProtocol { * @return reference to the class instance. */ public abstract RunProductCommand setNodeAndMainParameter(int actuatorId, int parameterValue); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunProductIdentification.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunProductIdentification.java index 5b7c813c7791f..981fca20822e2 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunProductIdentification.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunProductIdentification.java @@ -41,5 +41,4 @@ public abstract class RunProductIdentification implements BridgeCommunicationPro public RunProductIdentification setProductId(int id) { return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunScene.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunScene.java index 4c31645a087b1..3cd2e1c4cc26e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunScene.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/RunScene.java @@ -51,5 +51,4 @@ public RunScene setSceneId(int id) { public RunScene setVelocity(int velocity) { return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetHouseStatusMonitor.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetHouseStatusMonitor.java index 26f7c6f8f64ad..ba18be576af94 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetHouseStatusMonitor.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetHouseStatusMonitor.java @@ -39,5 +39,4 @@ public abstract class SetHouseStatusMonitor implements BridgeCommunicationProtoc * @return reference to the class instance. */ public abstract SetHouseStatusMonitor serviceActivation(boolean enableService); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetProductLimitation.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetProductLimitation.java index ccf6c66a67d56..da0920b16112b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetProductLimitation.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetProductLimitation.java @@ -50,5 +50,4 @@ public abstract class SetProductLimitation implements BridgeCommunicationProtoco * @param limitationMaximum Maximum Restriction value. */ public abstract void setActuatorIdAndMaximumLimitation(int nodeId, int limitationMaximum); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetSceneVelocity.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetSceneVelocity.java index df54d191c1d82..40da6cec51f4e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetSceneVelocity.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/common/SetSceneVelocity.java @@ -33,5 +33,4 @@ public abstract class SetSceneVelocity implements BridgeCommunicationProtocol { public abstract SetSceneVelocity setMode(int id, boolean silent); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetDeviceStatus.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetDeviceStatus.java index a6a6d32368d1f..77e3d668c405d 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetDeviceStatus.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetDeviceStatus.java @@ -166,5 +166,4 @@ public VeluxGwState getState() { } return new VeluxGwState(stateValue, subStateValue); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetFirmware.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetFirmware.java index 5cfd49e1560ac..76b52c0026962 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetFirmware.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetFirmware.java @@ -162,5 +162,4 @@ public VeluxGwFirmware getFirmware() { VeluxGwFirmware gwFirmware = new VeluxGwFirmware(response.data.version); return gwFirmware; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetLANConfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetLANConfig.java index 267c6b8345274..14165afb473ed 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetLANConfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetLANConfig.java @@ -186,5 +186,4 @@ public VeluxGwLAN getLANConfig() { response.data.defaultGateway, response.data.dhcp); return gwLAN; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetProducts.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetProducts.java index e30b67d30f90f..b70c6566f608f 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetProducts.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetProducts.java @@ -193,5 +193,4 @@ public VeluxProduct[] getProducts() { } return products; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetScenes.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetScenes.java index 45e8b5e0bb272..284a28579d4ad 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetScenes.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetScenes.java @@ -226,5 +226,4 @@ public VeluxScene[] getScenes() { } return scenes; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetWLANConfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetWLANConfig.java index 694a7e1ba7a5f..0831033dbf646 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetWLANConfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCgetWLANConfig.java @@ -181,5 +181,4 @@ public VeluxGwWLAN getWLANConfig() { VeluxGwWLAN gwWLAN = new VeluxGwWLAN(response.data.name, response.data.password); return gwWLAN; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogin.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogin.java index 535b28db70b8b..862f321889c3d 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogin.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogin.java @@ -167,5 +167,4 @@ public void setPassword(String thisPassword) { public String getAuthToken() { return response.getToken(); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogout.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogout.java index e080cba4a4128..62f788d2108d4 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogout.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JClogout.java @@ -133,5 +133,4 @@ public String getDeviceStatus() { public String[] getErrors() { return response.errors; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunProductDiscovery.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunProductDiscovery.java index 1957cfb2d4da9..4f01d18c63178 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunProductDiscovery.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunProductDiscovery.java @@ -155,5 +155,4 @@ public String getDeviceStatus() { public String[] getErrors() { return response.getErrors(); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunProductSearch.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunProductSearch.java index c0f09b2455ffa..df42711c8aa71 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunProductSearch.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunProductSearch.java @@ -100,7 +100,6 @@ private static class Response { @SuppressWarnings("unused") private String[] data = {}; private String[] errors = {}; - } /* @@ -146,5 +145,4 @@ public String getDeviceStatus() { public String[] getErrors() { return response.errors; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunScene.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunScene.java index a7cab20b2547b..bc44755990226 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunScene.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCrunScene.java @@ -153,5 +153,4 @@ public JCrunScene setSceneId(int id) { request.params.id = id; return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCsetSceneVelocity.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCsetSceneVelocity.java index e463aca5894ee..6b5073b11bfce 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCsetSceneVelocity.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JCsetSceneVelocity.java @@ -165,5 +165,4 @@ public JCsetSceneVelocity setMode(int id, boolean silent) { JCsetSceneVelocity.silentMode = silent; return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeAPI.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeAPI.java index fdf452c511566..f8e37775978f0 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeAPI.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeAPI.java @@ -205,5 +205,4 @@ public RunScene runScene() { public SetSceneVelocity setSceneVelocity() { return SETSCENEVELOCITY; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeCommunicationProtocol.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeCommunicationProtocol.java index 59f77ab20202b..da66ac0eba6fb 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeCommunicationProtocol.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonBridgeCommunicationProtocol.java @@ -89,5 +89,4 @@ interface JsonBridgeCommunicationProtocol extends BridgeCommunicationProtocol { * @return errors as String[] describing the status of the operation according to the request in depth. */ String[] getErrors(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonVeluxBridge.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonVeluxBridge.java index 8090f1e311f45..e691f0a4aaee7 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonVeluxBridge.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/json/JsonVeluxBridge.java @@ -318,5 +318,4 @@ private T ioUnauthenticated(String url, U request, Class classOfRespon throws JsonSyntaxException, IOException { return io(url, "", request, classOfResponse); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetDeviceStatus.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetDeviceStatus.java index 7ced9a1202c8c..a8033c3127dc6 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetDeviceStatus.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetDeviceStatus.java @@ -148,5 +148,4 @@ public VeluxGwState getState() { logger.trace("getState() returns {} ({}).", thisGwState, thisGwState.toDescription()); return thisGwState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetFirmware.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetFirmware.java index 83ae94889c091..73a83177fb87e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetFirmware.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetFirmware.java @@ -161,5 +161,4 @@ public VeluxGwFirmware getFirmware() { logger.trace("getFirmware() returns {}.", result); return new VeluxGwFirmware(result); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetHouseStatus.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetHouseStatus.java index e67458b1438b7..0500fd2e02103 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetHouseStatus.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetHouseStatus.java @@ -180,5 +180,4 @@ public int getNtfCurrentPosition() { public int getNtfTarget() { return ntfTarget; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetLANConfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetLANConfig.java index 38099fae545ea..719e88bde7caf 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetLANConfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetLANConfig.java @@ -149,5 +149,4 @@ public VeluxGwLAN getLANConfig() { logger.debug("getLANConfig() returns {}.", result); return result; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetLimitation.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetLimitation.java index 84b7966d9bbaf..22f00493625a2 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetLimitation.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetLimitation.java @@ -296,5 +296,4 @@ public void setActuatorIdAndLimitationType(int nodeId, boolean limitationMinimum public int getLimitation() { return limitationValue; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetProduct.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetProduct.java index b810f96346ece..03b54d81e8253 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetProduct.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetProduct.java @@ -264,5 +264,4 @@ public VeluxProduct getProduct() { logger.trace("getProduct(): returning product {}.", product); return product; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetProducts.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetProducts.java index 31cc6862c4101..af9e19557bfaf 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetProducts.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetProducts.java @@ -272,5 +272,4 @@ public VeluxProduct[] getProducts() { return new VeluxProduct[0]; } } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetScenes.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetScenes.java index 6499c5f4c50e7..1169189fe3d67 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetScenes.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetScenes.java @@ -16,10 +16,10 @@ import org.openhab.binding.velux.internal.bridge.common.GetScenes; import org.openhab.binding.velux.internal.bridge.slip.utils.KLF200Response; import org.openhab.binding.velux.internal.bridge.slip.utils.Packet; -import org.openhab.binding.velux.internal.things.VeluxProductState; -import org.openhab.binding.velux.internal.things.VeluxScene; import org.openhab.binding.velux.internal.things.VeluxKLFAPI.Command; import org.openhab.binding.velux.internal.things.VeluxKLFAPI.CommandNumber; +import org.openhab.binding.velux.internal.things.VeluxProductState; +import org.openhab.binding.velux.internal.things.VeluxScene; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -171,5 +171,4 @@ public VeluxScene[] getScenes() { logger.trace("getScenes(): returning {} scenes.", scenes.length); return scenes; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetWLANConfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetWLANConfig.java index 532544e8dae85..d496cc12f9023 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetWLANConfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCgetWLANConfig.java @@ -120,5 +120,4 @@ public VeluxGwWLAN getWLANConfig() { // Enhancement idea: Velux should provide an enhanced API. return new VeluxGwWLAN(UNSUPPORTED, UNSUPPORTED); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SClogin.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SClogin.java index f0c87007bcb31..951dcc39a6ac6 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SClogin.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SClogin.java @@ -162,5 +162,4 @@ public String getAuthToken() { logger.trace("getAuthToken() called, returning {}.", reqPassword.replaceAll(".", "*")); return reqPassword; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SClogout.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SClogout.java index 2090ddcad7693..e573ac4764056 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SClogout.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SClogout.java @@ -98,5 +98,4 @@ public boolean isCommunicationFinished() { public boolean isCommunicationSuccessful() { return success; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductCommand.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductCommand.java index da54c23d71bcf..95b66a2481d2c 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductCommand.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductCommand.java @@ -309,5 +309,4 @@ public SCrunProductCommand setNodeAndMainParameter(int nodeId, int value) { this.reqMainParameter = value; return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductDiscovery.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductDiscovery.java index dbbb97d1bbae7..9b89ed4422ea9 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductDiscovery.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductDiscovery.java @@ -150,5 +150,4 @@ public boolean isCommunicationFinished() { public boolean isCommunicationSuccessful() { return success; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductIdentification.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductIdentification.java index 1b62afa82ed25..069cbfb63a69b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductIdentification.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductIdentification.java @@ -200,5 +200,4 @@ public SCrunProductIdentification setProductId(int actuatorId) { this.reqIndexValue0 = actuatorId; return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductSearch.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductSearch.java index ee10d5e57d7bf..bc4843d903f82 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductSearch.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunProductSearch.java @@ -109,5 +109,4 @@ public VeluxGwState getState() { logger.trace("getState() returns {} ({}).", thisGwState, thisGwState.toDescription()); return thisGwState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunScene.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunScene.java index 8a221aee1960e..6d43d872a2d6c 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunScene.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCrunScene.java @@ -287,5 +287,4 @@ public SCrunScene setVelocity(int velocity) { this.reqVelocity = velocity; return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetHouseStatusMonitor.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetHouseStatusMonitor.java index a7d4ec71e3186..b7d2f4840bad8 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetHouseStatusMonitor.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetHouseStatusMonitor.java @@ -141,5 +141,4 @@ public SetHouseStatusMonitor serviceActivation(boolean enableService) { this.activateService = enableService; return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetLimitation.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetLimitation.java index 6f6626be6498f..e904d7792ab02 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetLimitation.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetLimitation.java @@ -316,5 +316,4 @@ public void setActuatorIdAndResetLimitation(int nodeId) { reqLimitationValueMax = VeluxProductPosition.VPP_VELUX_IGNORE; return; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetSceneVelocity.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetSceneVelocity.java index 9c0964f9c722e..da21d829e9f8a 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetSceneVelocity.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SCsetSceneVelocity.java @@ -16,9 +16,9 @@ import org.openhab.binding.velux.internal.bridge.common.SetSceneVelocity; import org.openhab.binding.velux.internal.bridge.slip.utils.KLF200Response; import org.openhab.binding.velux.internal.bridge.slip.utils.Packet; -import org.openhab.binding.velux.internal.things.VeluxProductVelocity; import org.openhab.binding.velux.internal.things.VeluxKLFAPI.Command; import org.openhab.binding.velux.internal.things.VeluxKLFAPI.CommandNumber; +import org.openhab.binding.velux.internal.things.VeluxProductVelocity; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -171,5 +171,4 @@ public SCsetSceneVelocity setMode(int actuatorId, boolean silent) { : VeluxProductVelocity.FAST.getVelocity(); return this; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeAPI.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeAPI.java index c2e6d652bd1fc..5d9084d398316 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeAPI.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeAPI.java @@ -210,5 +210,4 @@ public RunScene runScene() { public SetSceneVelocity setSceneVelocity() { return SETSCENEVELOCITY; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeCommunicationProtocol.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeCommunicationProtocol.java index 265cc719eb223..f3164174e2550 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeCommunicationProtocol.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipBridgeCommunicationProtocol.java @@ -81,5 +81,4 @@ interface SlipBridgeCommunicationProtocol extends BridgeCommunicationProtocol { * is a boolean signaling the end of this transaction. */ public boolean isCommunicationFinished(); - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipVeluxBridge.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipVeluxBridge.java index 37aebce1e5d9f..d7f7372485202 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipVeluxBridge.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/SlipVeluxBridge.java @@ -381,5 +381,4 @@ private synchronized boolean bridgeDirectCommunicate(SlipBridgeCommunicationProt logger.debug("bridgeDirectCommunicate({}) returns {}.", commandString, success ? "success" : "failure"); return success; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/Connection.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/Connection.java index 634c5cafb67c4..a42d7a12c3c9e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/Connection.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/Connection.java @@ -237,5 +237,4 @@ public synchronized void resetConnection() { } logger.trace("resetConnection() done."); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/DataInputStreamWithTimeout.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/DataInputStreamWithTimeout.java index 1a2db47e5c31e..967277e0f21fd 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/DataInputStreamWithTimeout.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/DataInputStreamWithTimeout.java @@ -131,7 +131,5 @@ public Integer call() throws IOException { } catch (TimeoutException e) { throw new IOException("read timeout", e); } - } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/SSLconnection.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/SSLconnection.java index b1c177b1ac3c0..d53ea05943af0 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/SSLconnection.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/io/SSLconnection.java @@ -254,5 +254,4 @@ void setTimeout(int timeoutMSecs) { logger.debug("setTimeout() set timeout to {} milliseconds.", timeoutMSecs); ioTimeoutMSecs = timeoutMSecs; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/Packet.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/Packet.java index b351d0e05ee16..01e556245d48b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/Packet.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/Packet.java @@ -276,5 +276,4 @@ public static String intToIPAddressString(int ipAddress) { return String.format("%d.%d.%d.%d", ((ipAddress >>> 24) & 0xFF), ((ipAddress >>> 16) & 0xFF), ((ipAddress >>> 8) & 0xFF), (ipAddress & 0xFF)); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipEncoding.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipEncoding.java index afe9b6564518c..7047780229646 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipEncoding.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipEncoding.java @@ -166,5 +166,4 @@ public byte[] toMessage() { public String toString() { return new Packet(message).toString(); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipRFC1055.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipRFC1055.java index accc7eccad750..04150f0f50db6 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipRFC1055.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/bridge/slip/utils/SlipRFC1055.java @@ -122,5 +122,4 @@ public byte[] decode(byte[] packet) throws ParseException { logger.trace("decode() provides payload: {}.", new Packet(payload)); return payload; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/discovery/VeluxDiscoveryService.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/discovery/VeluxDiscoveryService.java index 081ebd25ee378..67db07c6bc120 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/discovery/VeluxDiscoveryService.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/discovery/VeluxDiscoveryService.java @@ -269,5 +269,4 @@ private void discoverProducts() { } logger.trace("discoverProducts() finished."); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/factory/VeluxHandlerFactory.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/factory/VeluxHandlerFactory.java index d0c14e0f4943f..01c4acc71aceb 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/factory/VeluxHandlerFactory.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/factory/VeluxHandlerFactory.java @@ -73,7 +73,6 @@ private void registerDeviceDiscoveryService(VeluxBridgeHandler bridgeHandler) { ServiceRegistration discoveryServiceReg = bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()); discoveryServiceRegistrations.put(bridgeHandler.getThing().getUID(), discoveryServiceReg); - } // Even if the compiler tells, that the value of cannot be null, it is possible! @@ -131,7 +130,6 @@ public VeluxHandlerFactory(final @Reference LocaleProvider givenLocaleProvider, logger.trace("VeluxHandlerFactory(locale={},translation={}) called.", givenLocaleProvider, givenI18nProvider); localeProvider = givenLocaleProvider; i18nProvider = givenI18nProvider; - } @Reference @@ -203,5 +201,4 @@ protected void removeHandler(ThingHandler thingHandler) { updateBindingState(); super.removeHandler(thingHandler); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/BridgeChannels.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/BridgeChannels.java index 41d09acda4059..86f0e888de12b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/BridgeChannels.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/BridgeChannels.java @@ -98,5 +98,4 @@ static Set getAllLinkedChannelUIDs(ExtendedBaseBridgeHandler bridge) LOGGER.trace("getAllLinkedChannelUIDs() returns {}.", channelUIDs); return channelUIDs; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelActuatorLimitation.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelActuatorLimitation.java index 27a9e5d39b637..58730a1671234 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelActuatorLimitation.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelActuatorLimitation.java @@ -206,5 +206,4 @@ private ChannelActuatorLimitation() { return newValue; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelActuatorPosition.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelActuatorPosition.java index 6b3134ca16dc6..8e07626445ee6 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelActuatorPosition.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelActuatorPosition.java @@ -175,5 +175,4 @@ private ChannelActuatorPosition() { } while (false); // common exit return newValue; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeCheck.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeCheck.java index 0e391ba8b22dc..365cbc057cb42 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeCheck.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeCheck.java @@ -112,5 +112,4 @@ private ChannelBridgeCheck() { } while (false); // common exit return newState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeDoDetection.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeDoDetection.java index 1617df3c13086..6842005fd9c76 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeDoDetection.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeDoDetection.java @@ -74,5 +74,4 @@ private ChannelBridgeDoDetection() { } return null; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeFirmware.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeFirmware.java index 40a89c8460003..8eb20413b0875 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeFirmware.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeFirmware.java @@ -68,5 +68,4 @@ private ChannelBridgeFirmware() { LOGGER.trace("handleRefresh() returns {}.", newState); return newState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeLANconfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeLANconfig.java index b50fdeede3b5f..546e9035a5b59 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeLANconfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeLANconfig.java @@ -96,5 +96,4 @@ private ChannelBridgeLANconfig() { LOGGER.trace("handleRefresh() returns {}.", newState); return newState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeProducts.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeProducts.java index 4abe789afa620..6f6635731a270 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeProducts.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeProducts.java @@ -70,5 +70,4 @@ private ChannelBridgeProducts() { LOGGER.trace("handleRefresh() returns {}.", newState); return newState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeScenes.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeScenes.java index 126306b891aff..69f4bb1525eae 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeScenes.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeScenes.java @@ -70,5 +70,4 @@ private ChannelBridgeScenes() { LOGGER.trace("handleRefresh() returns {}.", newState); return newState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeStatus.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeStatus.java index 22f59948e5f53..c4935855f8f5b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeStatus.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeStatus.java @@ -68,5 +68,4 @@ private ChannelBridgeStatus() { LOGGER.trace("handleRefresh() returns {}.", newState); return newState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeWLANconfig.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeWLANconfig.java index 5d542e00c9b3f..19abcce77a60c 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeWLANconfig.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelBridgeWLANconfig.java @@ -86,5 +86,4 @@ private ChannelBridgeWLANconfig() { LOGGER.trace("handleRefresh() returns {}.", newState); return newState; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelHandlerTemplate.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelHandlerTemplate.java index 6f23e63462f58..5a464136e2cbb 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelHandlerTemplate.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelHandlerTemplate.java @@ -68,5 +68,4 @@ abstract class ChannelHandlerTemplate { VeluxBridgeHandler thisBridgeHandler) { throw new IllegalStateException("handleRefresh hasn't been set up in the subclass"); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelSceneAction.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelSceneAction.java index 07bc016d3dafd..21a75ecab937b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelSceneAction.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelSceneAction.java @@ -118,5 +118,4 @@ private ChannelSceneAction() { } while (false); // common exit return newValue; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelSceneSilentmode.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelSceneSilentmode.java index 89f3d204ba91a..da19e4c0e0c71 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelSceneSilentmode.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelSceneSilentmode.java @@ -98,5 +98,4 @@ private ChannelSceneSilentmode() { } while (false); // common exit return newValue; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelVShutterPosition.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelVShutterPosition.java index 35cdfddad01da..50ce83cf0c3a5 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelVShutterPosition.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/ChannelVShutterPosition.java @@ -164,5 +164,4 @@ private ChannelVShutterPosition() { LOGGER.trace("handleCommand() returns {}.", newValue); return newValue; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/PropertyHandlerTemplate.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/PropertyHandlerTemplate.java index c9ff9047a0857..c3763f8b91ce1 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/PropertyHandlerTemplate.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/PropertyHandlerTemplate.java @@ -46,5 +46,4 @@ abstract class PropertyHandlerTemplate { VeluxBridgeHandler thisBridgeHandler) { throw new IllegalStateException("handleRefresh hasn't been set up in the subclass"); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBindingHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBindingHandler.java index fae5a31ea9c36..d1be2ffb5ef48 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBindingHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBindingHandler.java @@ -237,5 +237,4 @@ public void updateBindingState(Integer veluxBridgeCount, Integer veluxThingCount currentNumberOfThings = veluxThingCount; updateVisibleInformation(); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java index 1fa1d148712f0..06cc345197d92 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxBridgeHandler.java @@ -475,7 +475,6 @@ private void syncChannelsWithProducts() { logger.trace("syncChannelsWithProducts(): resetting dirty flag."); bridgeParameters.actuators.getChannel().existingProducts.resetDirtyFlag(); logger.trace("syncChannelsWithProducts() done."); - } // Processing of openHAB events @@ -703,5 +702,4 @@ private synchronized void handleCommandScheduled(ChannelUID channelUID, Command new java.util.Date(thisBridge.lastSuccessfulCommunication()).toString()); logger.trace("handleCommandScheduled({}) done.", Thread.currentThread()); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java index bc0b780b36a26..0465257f96833 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/VeluxHandler.java @@ -124,5 +124,4 @@ public void handleConfigurationUpdate(Map configurationParameter super.handleConfigurationUpdate(configurationParameters); } } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ExtendedBaseThingHandler.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ExtendedBaseThingHandler.java index db0d248b8ff55..7ca598b1fd062 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ExtendedBaseThingHandler.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ExtendedBaseThingHandler.java @@ -64,5 +64,4 @@ public Map editProperties() { public void updateProperties(Map properties) { super.updateProperties(properties); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/StateUtils.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/StateUtils.java index cbc0d1176c4cb..fac351e946331 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/StateUtils.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/StateUtils.java @@ -83,5 +83,4 @@ public static State createState(@Nullable Object propertyValue) { return new StringType(propertyValue.toString()); } } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/Thing2VeluxActuator.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/Thing2VeluxActuator.java index d722957f72af9..3e06b6aa4535d 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/Thing2VeluxActuator.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/Thing2VeluxActuator.java @@ -140,5 +140,4 @@ public boolean isInverted() { } return isInverted; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ThingConfiguration.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ThingConfiguration.java index e24e9b8520961..9a981b3276c5e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ThingConfiguration.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ThingConfiguration.java @@ -65,7 +65,7 @@ private ThingConfiguration() { */ public static boolean exists(BaseBridgeHandler bridge, ChannelUID channelUID, String configName) { ThingUID channelTUID = channelUID.getThingUID(); - Thing thingOfChannel = bridge.getThingByUID(channelTUID); + Thing thingOfChannel = bridge.getThing().getThing(channelTUID); boolean exists = false; if (thingOfChannel == null) { LOGGER.debug("exists(): Channel {} does not belong to a thing.", channelUID); @@ -92,7 +92,7 @@ public static boolean exists(BaseBridgeHandler bridge, ChannelUID channelUID, St */ public static Object getValue(BaseBridgeHandler bridge, ChannelUID channelUID, String configName) { ThingUID channelTUID = channelUID.getThingUID(); - Thing thingOfChannel = bridge.getThingByUID(channelTUID); + Thing thingOfChannel = bridge.getThing().getThing(channelTUID); if (thingOfChannel == null) { LOGGER.warn("getValue(): Channel {} does not belong to a thing.", channelUID); return true; @@ -101,5 +101,4 @@ public static Object getValue(BaseBridgeHandler bridge, ChannelUID channelUID, S LOGGER.trace("getValue({},{}) returns {}.", channelUID, configName, configurationValue); return configurationValue; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ThingProperty.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ThingProperty.java index 0b27857d2e1af..16a2d6ddea21e 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ThingProperty.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/handler/utils/ThingProperty.java @@ -93,12 +93,11 @@ public static void setValue(ExtendedBaseBridgeHandler bridgeHandler, String prop public static void setValue(ExtendedBaseBridgeHandler bridgeHandler, ChannelUID channelUID, String propertyName, String propertyValue) { ThingUID channelTUID = channelUID.getThingUID(); - Thing thingOfChannel = bridgeHandler.getThingByUID(channelTUID); + Thing thingOfChannel = bridgeHandler.getThing().getThing(channelTUID); if (thingOfChannel == null) { LOGGER.warn("setValue(): Channel {} does not belong to a thing.", channelUID); return; } setValue(thingOfChannel, propertyName, propertyValue); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxExistingProducts.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxExistingProducts.java index 73a8179c01430..bfcd098368cc3 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxExistingProducts.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxExistingProducts.java @@ -202,5 +202,4 @@ public String toString(boolean showSummary, String delimiter) { public String toString() { return toString(true, VeluxBindingConstants.OUTPUT_VALUE_SEPARATOR); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwFirmware.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwFirmware.java index 9b1ffe07f5641..3b88a39240f09 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwFirmware.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwFirmware.java @@ -49,5 +49,4 @@ public VeluxGwFirmware() { public String getfirmwareVersion() { return this.firmwareVersion; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwLAN.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwLAN.java index 1a34111901067..ccc2cafdd64fd 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwLAN.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwLAN.java @@ -73,5 +73,4 @@ public String toString() { return String.format("ip %s, nm %s, gw %s, DHCP %s", this.ipAddress, this.subnetMask, this.defaultGW, this.enabledDHCP ? "enabled" : "disabled"); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwState.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwState.java index fc7a7455dc887..8936beebb4f66 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwState.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwState.java @@ -171,5 +171,4 @@ public String toDescription() { public byte getSubState() { return (byte) this.gwSubState.getStateValue(); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwWLAN.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwWLAN.java index 3effaa76bf8ca..384a9f2cbfb7b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwWLAN.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxGwWLAN.java @@ -55,5 +55,4 @@ public String getSSID() { public String getPassword() { return this.password; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxKLFAPI.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxKLFAPI.java index 7662a4e783320..255beae727eb5 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxKLFAPI.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxKLFAPI.java @@ -78,7 +78,6 @@ public static class CommandName { public String toString() { return name; } - } /** @@ -352,7 +351,5 @@ public static Command get(short thisTypeId) { return Command.UNDEFTYPE; } } - } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProduct.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProduct.java index 41943610441a5..383a15ad21309 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProduct.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProduct.java @@ -334,5 +334,4 @@ public int getRemainingTime() { public int getTimeStamp() { return timeStamp; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductName.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductName.java index 9f0cbfd64389c..100ab4a4f39b9 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductName.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductName.java @@ -45,5 +45,4 @@ public VeluxProductName(String name) { public String toString() { return name; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductPosition.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductPosition.java index 8b0fda88963c4..9bff63b854f44 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductPosition.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductPosition.java @@ -170,5 +170,4 @@ public static int getRelativePositionAsVeluxType(boolean upwards, PercentType po } return (int) result; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductReference.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductReference.java index ea30b7774261b..75070bc5b9728 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductReference.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductReference.java @@ -74,5 +74,4 @@ public VeluxProductType getProductType() { public String toString() { return String.format("Prod.ref. \"%s\"/%s", this.name, this.typeId); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductSerialNo.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductSerialNo.java index 4bf12768b5b0e..6c2b6e41c2a6b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductSerialNo.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductSerialNo.java @@ -134,5 +134,4 @@ public static String cleaned(String serialNumberString) { ? serialNumberString.substring(0, serialNumberString.length() - 1) : serialNumberString; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductState.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductState.java index 9c42ab8da774e..9c09412ffc8a8 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductState.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductState.java @@ -87,5 +87,4 @@ public int getStateAsInt() { public String toString() { return String.format("State (%s, actuator %d, value %d)", this.productReference, this.actuator, this.state); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductType.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductType.java index de056660b6370..b692c3077b3e5 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductType.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductType.java @@ -123,5 +123,4 @@ public static VeluxProductType get(int nodeType) { public static String toString(int nodeType) { return ActuatorType.get(nodeType).getDescription(); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductVelocity.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductVelocity.java index 343aecb458529..50f14479b3be2 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductVelocity.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxProductVelocity.java @@ -92,5 +92,4 @@ public static String dump() { } return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxScene.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxScene.java index 58731801002b8..96aa559bcea3b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxScene.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/things/VeluxScene.java @@ -137,5 +137,4 @@ public String toString() { return String.format("Scene \"%s\" (index %d) with %ssilent mode and %d actions", this.name, this.bridgeSceneIndex.toInt(), this.silent ? "" : "non-", this.productStates.length); } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/utils/Localization.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/utils/Localization.java index 76cc54d637850..2bea2abe0959b 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/utils/Localization.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/utils/Localization.java @@ -113,5 +113,4 @@ public String getText(String key, Object... arguments) { logger.trace("getText() returns {}.", text); return text; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/utils/ManifestInformation.java b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/utils/ManifestInformation.java index 627aba075890a..58e8554d473ea 100644 --- a/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/utils/ManifestInformation.java +++ b/bundles/org.openhab.binding.velux/src/main/java/org/openhab/binding/velux/internal/utils/ManifestInformation.java @@ -53,5 +53,4 @@ public static String getBundleVersion() { .toString(); return osgiBundleVersion; } - } diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/config/config.xml index c30311f034f39..4f6b264151eb7 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/config/config.xml @@ -194,4 +194,3 @@ - diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/actuator.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/actuator.xml index 129311b2616b3..53884c28c3514 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/actuator.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/actuator.xml @@ -9,18 +9,18 @@ - + @text/thing-type.velux.actuator.description Blinds - - - - + + + + serialNumber - + diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/binding.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/binding.xml index 6089360d02210..51e6720b39eaf 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/binding.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/binding.xml @@ -12,7 +12,7 @@ @text/thing-type.velux.binding.description NetworkAppliance - + N/A diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/bridge.xml index 66bb7587275d7..3eb97427d962e 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/bridge.xml @@ -11,29 +11,29 @@ @text/bridge-type.velux.klf200.description - - - - + + + + Velux - + diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/channels.xml index 8eb7d33c6d8f7..ed7c0519d5f2c 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/channels.xml @@ -38,7 +38,7 @@ @text/channel-type.velux.downtime.description NetworkAppliance - + @@ -49,85 +49,85 @@ diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/rollershutter.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/rollershutter.xml index c4d59c0aeb348..c8b8f8910395a 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/rollershutter.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/rollershutter.xml @@ -10,17 +10,17 @@ - + @text/thing-type.velux.rollershutter.description Blinds - - - + + + unique - + diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/scene.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/scene.xml index 1bce1894caadc..7abd5365b2117 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/scene.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/scene.xml @@ -10,16 +10,16 @@ - + @text/thing-type.velux.scene.description Blinds - - + + unique - + diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/vshutter.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/vshutter.xml index 7e77495b67fd3..8545eab3ee0f2 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/vshutter.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/vshutter.xml @@ -10,14 +10,14 @@ - + @text/thing-type.velux.vshutter.description Blinds - + - + diff --git a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/window.xml b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/window.xml index 7a04b12aa877b..f6f7ecec71125 100644 --- a/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/window.xml +++ b/bundles/org.openhab.binding.velux/src/main/resources/ESH-INF/thing/window.xml @@ -10,17 +10,17 @@ - + @text/thing-type.velux.window.description Window - - + + serialNumber - + diff --git a/bundles/org.openhab.binding.vitotronic/pom.xml b/bundles/org.openhab.binding.vitotronic/pom.xml index 47b259bbd5e28..bb6c52be7e8a8 100644 --- a/bundles/org.openhab.binding.vitotronic/pom.xml +++ b/bundles/org.openhab.binding.vitotronic/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.vitotronic diff --git a/bundles/org.openhab.binding.vitotronic/src/main/feature/feature.xml b/bundles/org.openhab.binding.vitotronic/src/main/feature/feature.xml index 33b874d7da03d..a3efb7f6f2fa6 100644 --- a/bundles/org.openhab.binding.vitotronic/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.vitotronic/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.vitotronic/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.vitotronic/${project.version} + diff --git a/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/VitotronicBindingConfiguration.java b/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/VitotronicBindingConfiguration.java index 6b3c101364112..c9845b344206b 100644 --- a/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/VitotronicBindingConfiguration.java +++ b/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/VitotronicBindingConfiguration.java @@ -25,5 +25,4 @@ public class VitotronicBindingConfiguration { public Integer port; public String adapterId; public Integer refreshInterval; - } diff --git a/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicBridgeDiscovery.java b/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicBridgeDiscovery.java index 0ac58a7e4acae..2448904d37611 100644 --- a/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicBridgeDiscovery.java +++ b/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/discovery/VitotronicBridgeDiscovery.java @@ -104,5 +104,4 @@ private void addAdapter(String remoteIP, int remotePort, String adapterID) { ThingUID uid = new ThingUID(VitotronicBindingConstants.THING_TYPE_UID_BRIDGE, adapterID); thingDiscovered(DiscoveryResultBuilder.create(uid).withProperties(properties).withLabel(adapterID).build()); } - } diff --git a/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/handler/VitotronicBridgeHandler.java b/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/handler/VitotronicBridgeHandler.java index c6e6e62f5394e..08ded28fdd7bb 100644 --- a/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/handler/VitotronicBridgeHandler.java +++ b/bundles/org.openhab.binding.vitotronic/src/main/java/org/openhab/binding/vitotronic/internal/handler/VitotronicBridgeHandler.java @@ -68,7 +68,6 @@ public VitotronicBridgeHandler(Bridge bridge) { public void updateStatus(ThingStatus status) { super.updateStatus(status); updateThingHandlersStatus(status); - } public void updateStatus() { @@ -77,7 +76,6 @@ public void updateStatus() { } else { updateStatus(ThingStatus.OFFLINE); } - } // Managing Thing Discovery Service @@ -134,7 +132,6 @@ public void unregisterThingListener(VitotronicThingHandler thingHandler) { logger.trace("thingHandler for thing: {} not registered", thingID); } } - } private void updateThingHandlerStatus(VitotronicThingHandler thingHandler, ThingStatus status) { @@ -192,7 +189,6 @@ public void scanThings() { sendSocketData("list"); isDiscover = true; } - } public ThingStatus getStatus() { @@ -360,7 +356,6 @@ public void startElement(String uri, String localName, String pName, Attributes logger.error("Error in parsing data"); logger.trace("Diagnostic: ", e); } - } @Override @@ -387,7 +382,6 @@ public void endElement(String uri, String localName, String qName) throws SAXExc isChannel = false; break; } - } // Unused function of xmlReader @@ -422,7 +416,5 @@ public void startPrefixMapping(String arg0, String arg1) throws SAXException { @Override public void endPrefixMapping(String prefix) throws SAXException { } - } - } diff --git a/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/binding/binding.xml index 94fe75b684903..7d3f59b46bb78 100644 --- a/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Vitotronic Binding This is the binding for Vitotronic. diff --git a/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/thing/bridge.xml index b7d95751dc6d3..32a243eaaaf3b 100644 --- a/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/thing/bridge.xml @@ -6,7 +6,7 @@ - This bridge represents the Vitotronic Optolink adapter + This bridge represents the Vitotronic Optolink adapter @@ -15,8 +15,7 @@ The IP address of the Optolink adapter - + network-address Port of the LAN gateway @@ -26,8 +25,7 @@ The ID of the adapter. - + refresh Refreshtime in seconds. diff --git a/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/thing/thing-types.xml index 093efa5cae886..65383fea31e7e 100644 --- a/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.vitotronic/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,23 +7,23 @@ - + Vitotronic core system - - - - + + + + - + @@ -33,39 +33,39 @@ Power of the gas burner - + - + Pellet Fireplace, works for wood also - - - - - - - - - - + + + + + + + + + + Power of the pellet burner - + - + @@ -75,52 +75,53 @@ Power of the oil burner - - - - - - + + + + + + - + Storage Tank, stores heat in a water tank on 3 levels: bottom, middle, top=hot water - - - - - + + + + + - + - Heating circuit controls the flow of heating water between the heating system and the radiators in the rooms + Heating circuit controls the flow of heating water between the heating system and the radiators in the + rooms - - - - - - - - - - - + + + + + + + + + + + On/Off timer for Monday. Up to 4 timers can be set @@ -252,19 +253,19 @@ - + Solar water heating (SWH): Convert sunlight into energy for water heating - - - - - - + + + + + + @@ -272,34 +273,34 @@ - + Single temperature sensor - + - + Single pump - + - + Single valve - + @@ -310,7 +311,7 @@ DateTime - + @@ -318,7 +319,7 @@ Outside temperature sensor Temperature - + @@ -326,14 +327,14 @@ Temperature sensor of boiler (fireplace) Temperature - + Switch General Malfunction state of the heating - + @@ -341,7 +342,7 @@ Number - + @@ -349,7 +350,7 @@ Actual temperature of the exhaust Temperature - + @@ -359,70 +360,70 @@ Temperature of flame Temperature - + Number Oxygen content of the exhaust air - + Number Position of the primary air shutter - + Number Position of the secondary air shutter - + Number Count of starts - + Number Fan Speed in rpm - + Number Fan Speed in rpm - + Number Ontime in hours - + Number Consumed Pellets since start of heating in tons - + Switch Pump state - + @@ -431,35 +432,35 @@ Number Actual power of the burner - + Switch True, if errors for the burner exists - + Number Ontime in hours - + Number Ontime in hours - + Number Consumed Oil since start of heating in Liter - + @@ -468,7 +469,7 @@ Switch Circuit pump state - + @@ -476,7 +477,7 @@ Temperature sensor in the middle of the storage tank Temperature - + @@ -484,7 +485,7 @@ Temperature sensor at the bottom of the storage tank Temperature - + @@ -492,7 +493,7 @@ Temperature sensor of the hot water Temperature - + @@ -500,7 +501,7 @@ Set the hot water temperature Temperature - + @@ -510,35 +511,35 @@ Temperature sensor of the circuit flow Temperature - + Switch Pump state - + Number Operationmode - + Switch Partymode on/off - + Switch Savemode on/off - + @@ -546,7 +547,7 @@ Target temperature of party mode Temperature - + @@ -554,7 +555,7 @@ Target temperature of save mode Temperature - + @@ -562,7 +563,7 @@ Temperature of rooms Temperature - + @@ -570,27 +571,27 @@ Target temperature of rooms Temperature - + Number The gradient relative to outside temperature - + Number The niveau relative to outside temperature - + String - + @@ -600,7 +601,7 @@ Actual temperature of the collector Temperature - + @@ -608,28 +609,28 @@ Actual temperature of the storage tank (solar sensor) Temperature - + Switch State of the pump (on/off) - + Switch State of the load suppression (on/off) - + Number Produced heat since starting solar system - + @@ -639,13 +640,13 @@ Generic temperature sensor Temperature - + Number Value of a generic valve - + diff --git a/bundles/org.openhab.binding.volvooncall/README.md b/bundles/org.openhab.binding.volvooncall/README.md index 02c8c0a51a927..e20a23e40bc14 100644 --- a/bundles/org.openhab.binding.volvooncall/README.md +++ b/bundles/org.openhab.binding.volvooncall/README.md @@ -40,6 +40,7 @@ The 'VolvoOnCall API' bridge uses the owner's email address and password in orde ## Channels + All numeric channels use the [UoM feature](https://www.eclipse.org/smarthome/blog/2018/02/22/units-of-measurement.html). This means you can easily change the desired unit e.g. miles/h instead of km/h just in your item definition. @@ -82,6 +83,7 @@ Following channels are currently available: | other#brakeFluidLevel | String | Brake fluid level | Normal / Low / VeryLow | | other#washerFluidLevel | String | Washer fluid level | Normal / Low / VeryLow | | other#serviceWarning | String | Warning if service is needed | | +| other#bulbFailure | Switch | ON if at least one bulb is reported as failed | | | battery#batteryLevel | Number:Dimensionless | Battery level | Only for Plugin hybrid / Twin Engine models | | battery#batteryDistanceToEmpty | Number:Length | Distance until battery is empty | Only for Plugin hybrid / Twin Engine models | | battery#chargeStatus | String | Charging status | Only for Plugin hybrid / Twin Engine models | @@ -180,6 +182,7 @@ Example 1a: If Thing has been created using autodiscovery actions.openCarCommand() } ``` + Example 1b: If Thing has been created using script ``` diff --git a/bundles/org.openhab.binding.volvooncall/pom.xml b/bundles/org.openhab.binding.volvooncall/pom.xml index d9cf12fd587d6..5138152e8acb8 100644 --- a/bundles/org.openhab.binding.volvooncall/pom.xml +++ b/bundles/org.openhab.binding.volvooncall/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.volvooncall diff --git a/bundles/org.openhab.binding.volvooncall/src/main/feature/feature.xml b/bundles/org.openhab.binding.volvooncall/src/main/feature/feature.xml index 860c11cba7993..99a43beaa848a 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.volvooncall/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.volvooncall/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.volvooncall/${project.version} + diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallBindingConstants.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallBindingConstants.java index 381e57f483bc5..a01d8a8916989 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallBindingConstants.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallBindingConstants.java @@ -44,6 +44,12 @@ public class VolvoOnCallBindingConstants { public static final ThingTypeUID APIBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, "vocapi"); public static final ThingTypeUID VEHICLE_THING_TYPE = new ThingTypeUID(BINDING_ID, "vehicle"); + // List of Channel groups + public static final String GROUP_DOORS = "doors"; + public static final String GROUP_WINDOWS = "windows"; + public static final String GROUP_TYRES = "tyrePressure"; + public static final String GROUP_BATTERY = "battery"; + // List of Channel id's public static final String TAILGATE = "tailgate"; public static final String REAR_RIGHT = "rearRight"; @@ -82,6 +88,7 @@ public class VolvoOnCallBindingConstants { public static final String CHARGE_STATUS = "chargeStatus"; public static final String TIME_TO_BATTERY_FULLY_CHARGED = "timeToHVBatteryFullyCharged"; public static final String CHARGING_END = "chargingEnd"; + public static final String BULB_FAILURE = "bulbFailure"; // Last Trip Channel Id's public static final String LAST_TRIP_GROUP = "lasttrip"; @@ -118,5 +125,4 @@ public class VolvoOnCallBindingConstants { // Default value for undefined integers public static final int UNDEFINED = -1; - } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallException.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallException.java new file mode 100644 index 0000000000000..54ad35670f9a1 --- /dev/null +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallException.java @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.volvooncall.internal; + +import java.io.IOException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonSyntaxException; + +/** + * Exception for errors when using the VolvoOnCall API + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public class VolvoOnCallException extends Exception { + private final Logger logger = LoggerFactory.getLogger(VolvoOnCallException.class); + private static final long serialVersionUID = -6215621577081394328L; + + public static enum ErrorType { + UNKNOWN, + SERVICE_UNAVAILABLE, + IOEXCEPTION, + JSON_SYNTAX; + } + + private final ErrorType cause; + + public VolvoOnCallException(String label, @Nullable String description) { + super(label); + if ("FoundationServicesUnavailable".equalsIgnoreCase(label)) { + cause = ErrorType.SERVICE_UNAVAILABLE; + } else { + cause = ErrorType.UNKNOWN; + logger.warn("Unhandled VoC error : {} : {}", label, description); + } + } + + public VolvoOnCallException(Exception e) { + super(e); + if (e instanceof IOException) { + cause = ErrorType.IOEXCEPTION; + } else if (e instanceof JsonSyntaxException) { + cause = ErrorType.JSON_SYNTAX; + } else { + cause = ErrorType.UNKNOWN; + logger.warn("Unhandled VoC error : {}", e.getMessage()); + } + } + + public ErrorType getType() { + return cause; + } +} diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallHandlerFactory.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallHandlerFactory.java index aa03d9db74a7f..fe9e71ab14cca 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallHandlerFactory.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/VolvoOnCallHandlerFactory.java @@ -33,6 +33,7 @@ import org.openhab.binding.volvooncall.internal.handler.VehicleStateDescriptionProvider; import org.openhab.binding.volvooncall.internal.handler.VolvoOnCallBridgeHandler; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; @@ -47,9 +48,14 @@ @NonNullByDefault @Component(configurationPid = "binding.volvooncall", service = ThingHandlerFactory.class) public class VolvoOnCallHandlerFactory extends BaseThingHandlerFactory { - private Logger logger = LoggerFactory.getLogger(VolvoOnCallHandlerFactory.class); - private Map> discoveryServiceRegs = new HashMap<>(); - private @NonNullByDefault({}) VehicleStateDescriptionProvider stateDescriptionProvider; + private final Logger logger = LoggerFactory.getLogger(VolvoOnCallHandlerFactory.class); + private final Map> discoveryServiceRegs = new HashMap<>(); + private final VehicleStateDescriptionProvider stateDescriptionProvider; + + @Activate + public VolvoOnCallHandlerFactory(@Reference VehicleStateDescriptionProvider provider) { + this.stateDescriptionProvider = provider; + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -59,16 +65,15 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { @Override protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - if (thingTypeUID.equals(APIBRIDGE_THING_TYPE)) { + if (APIBRIDGE_THING_TYPE.equals(thingTypeUID)) { VolvoOnCallBridgeHandler bridgeHandler = new VolvoOnCallBridgeHandler((Bridge) thing); registerDeviceDiscoveryService(bridgeHandler); return bridgeHandler; - } else if (thingTypeUID.equals(VEHICLE_THING_TYPE) && stateDescriptionProvider != null) { + } else if (VEHICLE_THING_TYPE.equals(thingTypeUID)) { return new VehicleHandler(thing, stateDescriptionProvider); - } else { - logger.warn("ThingHandler not found for {}", thing.getThingTypeUID()); - return null; } + logger.warn("ThingHandler not found for {}", thing.getThingTypeUID()); + return null; } @Override @@ -93,13 +98,4 @@ private void unregisterDeviceDiscoveryService(ThingUID thingUID) { discoveryServiceRegs.remove(thingUID); } } - - @Reference - protected void setDynamicStateDescriptionProvider(VehicleStateDescriptionProvider provider) { - this.stateDescriptionProvider = provider; - } - - protected void unsetDynamicStateDescriptionProvider(VehicleStateDescriptionProvider provider) { - this.stateDescriptionProvider = null; - } } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/action/VolvoOnCallActions.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/action/VolvoOnCallActions.java index b18e9bc7be2b4..9d97190e05381 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/action/VolvoOnCallActions.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/action/VolvoOnCallActions.java @@ -56,6 +56,7 @@ public void setThingHandler(@Nullable ThingHandler handler) { @RuleAction(label = "Volvo On Call : Close", description = "Closes the car") public void closeCarCommand() { logger.debug("closeCarCommand called"); + VehicleHandler handler = this.handler; if (handler != null) { handler.actionClose(); } else { @@ -74,6 +75,7 @@ public static void closeCarCommand(@Nullable ThingActions actions) { @RuleAction(label = "Volvo On Call : Open", description = "Opens the car") public void openCarCommand() { logger.debug("openCarCommand called"); + VehicleHandler handler = this.handler; if (handler != null) { handler.actionOpen(); } else { @@ -92,6 +94,7 @@ public static void openCarCommand(@Nullable ThingActions actions) { @RuleAction(label = "Volvo On Call : Start Engine", description = "Starts the engine") public void engineStartCommand(@ActionInput(name = "runtime", label = "Runtime") @Nullable Integer runtime) { logger.debug("engineStartCommand called"); + VehicleHandler handler = this.handler; if (handler != null) { handler.actionStart(runtime != null ? runtime : 5); } else { @@ -110,6 +113,7 @@ public static void engineStartCommand(@Nullable ThingActions actions, @Nullable @RuleAction(label = "Volvo On Call : Heater Start", description = "Starts car heater") public void heaterStartCommand() { logger.debug("heaterStartCommand called"); + VehicleHandler handler = this.handler; if (handler != null) { handler.actionHeater(true); } else { @@ -128,6 +132,7 @@ public static void heaterStartCommand(@Nullable ThingActions actions) { @RuleAction(label = "Volvo On Call : Preclimatization Start", description = "Starts car heater") public void preclimatizationStartCommand() { logger.debug("preclimatizationStartCommand called"); + VehicleHandler handler = this.handler; if (handler != null) { handler.actionPreclimatization(true); } else { @@ -146,6 +151,7 @@ public static void preclimatizationStartCommand(@Nullable ThingActions actions) @RuleAction(label = "Volvo On Call : Heater Stop", description = "Stops car heater") public void heaterStopCommand() { logger.debug("heaterStopCommand called"); + VehicleHandler handler = this.handler; if (handler != null) { handler.actionHeater(false); } else { @@ -164,6 +170,7 @@ public static void heaterStopCommand(@Nullable ThingActions actions) { @RuleAction(label = "Volvo On Call : Preclimatization Stop", description = "Stops car heater") public void preclimatizationStopCommand() { logger.debug("preclimatizationStopCommand called"); + VehicleHandler handler = this.handler; if (handler != null) { handler.actionPreclimatization(false); } else { @@ -183,6 +190,7 @@ public static void preclimatizationStopCommand(@Nullable ThingActions actions) { public void honkBlinkCommand(@ActionInput(name = "honk", label = "Honk") Boolean honk, @ActionInput(name = "blink", label = "Blink") Boolean blink) { logger.debug("honkBlinkCommand called"); + VehicleHandler handler = this.handler; if (handler != null) { handler.actionHonkBlink(honk, blink); } else { diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/config/VehicleConfiguration.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/config/VehicleConfiguration.java index 8422d0983236e..f6083b4b14bc2 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/config/VehicleConfiguration.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/config/VehicleConfiguration.java @@ -12,13 +12,16 @@ */ package org.openhab.binding.volvooncall.internal.config; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * The {@link VehicleConfiguration} is the class used to match the * Vehicle thing configuration. * * @author Gaël L'hopital - Initial contribution */ +@NonNullByDefault public class VehicleConfiguration { - public String vin; - public Integer refresh; + public String vin = ""; + public Integer refresh = 5; } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/config/VolvoOnCallBridgeConfiguration.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/config/VolvoOnCallBridgeConfiguration.java index 7388cc4f29104..54e50743724b0 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/config/VolvoOnCallBridgeConfiguration.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/config/VolvoOnCallBridgeConfiguration.java @@ -15,18 +15,21 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * The {@link VolvoOnCallBridgeConfiguration} is responsible for holding * configuration informations needed to access VOC API * * @author Gaël L'hopital - Initial contribution */ +@NonNullByDefault public class VolvoOnCallBridgeConfiguration { - public String username; - public String password; + public String username = ""; + public String password = ""; public String getAuthorization() { - byte[] authorization = Base64.getEncoder().encode((username + ":" + password).getBytes()); + byte[] authorization = Base64.getEncoder().encode((String.format("%s:%s", username, password)).getBytes()); return "Basic " + new String(authorization, StandardCharsets.UTF_8); } } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/discovery/VolvoOnCallDiscoveryService.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/discovery/VolvoOnCallDiscoveryService.java index 69620a75f49de..d889384408f54 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/discovery/VolvoOnCallDiscoveryService.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/discovery/VolvoOnCallDiscoveryService.java @@ -14,13 +14,13 @@ import static org.openhab.binding.volvooncall.internal.VolvoOnCallBindingConstants.*; -import java.io.IOException; import java.util.Arrays; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.config.discovery.AbstractDiscoveryService; import org.eclipse.smarthome.config.discovery.DiscoveryResultBuilder; import org.eclipse.smarthome.core.thing.ThingUID; +import org.openhab.binding.volvooncall.internal.VolvoOnCallException; import org.openhab.binding.volvooncall.internal.dto.AccountVehicleRelation; import org.openhab.binding.volvooncall.internal.dto.Attributes; import org.openhab.binding.volvooncall.internal.dto.Vehicles; @@ -62,12 +62,11 @@ public void startScan() { .withBridge(bridgeHandler.getThing().getUID()).withProperty(VIN, attributes.vin) .withRepresentationProperty(accountVehicle.vehicleId).build()); - } catch (IOException e) { + } catch (VolvoOnCallException e) { logger.warn("Error while discovering vehicle: {}", e.getMessage()); } }); stopScan(); } - } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/AccountVehicleRelation.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/AccountVehicleRelation.java index 70460d19abb02..f53d7f96883a4 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/AccountVehicleRelation.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/AccountVehicleRelation.java @@ -24,7 +24,7 @@ * @author Gaël L'hopital - Initial contribution */ @NonNullByDefault -public class AccountVehicleRelation { +public class AccountVehicleRelation extends VocAnswer { @SerializedName("vehicle") public @NonNullByDefault({}) String vehicleURL; public @NonNullByDefault({}) String vehicleId; diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Attributes.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Attributes.java index 7c1bcafa82819..90bcf3c524b8f 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Attributes.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Attributes.java @@ -20,12 +20,12 @@ * * @author Gaël L'hopital - Initial contribution */ -public class Attributes { +public class Attributes extends VocAnswer { public String vehicleType; public String registrationNumber; public Boolean carLocatorSupported; public Boolean honkAndBlinkSupported; - public List honkAndBlinkVersionsSupported = null; + public List honkAndBlinkVersionsSupported; public Boolean remoteHeaterSupported; public Boolean unlockSupported; public Boolean lockSupported; @@ -75,5 +75,4 @@ public class Attributes { * private @Nullable List sendPOIToVehicleVersionsSupported = null; * private @Nullable List climatizationCalendarVersionsSupported = null; */ - } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/CustomerAccounts.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/CustomerAccounts.java index a123dd8f083cc..14fed7a2d9189 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/CustomerAccounts.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/CustomerAccounts.java @@ -24,7 +24,7 @@ * @author Gaël L'hopital - Initial contribution */ @NonNullByDefault -public class CustomerAccounts { +public class CustomerAccounts extends VocAnswer { @SerializedName("accountVehicleRelations") public @NonNullByDefault({}) String[] accountVehicleRelationsURL; public @Nullable String username; diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Heater.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Heater.java index 40f49d828b8fa..203ebca291691 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Heater.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Heater.java @@ -14,6 +14,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; /** * The {@link Heater} is responsible for storing @@ -23,13 +25,18 @@ */ @NonNullByDefault public class Heater { - public @NonNullByDefault({}) OnOffType status; + private String status = ""; /* * Currently unused in the binding, maybe interesting in the future * private ZonedDateTime timestamp; */ - + public State getStatus() { + if ("off".equalsIgnoreCase(status)) { + return OnOffType.OFF; + } else if ("on".equalsIgnoreCase(status) || "onOther".equalsIgnoreCase(status)) { + return OnOffType.ON; + } + return UnDefType.UNDEF; + } } - - diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/HvBattery.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/HvBattery.java index 525a24de12825..a7079131ec2c8 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/HvBattery.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/HvBattery.java @@ -32,7 +32,4 @@ public class HvBattery { * Currently unused in the binding, maybe interesting in the future * private ZonedDateTime timestamp; */ - } - - diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Position.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Position.java index cb630d16dc97f..dc1427282c758 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Position.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Position.java @@ -22,7 +22,7 @@ * @author Gaël L'hopital - Initial contribution */ @NonNullByDefault -public class Position { +public class Position extends VocAnswer { public @NonNullByDefault({}) PositionData position; public @NonNullByDefault({}) PositionData calculatedPosition; } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/PositionData.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/PositionData.java index 39e10e7dfdaaa..fa2e298fca38f 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/PositionData.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/PositionData.java @@ -13,6 +13,7 @@ package org.openhab.binding.volvooncall.internal.dto; import java.time.ZonedDateTime; +import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -28,7 +29,7 @@ public class PositionData { public @Nullable Double longitude; public @Nullable Double latitude; - public @Nullable ZonedDateTime timestamp; + private @Nullable ZonedDateTime timestamp; public @Nullable String speed; private @Nullable String heading; @@ -36,6 +37,13 @@ public Boolean isHeading() { return "true".equalsIgnoreCase(heading); } + public Optional getTimestamp() { + ZonedDateTime timestamp = this.timestamp; + if (timestamp != null) { + return Optional.of(timestamp); + } + return Optional.empty(); + } /* * Currently unused in the binding, maybe interesting in the future * private String streetAddress; diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/PostResponse.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/PostResponse.java index 828c18c7829fe..c8dac0e5df0e3 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/PostResponse.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/PostResponse.java @@ -13,7 +13,6 @@ package org.openhab.binding.volvooncall.internal.dto; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; import com.google.gson.annotations.SerializedName; @@ -24,7 +23,7 @@ * @author Gaël L'hopital - Initial contribution */ @NonNullByDefault -public class PostResponse { +public class PostResponse extends VocAnswer { public static enum Status { @SerializedName("Started") @@ -45,8 +44,6 @@ public static enum ServiceType { } public @NonNullByDefault({}) Status status; - public @Nullable String errorLabel; - public @NonNullByDefault({}) String errorDescription; public @NonNullByDefault({}) String vehicleId; @SerializedName("service") public @NonNullByDefault({}) String serviceURL; diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Status.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Status.java index 82cbdcb3ccba0..f514dfe08aaa2 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Status.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Status.java @@ -14,6 +14,9 @@ import static org.openhab.binding.volvooncall.internal.VolvoOnCallBindingConstants.UNDEFINED; +import java.util.List; +import java.util.Optional; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.OnOffType; @@ -25,8 +28,7 @@ * @author Gaël L'hopital - Initial contribution */ @NonNullByDefault -public class Status { - +public class Status extends VocAnswer { public double averageFuelConsumption = UNDEFINED; public int averageSpeed = UNDEFINED; public int fuelAmount = UNDEFINED; @@ -36,17 +38,77 @@ public class Status { public int tripMeter1 = UNDEFINED; public int tripMeter2 = UNDEFINED; - public @NonNullByDefault({}) OnOffType carLocked; - public @NonNullByDefault({}) OnOffType engineRunning; - public @NonNullByDefault({}) String brakeFluid; - public @NonNullByDefault({}) String washerFluidLevel; - public @Nullable WindowsStatus windows; - public @Nullable DoorsStatus doors; - public @Nullable TyrePressure tyrePressure; - public @Nullable HvBattery hvBattery; - public @Nullable Heater heater; + private @Nullable OnOffType carLocked; + private @Nullable OnOffType engineRunning; + public String brakeFluid = ""; + public String washerFluidLevel = ""; + private @Nullable WindowsStatus windows; + private @Nullable DoorsStatus doors; + private @Nullable TyrePressure tyrePressure; + private @Nullable HvBattery hvBattery; + private @Nullable Heater heater; + public String serviceWarningStatus = ""; + private @NonNullByDefault({}) List bulbFailures; + + public Optional getWindows() { + WindowsStatus windows = this.windows; + if (windows != null) { + return Optional.of(windows); + } + return Optional.empty(); + } + + public Optional getDoors() { + DoorsStatus doors = this.doors; + if (doors != null) { + return Optional.of(doors); + } + return Optional.empty(); + } + + public Optional getTyrePressure() { + TyrePressure tyrePressure = this.tyrePressure; + if (tyrePressure != null) { + return Optional.of(tyrePressure); + } + return Optional.empty(); + } + + public Optional getHvBattery() { + HvBattery hvBattery = this.hvBattery; + if (hvBattery != null) { + return Optional.of(hvBattery); + } + return Optional.empty(); + } + + public Optional getHeater() { + Heater heater = this.heater; + if (heater != null) { + return Optional.of(heater); + } + return Optional.empty(); + } + + public Optional getCarLocked() { + OnOffType carLocked = this.carLocked; + if (carLocked != null) { + return Optional.of(carLocked); + } + return Optional.empty(); + } + + public Optional getEngineRunning() { + OnOffType engineRunning = this.engineRunning; + if (engineRunning != null) { + return Optional.of(engineRunning); + } + return Optional.empty(); + } - public @NonNullByDefault({}) String serviceWarningStatus; + public boolean aFailedBulb() { + return bulbFailures.size() > 0; + } /* * Currently not used in the binding, maybe interesting for the future @@ -56,7 +118,6 @@ public class Status { * private ZonedDateTime averageFuelConsumptionTimestamp; * private ZonedDateTime averageSpeedTimestamp; * private ZonedDateTime brakeFluidTimestamp; - * private List bulbFailures = null; * private ZonedDateTime bulbFailuresTimestamp; * private ZonedDateTime carLockedTimestamp; * private ZonedDateTime distanceToEmptyTimestamp; diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/TripDetail.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/TripDetail.java index c9375d4364a6d..7d2f76dd24ce3 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/TripDetail.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/TripDetail.java @@ -12,9 +12,12 @@ */ package org.openhab.binding.volvooncall.internal.dto; +import static org.openhab.binding.volvooncall.internal.VolvoOnCallBindingConstants.UNDEFINED; + import java.time.Duration; import java.time.ZoneId; import java.time.ZonedDateTime; +import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -31,12 +34,12 @@ */ @NonNullByDefault public class TripDetail { - public @Nullable Integer fuelConsumption; - public @Nullable Integer electricalConsumption; - public @Nullable Integer electricalRegeneration; - public int distance; - public int startOdometer; - public int endOdometer; + private @Nullable Integer fuelConsumption; + private @Nullable Integer electricalConsumption; + private @Nullable Integer electricalRegeneration; + public int distance = UNDEFINED; + public int startOdometer = UNDEFINED; + public int endOdometer = UNDEFINED; private @Nullable ZonedDateTime endTime; private @Nullable ZonedDateTime startTime; private @NonNullByDefault({}) PositionData startPosition; @@ -50,9 +53,8 @@ private State ZonedDateTimeToState(@Nullable ZonedDateTime datetime) { private State getPositionAsState(PositionData details) { if (details.latitude != null && details.longitude != null) { return new PointType(details.latitude + "," + details.longitude); - } else { - return UnDefType.NULL; } + return UnDefType.NULL; } public State getStartTime() { @@ -75,4 +77,27 @@ public long getDurationInMinutes() { return Duration.between(startTime, endTime).toMinutes(); } + public Optional getFuelConsumption() { + Integer fuelConsumption = this.fuelConsumption; + if (fuelConsumption != null) { + return Optional.of(fuelConsumption); + } + return Optional.empty(); + } + + public Optional getElectricalConsumption() { + Integer electricalConsumption = this.electricalConsumption; + if (electricalConsumption != null) { + return Optional.of(electricalConsumption); + } + return Optional.empty(); + } + + public Optional getElectricalRegeneration() { + Integer electricalRegeneration = this.electricalRegeneration; + if (electricalRegeneration != null) { + return Optional.of(electricalRegeneration); + } + return Optional.empty(); + } } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Trips.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Trips.java index 5c886684771b9..75dd67d9fd6e9 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Trips.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Trips.java @@ -24,6 +24,6 @@ * @author Gaël L'hopital - Initial contribution */ @NonNullByDefault -public class Trips { - public @Nullable List trips = null; +public class Trips extends VocAnswer { + public @Nullable List trips; } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Vehicles.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Vehicles.java index 4fe7fcd2954b9..23d86dbc3788c 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Vehicles.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/Vehicles.java @@ -14,6 +14,8 @@ import org.eclipse.jdt.annotation.NonNullByDefault; +import com.google.gson.annotations.SerializedName; + /** * The {@link Vehicles} is responsible for storing * informations returned by vehicule rest answer @@ -21,18 +23,17 @@ * @author Gaël L'hopital - Initial contribution */ @NonNullByDefault -public class Vehicles { +public class Vehicles extends VocAnswer { public @NonNullByDefault({}) String vehicleId; + @SerializedName("attributes") + public @NonNullByDefault({}) String attributesURL; + @SerializedName("status") + public @NonNullByDefault({}) String statusURL; /* * Currently unused in the binding, maybe interesting in the future - * - * @SerializedName("attributes") - * private String attributesURL; - * - * @SerializedName("status") - * private String statusURL; - * + * + * * private String[] vehicleAccountRelations; */ } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/VocAnswer.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/VocAnswer.java new file mode 100644 index 0000000000000..1bb3fdf50ed01 --- /dev/null +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/dto/VocAnswer.java @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.volvooncall.internal.dto; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link VocAnswer} is the base class for all Voc API requests + * + * @author Gaël L'hopital - Initial contribution + */ +@NonNullByDefault +public abstract class VocAnswer { + + private @Nullable String errorLabel; + private @Nullable String errorDescription; + + public @Nullable String getErrorLabel() { + return errorLabel; + } + + public @Nullable String getErrorDescription() { + return errorDescription; + } +} diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/handler/VehicleHandler.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/handler/VehicleHandler.java index 99f54dd1ada0c..e96d322c3aff8 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/handler/VehicleHandler.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/handler/VehicleHandler.java @@ -13,6 +13,8 @@ package org.openhab.binding.volvooncall.internal.handler; import static org.eclipse.smarthome.core.library.unit.MetricPrefix.KILO; +import static org.eclipse.smarthome.core.library.unit.SIUnits.*; +import static org.eclipse.smarthome.core.library.unit.SmartHomeUnits.*; import static org.openhab.binding.volvooncall.internal.VolvoOnCallBindingConstants.*; import java.io.IOException; @@ -33,8 +35,6 @@ import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.QuantityType; import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.library.unit.SIUnits; -import org.eclipse.smarthome.core.library.unit.SmartHomeUnits; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; @@ -48,15 +48,21 @@ import org.eclipse.smarthome.core.types.RefreshType; import org.eclipse.smarthome.core.types.State; import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.binding.volvooncall.internal.VolvoOnCallException; import org.openhab.binding.volvooncall.internal.action.VolvoOnCallActions; import org.openhab.binding.volvooncall.internal.config.VehicleConfiguration; import org.openhab.binding.volvooncall.internal.dto.Attributes; +import org.openhab.binding.volvooncall.internal.dto.DoorsStatus; +import org.openhab.binding.volvooncall.internal.dto.Heater; +import org.openhab.binding.volvooncall.internal.dto.HvBattery; import org.openhab.binding.volvooncall.internal.dto.Position; import org.openhab.binding.volvooncall.internal.dto.Status; import org.openhab.binding.volvooncall.internal.dto.Trip; import org.openhab.binding.volvooncall.internal.dto.TripDetail; import org.openhab.binding.volvooncall.internal.dto.Trips; +import org.openhab.binding.volvooncall.internal.dto.TyrePressure; import org.openhab.binding.volvooncall.internal.dto.Vehicles; +import org.openhab.binding.volvooncall.internal.dto.WindowsStatus; import org.openhab.binding.volvooncall.internal.wrapper.VehiclePositionWrapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,8 +78,7 @@ @NonNullByDefault public class VehicleHandler extends BaseThingHandler { private final Logger logger = LoggerFactory.getLogger(VehicleHandler.class); - - private @NonNullByDefault({}) Map activeOptions; + private final Map activeOptions = new HashMap<>(); private @Nullable ScheduledFuture refreshJob; private Vehicles vehicle = new Vehicles(); @@ -86,9 +91,9 @@ public VehicleHandler(Thing thing, VehicleStateDescriptionProvider stateDescript super(thing); } - private Map discoverAttributes(VolvoOnCallBridgeHandler bridgeHandler, String vin) - throws JsonSyntaxException, IOException { - Attributes attributes = bridgeHandler.getURL(Attributes.class, vin); + private Map discoverAttributes(VolvoOnCallBridgeHandler bridgeHandler) + throws JsonSyntaxException, IOException, VolvoOnCallException { + Attributes attributes = bridgeHandler.getURL(vehicle.attributesURL, Attributes.class); Map properties = new HashMap<>(); properties.put(CAR_LOCATOR, attributes.carLocatorSupported.toString()); @@ -118,12 +123,12 @@ public void initialize() { vehicle = bridgeHandler.getURL(SERVICE_URL + "vehicles/" + configuration.vin, Vehicles.class); if (thing.getProperties().isEmpty()) { - Map properties = discoverAttributes(bridgeHandler, configuration.vin); + Map properties = discoverAttributes(bridgeHandler); updateProperties(properties); } - activeOptions = thing.getProperties().entrySet().stream().filter(p -> "true".equals(p.getValue())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + activeOptions.putAll(thing.getProperties().entrySet().stream().filter(p -> "true".equals(p.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))); if (thing.getProperties().containsKey(LAST_TRIP_ID)) { lastTripId = Integer.parseInt(thing.getProperties().get(LAST_TRIP_ID)); @@ -131,7 +136,7 @@ public void initialize() { updateStatus(ThingStatus.ONLINE); startAutomaticRefresh(configuration.refresh); - } catch (JsonSyntaxException | IOException e) { + } catch (JsonSyntaxException | IOException | VolvoOnCallException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR, e.getMessage()); } } @@ -143,6 +148,7 @@ public void initialize() { * @param refresh : refresh frequency in minutes */ private void startAutomaticRefresh(int refresh) { + ScheduledFuture refreshJob = this.refreshJob; if (refreshJob == null || refreshJob.isCancelled()) { refreshJob = scheduler.scheduleWithFixedDelay(this::queryApiAndUpdateChannels, 10, refresh, TimeUnit.MINUTES); @@ -153,27 +159,42 @@ private void queryApiAndUpdateChannels() { VolvoOnCallBridgeHandler bridgeHandler = getBridgeHandler(); if (bridgeHandler != null) { try { - vehicleStatus = bridgeHandler.getURL(Status.class, configuration.vin); + vehicleStatus = bridgeHandler.getURL(vehicle.statusURL, Status.class); vehiclePosition = new VehiclePositionWrapper(bridgeHandler.getURL(Position.class, configuration.vin)); // Update all channels from the updated data getThing().getChannels().stream().map(Channel::getUID) .filter(channelUID -> isLinked(channelUID) && !LAST_TRIP_GROUP.equals(channelUID.getGroupId())) .forEach(channelUID -> { - State state = getValue(channelUID.getIdWithoutGroup(), vehicleStatus, vehiclePosition); + State state = getValue(channelUID.getGroupId(), channelUID.getIdWithoutGroup(), + vehicleStatus, vehiclePosition); updateState(channelUID, state); }); updateTrips(bridgeHandler); - } catch (JsonSyntaxException | IOException e) { + } catch (VolvoOnCallException e) { logger.warn("Exception occurred during execution: {}", e.getMessage(), e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); - refreshJob = null; + freeRefreshJob(); startAutomaticRefresh(configuration.refresh); } } } - private void updateTrips(VolvoOnCallBridgeHandler bridgeHandler) throws JsonSyntaxException, IOException { + private void freeRefreshJob() { + ScheduledFuture refreshJob = this.refreshJob; + if (refreshJob != null) { + refreshJob.cancel(true); + this.refreshJob = null; + } + } + + @Override + public void dispose() { + freeRefreshJob(); + super.dispose(); + } + + private void updateTrips(VolvoOnCallBridgeHandler bridgeHandler) throws VolvoOnCallException { // This seems to rewind 100 days by default, did not find any way to filter it Trips carTrips = bridgeHandler.getURL(Trips.class, configuration.vin); List tripList = carTrips.trips; @@ -230,23 +251,21 @@ public void handleCommand(ChannelUID channelUID, Command command) { private State getTripValue(String channelId, TripDetail tripDetails) { switch (channelId) { case TRIP_CONSUMPTION: - if (tripDetails.fuelConsumption != null) { - return new QuantityType<>(tripDetails.fuelConsumption.floatValue() / 100, SmartHomeUnits.LITRE); - } else { - return UnDefType.UNDEF; - } + return tripDetails.getFuelConsumption() + .map(value -> (State) new QuantityType<>(value.floatValue() / 100, LITRE)) + .orElse(UnDefType.UNDEF); case TRIP_DISTANCE: - return new QuantityType<>((double) tripDetails.distance / 1000, KILO(SIUnits.METRE)); + return new QuantityType<>((double) tripDetails.distance / 1000, KILO(METRE)); case TRIP_START_TIME: return tripDetails.getStartTime(); case TRIP_END_TIME: return tripDetails.getEndTime(); case TRIP_DURATION: - return new QuantityType<>(tripDetails.getDurationInMinutes(), SmartHomeUnits.MINUTE); + return new QuantityType<>(tripDetails.getDurationInMinutes(), MINUTE); case TRIP_START_ODOMETER: - return new QuantityType<>((double) tripDetails.startOdometer / 1000, KILO(SIUnits.METRE)); + return new QuantityType<>((double) tripDetails.startOdometer / 1000, KILO(METRE)); case TRIP_STOP_ODOMETER: - return new QuantityType<>((double) tripDetails.endOdometer / 1000, KILO(SIUnits.METRE)); + return new QuantityType<>((double) tripDetails.endOdometer / 1000, KILO(METRE)); case TRIP_START_POSITION: return tripDetails.getStartPosition(); case TRIP_END_POSITION: @@ -256,88 +275,111 @@ private State getTripValue(String channelId, TripDetail tripDetails) { return UnDefType.NULL; } - private State getValue(String channelId, Status status, VehiclePositionWrapper position) { + private State getDoorsValue(String channelId, DoorsStatus doors) { switch (channelId) { case TAILGATE: - return status.doors != null ? status.doors.tailgateOpen : UnDefType.NULL; + return doors.tailgateOpen; case REAR_RIGHT: - return status.doors != null ? status.doors.rearRightDoorOpen : UnDefType.NULL; + return doors.rearRightDoorOpen; case REAR_LEFT: - return status.doors != null ? status.doors.rearLeftDoorOpen : UnDefType.NULL; + return doors.rearLeftDoorOpen; case FRONT_RIGHT: - return status.doors != null ? status.doors.frontRightDoorOpen : UnDefType.NULL; + return doors.frontRightDoorOpen; case FRONT_LEFT: - return status.doors != null ? status.doors.frontLeftDoorOpen : UnDefType.NULL; + return doors.frontLeftDoorOpen; case HOOD: - return status.doors != null ? status.doors.hoodOpen : UnDefType.NULL; + return doors.hoodOpen; + } + return UnDefType.NULL; + } + + private State getWindowsValue(String channelId, WindowsStatus windows) { + switch (channelId) { case REAR_RIGHT_WND: - return status.windows != null ? status.windows.rearRightWindowOpen : UnDefType.NULL; + return windows.rearRightWindowOpen; case REAR_LEFT_WND: - return status.windows != null ? status.windows.rearLeftWindowOpen : UnDefType.NULL; + return windows.rearLeftWindowOpen; case FRONT_RIGHT_WND: - return status.windows != null ? status.windows.frontRightWindowOpen : UnDefType.NULL; + return windows.frontRightWindowOpen; case FRONT_LEFT_WND: - return status.windows != null ? status.windows.frontLeftWindowOpen : UnDefType.NULL; + return windows.frontLeftWindowOpen; + } + return UnDefType.NULL; + } + + private State getTyresValue(String channelId, TyrePressure tyrePressure) { + switch (channelId) { case REAR_RIGHT_TYRE: - return status.tyrePressure != null ? new StringType(status.tyrePressure.rearRightTyrePressure) - : UnDefType.NULL; + return new StringType(tyrePressure.rearRightTyrePressure); case REAR_LEFT_TYRE: - return status.tyrePressure != null ? new StringType(status.tyrePressure.rearLeftTyrePressure) - : UnDefType.NULL; + return new StringType(tyrePressure.rearLeftTyrePressure); case FRONT_RIGHT_TYRE: - return status.tyrePressure != null ? new StringType(status.tyrePressure.frontRightTyrePressure) - : UnDefType.NULL; + return new StringType(tyrePressure.frontRightTyrePressure); case FRONT_LEFT_TYRE: - return status.tyrePressure != null ? new StringType(status.tyrePressure.frontLeftTyrePressure) - : UnDefType.NULL; + return new StringType(tyrePressure.frontLeftTyrePressure); + } + return UnDefType.NULL; + } + + private State getHeaterValue(String channelId, Heater heater) { + switch (channelId) { + case REMOTE_HEATER: + case PRECLIMATIZATION: + return heater.getStatus(); + } + return UnDefType.NULL; + } + + private State getBatteryValue(String channelId, HvBattery hvBattery) { + switch (channelId) { + case BATTERY_LEVEL: + return hvBattery.hvBatteryLevel != UNDEFINED ? new QuantityType<>(hvBattery.hvBatteryLevel, PERCENT) + : UnDefType.UNDEF; + case BATTERY_DISTANCE_TO_EMPTY: + return hvBattery.distanceToHVBatteryEmpty != UNDEFINED + ? new QuantityType<>(hvBattery.distanceToHVBatteryEmpty, KILO(METRE)) + : UnDefType.UNDEF; + case CHARGE_STATUS: + return hvBattery.hvBatteryChargeStatusDerived != null + ? new StringType(hvBattery.hvBatteryChargeStatusDerived) + : UnDefType.UNDEF; + case TIME_TO_BATTERY_FULLY_CHARGED: + return hvBattery.timeToHVBatteryFullyCharged != UNDEFINED + ? new QuantityType<>(hvBattery.timeToHVBatteryFullyCharged, MINUTE) + : UnDefType.UNDEF; + case CHARGING_END: + return hvBattery.timeToHVBatteryFullyCharged != UNDEFINED && hvBattery.timeToHVBatteryFullyCharged > 0 + ? new DateTimeType(ZonedDateTime.now().plusMinutes(hvBattery.timeToHVBatteryFullyCharged)) + : UnDefType.UNDEF; + + } + return UnDefType.NULL; + } + + private State getValue(@Nullable String groupId, String channelId, Status status, VehiclePositionWrapper position) { + switch (channelId) { case ODOMETER: - return status.odometer != UNDEFINED - ? new QuantityType<>((double) status.odometer / 1000, KILO(SIUnits.METRE)) + return status.odometer != UNDEFINED ? new QuantityType<>((double) status.odometer / 1000, KILO(METRE)) : UnDefType.UNDEF; case TRIPMETER1: return status.tripMeter1 != UNDEFINED - ? new QuantityType<>((double) status.tripMeter1 / 1000, KILO(SIUnits.METRE)) + ? new QuantityType<>((double) status.tripMeter1 / 1000, KILO(METRE)) : UnDefType.UNDEF; case TRIPMETER2: return status.tripMeter2 != UNDEFINED - ? new QuantityType<>((double) status.tripMeter2 / 1000, KILO(SIUnits.METRE)) + ? new QuantityType<>((double) status.tripMeter2 / 1000, KILO(METRE)) : UnDefType.UNDEF; case DISTANCE_TO_EMPTY: - return status.distanceToEmpty != UNDEFINED - ? new QuantityType<>(status.distanceToEmpty, KILO(SIUnits.METRE)) + return status.distanceToEmpty != UNDEFINED ? new QuantityType<>(status.distanceToEmpty, KILO(METRE)) : UnDefType.UNDEF; case FUEL_AMOUNT: - return status.fuelAmount != UNDEFINED ? new QuantityType<>(status.fuelAmount, SmartHomeUnits.LITRE) - : UnDefType.UNDEF; + return status.fuelAmount != UNDEFINED ? new QuantityType<>(status.fuelAmount, LITRE) : UnDefType.UNDEF; case FUEL_LEVEL: - return status.fuelAmountLevel != UNDEFINED - ? new QuantityType<>(status.fuelAmountLevel, SmartHomeUnits.PERCENT) + return status.fuelAmountLevel != UNDEFINED ? new QuantityType<>(status.fuelAmountLevel, PERCENT) : UnDefType.UNDEF; case FUEL_CONSUMPTION: return status.averageFuelConsumption != UNDEFINED ? new DecimalType(status.averageFuelConsumption / 10) : UnDefType.UNDEF; - case BATTERY_LEVEL: - return status.hvBattery.hvBatteryLevel != UNDEFINED - ? new QuantityType<>(status.hvBattery.hvBatteryLevel, SmartHomeUnits.PERCENT) - : UnDefType.UNDEF; - case BATTERY_DISTANCE_TO_EMPTY: - return status.hvBattery.distanceToHVBatteryEmpty != UNDEFINED - ? new QuantityType<>(status.hvBattery.distanceToHVBatteryEmpty, KILO(SIUnits.METRE)) - : UnDefType.UNDEF; - case CHARGE_STATUS: - return status.hvBattery.hvBatteryChargeStatusDerived != null - ? new StringType(status.hvBattery.hvBatteryChargeStatusDerived) - : UnDefType.UNDEF; - case TIME_TO_BATTERY_FULLY_CHARGED: - return status.hvBattery.timeToHVBatteryFullyCharged != UNDEFINED - ? new QuantityType<>(status.hvBattery.timeToHVBatteryFullyCharged, SmartHomeUnits.MINUTE) - : UnDefType.UNDEF; - case CHARGING_END: - return status.hvBattery.timeToHVBatteryFullyCharged != UNDEFINED - && status.hvBattery.timeToHVBatteryFullyCharged > 0 - ? new DateTimeType( - ZonedDateTime.now().plusMinutes(status.hvBattery.timeToHVBatteryFullyCharged)) - : UnDefType.UNDEF; case ACTUAL_LOCATION: return position.getPosition(); case CALCULATED_LOCATION: @@ -347,27 +389,43 @@ private State getValue(String channelId, Status status, VehiclePositionWrapper p case LOCATION_TIMESTAMP: return position.getTimestamp(); case CAR_LOCKED: - return status.carLocked; + // Warning : carLocked is in the Doors group but is part of general status informations. + // Did not change it to avoid breaking change for users + return status.getCarLocked().map(State.class::cast).orElse(UnDefType.UNDEF); case ENGINE_RUNNING: - return status.engineRunning; + return status.getEngineRunning().map(State.class::cast).orElse(UnDefType.UNDEF); case BRAKE_FLUID_LEVEL: return new StringType(status.brakeFluid); case WASHER_FLUID_LEVEL: return new StringType(status.washerFluidLevel); case AVERAGE_SPEED: - return status.averageSpeed != UNDEFINED - ? new QuantityType<>(status.averageSpeed, SIUnits.KILOMETRE_PER_HOUR) + return status.averageSpeed != UNDEFINED ? new QuantityType<>(status.averageSpeed, KILOMETRE_PER_HOUR) : UnDefType.UNDEF; case SERVICE_WARNING: return new StringType(status.serviceWarningStatus); case FUEL_ALERT: return status.distanceToEmpty < 100 ? OnOffType.ON : OnOffType.OFF; + case BULB_FAILURE: + return status.aFailedBulb() ? OnOffType.ON : OnOffType.OFF; case REMOTE_HEATER: - return status.heater != null && status.heater.status != null ? status.heater.status : UnDefType.UNDEF; case PRECLIMATIZATION: - return status.heater != null && status.heater.status != null ? status.heater.status : UnDefType.UNDEF; + return status.getHeater().map(heater -> getHeaterValue(channelId, heater)).orElse(UnDefType.NULL); + } + if (groupId != null) { + switch (groupId) { + case GROUP_DOORS: + return status.getDoors().map(doors -> getDoorsValue(channelId, doors)).orElse(UnDefType.NULL); + case GROUP_WINDOWS: + return status.getWindows().map(windows -> getWindowsValue(channelId, windows)) + .orElse(UnDefType.NULL); + case GROUP_TYRES: + return status.getTyrePressure().map(tyres -> getTyresValue(channelId, tyres)) + .orElse(UnDefType.NULL); + case GROUP_BATTERY: + return status.getHvBattery().map(batteries -> getBatteryValue(channelId, batteries)) + .orElse(UnDefType.NULL); + } } - return UnDefType.NULL; } @@ -389,7 +447,7 @@ public void actionHonkBlink(Boolean honk, Boolean blink) { try { bridgeHandler.postURL(url.toString(), vehiclePosition.getPositionAsJSon()); - } catch (JsonSyntaxException | IOException e) { + } catch (VolvoOnCallException e) { logger.warn("Exception occurred during execution: {}", e.getMessage(), e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } @@ -400,11 +458,15 @@ private void actionOpenClose(String action, OnOffType controlState) { VolvoOnCallBridgeHandler bridgeHandler = getBridgeHandler(); if (bridgeHandler != null) { if (activeOptions.containsKey(action)) { - if (vehicleStatus.carLocked != controlState) { + if (!vehicleStatus.getCarLocked().isPresent() || vehicleStatus.getCarLocked().get() != controlState) { try { - String address = SERVICE_URL + "vehicles/" + configuration.vin + "/" + action; - bridgeHandler.postURL(address, "{}"); - } catch (JsonSyntaxException | IOException e) { + StringBuilder address = new StringBuilder(SERVICE_URL); + address.append("vehicles/"); + address.append(configuration.vin); + address.append("/"); + address.append(action); + bridgeHandler.postURL(address.toString(), "{}"); + } catch (VolvoOnCallException e) { logger.warn("Exception occurred during execution: {}", e.getMessage(), e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } @@ -431,7 +493,7 @@ private void actionHeater(String action, Boolean start) { String address = SERVICE_URL + "vehicles/" + configuration.vin + "/preclimatization/" + command; bridgeHandler.postURL(address, start ? "{}" : null); } - } catch (JsonSyntaxException | IOException e) { + } catch (VolvoOnCallException e) { logger.warn("Exception occurred during execution: {}", e.getMessage(), e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } @@ -466,7 +528,7 @@ public void actionStart(Integer runtime) { try { bridgeHandler.postURL(url, json); - } catch (JsonSyntaxException | IOException e) { + } catch (VolvoOnCallException e) { logger.warn("Exception occurred during execution: {}", e.getMessage(), e); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/handler/VolvoOnCallBridgeHandler.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/handler/VolvoOnCallBridgeHandler.java index 5eacac62464be..1ba5487cc9463 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/handler/VolvoOnCallBridgeHandler.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/handler/VolvoOnCallBridgeHandler.java @@ -36,9 +36,12 @@ import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.io.net.http.HttpUtil; +import org.openhab.binding.volvooncall.internal.VolvoOnCallException; +import org.openhab.binding.volvooncall.internal.VolvoOnCallException.ErrorType; import org.openhab.binding.volvooncall.internal.config.VolvoOnCallBridgeConfiguration; import org.openhab.binding.volvooncall.internal.dto.CustomerAccounts; import org.openhab.binding.volvooncall.internal.dto.PostResponse; +import org.openhab.binding.volvooncall.internal.dto.VocAnswer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,6 +75,7 @@ public VolvoOnCallBridgeHandler(Bridge bridge) { httpHeader.put("x-originator-type", "App"); httpHeader.put("x-os-type", "Android"); httpHeader.put("x-os-version", "22"); + httpHeader.put("Accept", "*/*"); gson = new GsonBuilder() .registerTypeAdapter(ZonedDateTime.class, @@ -101,7 +105,7 @@ public void initialize() { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Incorrect username or password"); } - } catch (IOException | JsonSyntaxException e) { + } catch (JsonSyntaxException | VolvoOnCallException e) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); } } @@ -114,19 +118,29 @@ public void handleCommand(ChannelUID channelUID, Command command) { public String[] getVehiclesRelationsURL() { if (customerAccount != null) { return customerAccount.accountVehicleRelationsURL; - } else { - return new String[0]; } + return new String[0]; } - public T getURL(Class objectClass, String vin) throws IOException, JsonSyntaxException { + public T getURL(Class objectClass, String vin) throws VolvoOnCallException { String url = SERVICE_URL + "vehicles/" + vin + "/" + objectClass.getSimpleName().toLowerCase(); return getURL(url, objectClass); } - public T getURL(String url, Class objectClass) throws IOException, JsonSyntaxException { - String jsonResponse = HttpUtil.executeUrl("GET", url, httpHeader, null, JSON_CONTENT_TYPE, REQUEST_TIMEOUT); - return gson.fromJson(jsonResponse, objectClass); + public T getURL(String url, Class objectClass) throws VolvoOnCallException { + try { + String jsonResponse = HttpUtil.executeUrl("GET", url, httpHeader, null, JSON_CONTENT_TYPE, REQUEST_TIMEOUT); + logger.debug("Request for : {}", url); + logger.debug("Received : {}", jsonResponse); + T response = gson.fromJson(jsonResponse, objectClass); + String error = response.getErrorLabel(); + if (error != null) { + throw new VolvoOnCallException(error, response.getErrorDescription()); + } + return response; + } catch (JsonSyntaxException | IOException e) { + throw new VolvoOnCallException(e); + } } public class ActionResultControler implements Runnable { @@ -141,7 +155,7 @@ public void run() { switch (postResponse.status) { case SUCCESSFULL: case FAILED: - logger.debug("Action status : {} for vehicle : {}.", postResponse.status.toString(), + logger.info("Action status : {} for vehicle : {}.", postResponse.status.toString(), postResponse.vehicleId); getThing().getThings().stream().filter(VehicleHandler.class::isInstance) .map(VehicleHandler.class::cast) @@ -151,25 +165,32 @@ public void run() { try { postResponse = getURL(postResponse.serviceURL, PostResponse.class); scheduler.schedule(new ActionResultControler(postResponse), 1000, TimeUnit.MILLISECONDS); - } catch (JsonSyntaxException | IOException e) { - logger.warn("Error calling : {} : {}", postResponse.serviceURL, e.getMessage()); + } catch (VolvoOnCallException e) { + if (e.getType() == ErrorType.SERVICE_UNAVAILABLE) { + scheduler.schedule(new ActionResultControler(postResponse), 1000, TimeUnit.MILLISECONDS); + } } } } } - void postURL(String URL, @Nullable String body) throws IOException, JsonSyntaxException { + void postURL(String URL, @Nullable String body) throws VolvoOnCallException { InputStream inputStream = body != null ? new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)) : null; - String jsonString = HttpUtil.executeUrl("POST", URL, httpHeader, inputStream, null, REQUEST_TIMEOUT); - logger.debug("Post URL: {} Attributes {}", URL, httpHeader); - PostResponse postResponse = gson.fromJson(jsonString, PostResponse.class); - if (postResponse.errorLabel == null) { - pendingActions - .add(scheduler.schedule(new ActionResultControler(postResponse), 1000, TimeUnit.MILLISECONDS)); - } else { - logger.warn("URL {} returned {}", URL, postResponse.errorDescription); + try { + String jsonString = HttpUtil.executeUrl("POST", URL, httpHeader, inputStream, null, REQUEST_TIMEOUT); + logger.debug("Post URL: {} Attributes {}", URL, httpHeader); + PostResponse postResponse = gson.fromJson(jsonString, PostResponse.class); + String error = postResponse.getErrorLabel(); + if (error == null) { + pendingActions + .add(scheduler.schedule(new ActionResultControler(postResponse), 1000, TimeUnit.MILLISECONDS)); + } else { + throw new VolvoOnCallException(error, postResponse.getErrorDescription()); + } + pendingActions.removeIf(ScheduledFuture::isDone); + } catch (JsonSyntaxException | IOException e) { + throw new VolvoOnCallException(e); } - pendingActions.removeIf(ScheduledFuture::isDone); } @Override diff --git a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/wrapper/VehiclePositionWrapper.java b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/wrapper/VehiclePositionWrapper.java index 5461f88cfaf72..8b36c6a22aedf 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/wrapper/VehiclePositionWrapper.java +++ b/bundles/org.openhab.binding.volvooncall/src/main/java/org/openhab/binding/volvooncall/internal/wrapper/VehiclePositionWrapper.java @@ -13,6 +13,7 @@ package org.openhab.binding.volvooncall.internal.wrapper; import java.time.ZoneId; +import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -32,39 +33,38 @@ */ @NonNullByDefault public class VehiclePositionWrapper { - private final Position vehicle; + private final Optional position; + private boolean isCalculated; public VehiclePositionWrapper(Position vehicle) { - this.vehicle = vehicle; + if (vehicle.calculatedPosition != null && vehicle.position.latitude != null) { + position = Optional.of(vehicle.position); + isCalculated = false; + } else if (vehicle.calculatedPosition != null && vehicle.calculatedPosition.latitude != null) { + position = Optional.of(vehicle.calculatedPosition); + isCalculated = true; + } else { + position = Optional.empty(); + } } private State getPositionAsState(PositionData details) { if (details.latitude != null && details.longitude != null) { return new PointType(details.latitude + "," + details.longitude); - } else { - return UnDefType.NULL; } + return UnDefType.NULL; } public State getPosition() { - if (vehicle.position.latitude != null) { - return getPositionAsState(vehicle.position); - } else if (vehicle.calculatedPosition.latitude != null) { - return getPositionAsState(vehicle.calculatedPosition); - } else { - return UnDefType.NULL; - } + return position.map(pos -> getPositionAsState(pos)).orElse(UnDefType.UNDEF); } public @Nullable String getPositionAsJSon() { - PositionData details = vehicle.position; - if (details != null && details.latitude != null && details.longitude != null) { - StringBuilder json = new StringBuilder(); - - json.append("{\"clientLatitude\":"); - json.append(details.latitude); + if (getPosition() != UnDefType.UNDEF) { + StringBuilder json = new StringBuilder("{\"clientLatitude\":"); + json.append(position.get().latitude); json.append(",\"clientLongitude\":"); - json.append(details.longitude); + json.append(position.get().longitude); json.append(",\"clientAccuracy\":0}"); return json.toString(); @@ -73,19 +73,16 @@ public State getPosition() { } public State isCalculated() { - return vehicle.calculatedPosition.latitude != null ? OnOffType.ON : OnOffType.OFF; + return position.map(pos -> isCalculated ? (State) OnOffType.ON : OnOffType.OFF).orElse(UnDefType.UNDEF); } public State isHeading() { - return (vehicle.position.isHeading() || vehicle.calculatedPosition.isHeading()) ? OnOffType.ON : OnOffType.OFF; + return position.map(pos -> pos.isHeading() ? (State) OnOffType.ON : OnOffType.OFF).orElse(UnDefType.UNDEF); } public State getTimestamp() { - return vehicle.position.timestamp != null - ? new DateTimeType(vehicle.position.timestamp.withZoneSameInstant(ZoneId.systemDefault())) - : vehicle.calculatedPosition.timestamp != null - ? new DateTimeType( - vehicle.calculatedPosition.timestamp.withZoneSameInstant(ZoneId.systemDefault())) - : UnDefType.NULL; + return position.flatMap(pos -> pos.getTimestamp()) + .map(dt -> (State) new DateTimeType(dt.withZoneSameInstant(ZoneId.systemDefault()))) + .orElse(UnDefType.NULL); } } diff --git a/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/config/config.xml index 10d60607bb718..aef24a4a262e7 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/thing/bridge.xml index 84174a8e89567..0c5b78f566b43 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/thing/bridge.xml @@ -8,7 +8,7 @@ This bridge represents the gateway to Volvo On Call API. - + diff --git a/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/thing/vehicle.xml b/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/thing/vehicle.xml index 1ca4314e8a686..9bea49eb049d8 100644 --- a/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/thing/vehicle.xml +++ b/bundles/org.openhab.binding.volvooncall/src/main/resources/ESH-INF/thing/vehicle.xml @@ -7,21 +7,21 @@ - + - - - - - - - - - + + + + + + + + + vin @@ -43,13 +43,14 @@ - - - - - - - + + + + + + + + @@ -72,7 +73,7 @@ Trip end time - + @@ -111,7 +112,7 @@ - + @@ -154,7 +155,7 @@ - + @@ -171,9 +172,9 @@ Indicates the quantity of fuel available in the tank - - - + + + Distance left with given quantity of fuel @@ -188,8 +189,8 @@ The position of the vehicle - - + + Timestamp of location value update @@ -200,12 +201,12 @@ - + - - + + @@ -291,7 +292,7 @@ DateTime Data timestamp - + @@ -324,6 +325,13 @@ (De)Activates remote heater + + Switch + + At least on bulb is reported as dead + + + String @@ -377,7 +385,7 @@ Switch set to 'ON' when the tank level is low - + diff --git a/bundles/org.openhab.binding.weathercompany/README.md b/bundles/org.openhab.binding.weathercompany/README.md index 161b572ce168c..9c0ed3d4bd211 100644 --- a/bundles/org.openhab.binding.weathercompany/README.md +++ b/bundles/org.openhab.binding.weathercompany/README.md @@ -146,113 +146,114 @@ The following channels will be translated to local language based on the languag ### Thing Example ``` -Bridge weathercompany:account:bridge [ apiKey="734982347982374" ] { - Thing weathercompany:weather-forecast:forecast "Local Forecast" @ "Home" [locationType="postalCode",postalCode="10001:US",language="en-US",refreshInterval=30] - Thing weathercompany:weather-forecast:chitown "Chicago Forecast" @ "Ohare Airport" [apiKey="734982347982374",locationType="iataCode",iataCode="ORD",language="en-US",refreshInterval=30] - Thing weathercompany:weather-forecast:miami "Miami Weather" @ "South Beach" [locationType="postalCode",postalCode="33139:US",language="es-US",refreshInterval=30] - Thing weathercompany:weather-observations:observations "Local Observations" @ "Home" [pwsStationId="KFLMIAMI208",refreshInterval=30] - Thing weathercompany:weather-observations:patagonia "Torres del Paine Weather" @ "Patagonia" [pwsStationId="IPUNTAAR4",refreshInterval=30] +Bridge weathercompany:account:myaccount [ apiKey="0123456789" ] { + Thing weather-forecast myweather "My Forecast" @ "Home" [locationType="postalCode",postalCode="10001:US",language="en-US",refreshInterval=30] + Thing weather-observations myobservations "My Observations" @ "Home" [pwsStationId="KFLMIAMI208",refreshInterval=30] + Thing weather-forecast chitown "Chicago Forecast" @ "Ohare Airport" [apiKey="734982347982374",locationType="iataCode",iataCode="ORD",language="en-US",refreshInterval=30] + Thing weather-forecast miami "Miami Weather" @ "South Beach" [locationType="postalCode",postalCode="33139:US",language="es-US",refreshInterval=30] + Thing weather-observations patagonia "Torres del Paine Weather" @ "Patagonia" [pwsStationId="IPUNTAAR4",refreshInterval=30] } + ``` ### Items Example ``` // PWS Current Observations -Number:Temperature WC_PWS_Temperature "Temperature [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentTemperature" } -Number:Temperature WC_PWS_TemperatureDewPoint "Dew Point Temperature [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentTemperatureDewPoint" } -Number:Temperature WC_PWS_TemperatureHeatIndex "Heat Index Temperature [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentTemperatureHeatIndex" } -Number:Temperature WC_PWS_TemperatureWindChill "Wind Chill Temperature [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentTemperatureWindChill" } -Number:Dimensionless WC_PWS_RelativeHumidity "Relative Humidity [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentHumidity" } -Number:Pressure WC_PWS_Pressure "Pressure [%.2f %unit%]" { channel="weathercompany:weather-observations:observations:currentPressure" } +Number:Temperature WC_PWS_Temperature "Temperature [%.1f %unit%]" { channel="weathercompany:weather-observations:myaccount:myobservations:currentTemperature" } +Number:Temperature WC_PWS_TemperatureDewPoint "Dew Point Temperature [%.1f %unit%]" { channel="weathercompany:weather-observations:myaccount:myobservations:currentTemperatureDewPoint" } +Number:Temperature WC_PWS_TemperatureHeatIndex "Heat Index Temperature [%.1f %unit%]" { channel="weathercompany:weather-observations:myaccount:myobservations:currentTemperatureHeatIndex" } +Number:Temperature WC_PWS_TemperatureWindChill "Wind Chill Temperature [%.1f %unit%]" { channel="weathercompany:weather-observations:myaccount:myobservations:currentTemperatureWindChill" } +Number:Dimensionless WC_PWS_RelativeHumidity "Relative Humidity [%.1f %unit%]" { channel="weathercompany:weather-observations:myaccount:myobservations:currentHumidity" } +Number:Pressure WC_PWS_Pressure "Pressure [%.2f %unit%]" { channel="weathercompany:weather-observations:myaccount:myobservations:currentPressure" } // Use this for SI units -Number:Speed WC_PWS_PrecipitationRate "Precipitation Rate [%.1f mm/h]" { channel="weathercompany:weather-observations:observations:currentPrecipitationRate" } +//Number:Speed WC_PWS_PrecipitationRate "Precipitation Rate [%.1f mm/h]" { channel="weathercompany:weather-observations:myaccount:myobservations:currentPrecipitationRate" } // Use this for Imperial units -//Number:Speed WC_PWS_PrecipitationRate "Precipitation Rate [%.2f in/h]" { channel="weathercompany:weather-observations:observations:currentPrecipitationRate" } -Number:Length WC_PWS_PrecipitationTotal "Precipitation Total [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentPrecipitationTotal" } -Number:Intensity WC_PWS_SolarRadiation "Solar Radiation [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentSolarRadiation" } -Number WC_PWS_UV "UV Index [%.0f]" { channel="weathercompany:weather-observations:observations:currentUv" } -Number:Angle WC_PWS_WindDirection "Wind Direction [%.0f %unit%]" { channel="weathercompany:weather-observations:observations:currentWindDirection" } -Number:Speed WC_PWS_WindSpeed "Wind Speed [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentWindSpeed" } -Number:Speed WC_PWS_WindSpeedGust "Wind Speed Gust [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:currentWindSpeedGust" } -String WC_PWS_Country "Country [%s]" { channel="weathercompany:weather-observations:observations:country" } -Location WC_PWS_Location "Lat/Lon [%2$s°N, %3$s°W]" { channel="weathercompany:weather-observations:observations:location" } -Number:Length WC_PWS_Elevation "Elevation [%.1f %unit%]" { channel="weathercompany:weather-observations:observations:elevation" } -String WC_PWS_Neighborhood "Neighborhood [%s]" { channel="weathercompany:weather-observations:observations:neighborhood" } -DateTime WC_PWS_ObservationTimeLocal "Observation Time [%1$tA, %1$tm/%1$td/%1$tY %1$tl:%1$tM %1$tp]" @@ -282,14 +283,14 @@ Location Latitude and longitude of weather station - + Number:Length Elevation above ground of weather station - + @@ -317,7 +318,7 @@ Number:Dimensionless Chance of precipitation - + @@ -325,7 +326,7 @@ Forecasted measurable liquid precipitation during 24 hour period Rain - + @@ -333,7 +334,7 @@ Precipitation rate Rain - + @@ -341,7 +342,7 @@ Forecasted measurable snow precipitation during 24 hour period Rain - + @@ -349,7 +350,7 @@ Precipitation total Rain - + @@ -364,14 +365,14 @@ Barometric Pressure Pressure - + Number QC status - + @@ -392,7 +393,7 @@ Number:Dimensionless Forecasted relative humidity - + @@ -413,7 +414,7 @@ Number:Intensity Solar radiation - + @@ -428,7 +429,7 @@ Forecasted temperature Temperature - + @@ -470,7 +471,7 @@ Number:Angle Wind direction - + @@ -491,7 +492,7 @@ Number:Speed Wind speed - + diff --git a/bundles/org.openhab.binding.weatherunderground/pom.xml b/bundles/org.openhab.binding.weatherunderground/pom.xml index 7e73898060c07..415132cf7e0db 100644 --- a/bundles/org.openhab.binding.weatherunderground/pom.xml +++ b/bundles/org.openhab.binding.weatherunderground/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.weatherunderground diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/feature/feature.xml b/bundles/org.openhab.binding.weatherunderground/src/main/feature/feature.xml index 0e963584ae5ce..3b70e032992f0 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.weatherunderground/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.weatherunderground/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.weatherunderground/${project.version} + diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/WeatherUndergroundBindingConstants.java b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/WeatherUndergroundBindingConstants.java index 98a1737917000..b8ed0825addd6 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/WeatherUndergroundBindingConstants.java +++ b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/WeatherUndergroundBindingConstants.java @@ -17,6 +17,7 @@ import java.util.HashSet; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.smarthome.core.thing.ThingTypeUID; /** @@ -26,6 +27,7 @@ * @author Laurent Garnier - Initial contribution * @author Theo Giovanna - Added a bridge for the API key */ +@NonNullByDefault public class WeatherUndergroundBindingConstants { public static final String BINDING_ID = "weatherunderground"; diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/WeatherUndergroundHandlerFactory.java b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/WeatherUndergroundHandlerFactory.java index abe88d32b4e1e..36b3d336c9408 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/WeatherUndergroundHandlerFactory.java +++ b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/WeatherUndergroundHandlerFactory.java @@ -21,6 +21,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.discovery.DiscoveryService; import org.eclipse.smarthome.core.i18n.LocaleProvider; import org.eclipse.smarthome.core.i18n.LocationProvider; @@ -36,6 +38,7 @@ import org.openhab.binding.weatherunderground.internal.handler.WeatherUndergroundBridgeHandler; import org.openhab.binding.weatherunderground.internal.handler.WeatherUndergroundHandler; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -47,53 +50,35 @@ * @author Theo Giovanna - Added a bridge for the API key * @author Laurent Garnier - Registration of the discovery service updated */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.weatherunderground") public class WeatherUndergroundHandlerFactory extends BaseThingHandlerFactory { - private Map> discoveryServiceRegs = new HashMap<>(); - - private LocaleProvider localeProvider; - private LocationProvider locationProvider; - private UnitProvider unitProvider; + private static final Set SUPPORTED_THING_TYPES_UIDS = Stream + .of(BRIDGE_THING_TYPES_UIDS, WeatherUndergroundBindingConstants.SUPPORTED_THING_TYPES_UIDS) + .flatMap(x -> x.stream()).collect(Collectors.toSet()); - @Reference - protected void setLocaleProvider(final LocaleProvider localeProvider) { - this.localeProvider = localeProvider; - } + private final Map> discoveryServiceRegs = new HashMap<>(); - protected void unsetLocaleProvider(final LocaleProvider localeProvider) { - this.localeProvider = null; - } + private final LocaleProvider localeProvider; + private final LocationProvider locationProvider; + private final UnitProvider unitProvider; - @Reference - public void setLocationProvider(LocationProvider locationProvider) { + @Activate + public WeatherUndergroundHandlerFactory(final @Reference LocaleProvider localeProvider, + final @Reference LocationProvider locationProvider, final @Reference UnitProvider unitProvider) { + this.localeProvider = localeProvider; this.locationProvider = locationProvider; - } - - public void unsetLocationProvider(LocationProvider locationProvider) { - this.locationProvider = null; - } - - @Reference - protected void setUnitProvider(final UnitProvider unitProvider) { this.unitProvider = unitProvider; } - protected void unsetUnitProvider(final UnitProvider unitProvider) { - this.unitProvider = null; - } - - private static final Set SUPPORTED_THING_TYPES_UIDS = Stream - .of(BRIDGE_THING_TYPES_UIDS, WeatherUndergroundBindingConstants.SUPPORTED_THING_TYPES_UIDS) - .flatMap(x -> x.stream()).collect(Collectors.toSet()); - @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); } @Override - protected ThingHandler createHandler(Thing thing) { + protected @Nullable ThingHandler createHandler(Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (thingTypeUID.equals(THING_TYPE_WEATHER)) { @@ -135,5 +120,4 @@ private synchronized void unregisterDiscoveryService(ThingUID bridgeUID) { } } } - } diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/config/WeatherUndergroundConfiguration.java b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/config/WeatherUndergroundConfiguration.java index 483c73bbeb866..983ab5941e766 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/config/WeatherUndergroundConfiguration.java +++ b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/config/WeatherUndergroundConfiguration.java @@ -26,5 +26,4 @@ public class WeatherUndergroundConfiguration { public String location; public String language; public Integer refresh; - } diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/discovery/WeatherUndergroundDiscoveryService.java b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/discovery/WeatherUndergroundDiscoveryService.java index 102de24ed2597..cdea3f215aa4d 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/discovery/WeatherUndergroundDiscoveryService.java +++ b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/discovery/WeatherUndergroundDiscoveryService.java @@ -151,5 +151,4 @@ private void createResults(PointType location, Locale locale) { thingDiscovered(DiscoveryResultBuilder.create(localWeatherThing).withLabel("Local Weather") .withProperties(properties).withBridge(bridgeUID).build()); } - } diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/handler/WeatherUndergroundBridgeHandler.java b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/handler/WeatherUndergroundBridgeHandler.java index 19cb5ff9765ce..a64a09c11786c 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/handler/WeatherUndergroundBridgeHandler.java +++ b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/handler/WeatherUndergroundBridgeHandler.java @@ -16,7 +16,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.core.Configuration; @@ -54,8 +53,7 @@ public class WeatherUndergroundBridgeHandler extends BaseBridgeHandler { @Nullable private ScheduledFuture controlApiKeyJob; - @Nullable - private String apikey; + private String apikey = ""; public WeatherUndergroundBridgeHandler(Bridge bridge) { super(bridge); @@ -68,12 +66,13 @@ public void initialize() { Configuration config = getThing().getConfiguration(); // Check if an api key has been provided during the bridge creation - if (StringUtils.trimToNull((String) config.get(WeatherUndergroundBindingConstants.APIKEY)) == null) { + Object configApiKey = config.get(WeatherUndergroundBindingConstants.APIKEY); + if (configApiKey == null || !(configApiKey instanceof String) || ((String) configApiKey).trim().isEmpty()) { logger.debug("Setting thing '{}' to OFFLINE: Parameter 'apikey' must be configured.", getThing().getUID()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-missing-apikey"); } else { - apikey = (String) config.get(WeatherUndergroundBindingConstants.APIKEY); + apikey = ((String) configApiKey).trim(); updateStatus(ThingStatus.UNKNOWN); startControlApiKeyJob(); } @@ -95,7 +94,7 @@ public void run() { // Check if the provided api key is valid for use with the weatherunderground service try { - String urlStr = URL.replace("%APIKEY%", StringUtils.trimToEmpty(getApikey())); + String urlStr = URL.replace("%APIKEY%", getApikey()); // Run the HTTP request and get the JSON response from Weather Underground String response = null; try { @@ -168,7 +167,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { // not needed } - public @Nullable String getApikey() { + public String getApikey() { return apikey; } } diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/handler/WeatherUndergroundHandler.java b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/handler/WeatherUndergroundHandler.java index e4bb444fbb268..a24d57f11ad3a 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/handler/WeatherUndergroundHandler.java +++ b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/handler/WeatherUndergroundHandler.java @@ -28,7 +28,6 @@ import javax.measure.Quantity; import javax.measure.Unit; -import org.apache.commons.lang.StringUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.i18n.LocaleProvider; @@ -233,14 +232,13 @@ private void initializeThingHandler(@Nullable ThingHandler bridgeHandler, @Nulla String errors = ""; String statusDescr = null; - if (StringUtils.trimToNull(config.location) == null) { + if (config.location == null || config.location.trim().isEmpty()) { errors += " Parameter 'location' must be configured."; statusDescr = "@text/offline.conf-error-missing-location"; validConfig = false; } if (config.language != null) { - String lang = StringUtils.trimToEmpty(config.language); - if (lang.length() != 2) { + if (config.language.trim().length() != 2) { errors += " Parameter 'language' must be 2 letters."; statusDescr = "@text/offline.conf-error-syntax-language"; validConfig = false; @@ -264,7 +262,7 @@ private void initializeThingHandler(@Nullable ThingHandler bridgeHandler, @Nulla updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); } } else { - updateStatus(ThingStatus.OFFLINE); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); } } @@ -535,11 +533,9 @@ private boolean updateWeatherData(Set features) { try { WeatherUndergroundConfiguration config = getConfigAs(WeatherUndergroundConfiguration.class); - String urlStr = URL_QUERY.replace("%APIKEY%", StringUtils.trimToEmpty(bridgeHandler.getApikey())); + String urlStr = URL_QUERY.replace("%FEATURES%", String.join("/", features)); - urlStr = urlStr.replace("%FEATURES%", String.join("/", features)); - - String lang = StringUtils.trimToEmpty(config.language); + String lang = config.language == null ? "" : config.language.trim(); if (lang.isEmpty()) { // If language is not set in the configuration, you try deducing it from the system language lang = getCodeFromLanguage(localeProvider.getLocale()); @@ -552,8 +548,13 @@ private boolean updateWeatherData(Set features) { urlStr = urlStr.replace("%SETTINGS%", "lang:" + lang.toUpperCase()); } - urlStr = urlStr.replace("%QUERY%", StringUtils.trimToEmpty(config.location)); - logger.debug("URL = {}", urlStr); + String location = config.location == null ? "" : config.location.trim(); + urlStr = urlStr.replace("%QUERY%", location); + if (logger.isDebugEnabled()) { + logger.debug("URL = {}", urlStr.replace("%APIKEY%", "***")); + } + + urlStr = urlStr.replace("%APIKEY%", bridgeHandler.getApikey()); // Run the HTTP request and get the JSON response from Weather Underground String response = null; @@ -562,8 +563,7 @@ private boolean updateWeatherData(Set features) { logger.debug("weatherData = {}", response); } catch (IllegalArgumentException e) { // catch Illegal character in path at index XX: http://api.wunderground.com/... - error = "Error creating URI with location parameter: '" + StringUtils.trimToEmpty(config.location) - + "'"; + error = "Error creating URI with location parameter: '" + location + "'"; errorDetail = e.getMessage(); statusDescr = "@text/offline.uri-error"; } @@ -628,11 +628,11 @@ private boolean updateWeatherData(Set features) { */ public static String getCodeFromLanguage(Locale locale) { String key = locale.getLanguage() + "-" + locale.getCountry(); - String language = StringUtils.trimToEmpty(LANG_COUNTRY_TO_WU_CODES.get(key)); - if (language.isEmpty()) { - language = StringUtils.trimToEmpty(LANG_ISO_TO_WU_CODES.get(locale.getLanguage().toUpperCase())); + String language = LANG_COUNTRY_TO_WU_CODES.get(key); + if (language == null) { + language = LANG_ISO_TO_WU_CODES.get(locale.getLanguage().toUpperCase()); } - return language; + return language != null ? language : ""; } private WUQuantity getTemperature(BigDecimal siValue, BigDecimal imperialValue) { diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/json/WeatherUndergroundJsonData.java b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/json/WeatherUndergroundJsonData.java index b8ec0fd9a9113..3155d28d2d6a4 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/json/WeatherUndergroundJsonData.java +++ b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/json/WeatherUndergroundJsonData.java @@ -65,5 +65,4 @@ public WeatherUndergroundJsonForecast getForecast() { public WeatherUndergroundJsonCurrent getCurrent() { return current_observation; } - } diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/json/WeatherUndergroundJsonUtils.java b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/json/WeatherUndergroundJsonUtils.java index cf4dc5f5294f2..f01ee524a3dcb 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/json/WeatherUndergroundJsonUtils.java +++ b/bundles/org.openhab.binding.weatherunderground/src/main/java/org/openhab/binding/weatherunderground/internal/json/WeatherUndergroundJsonUtils.java @@ -20,7 +20,6 @@ import java.time.ZonedDateTime; import java.util.TimeZone; -import org.apache.commons.lang.StringUtils; import org.slf4j.LoggerFactory; /** @@ -104,9 +103,9 @@ private static boolean isValid(String value) { */ public static URL getValidUrl(String url) { URL validUrl = null; - if (StringUtils.isNotBlank(url)) { + if (url != null && !url.trim().isEmpty()) { try { - validUrl = new URL(url); + validUrl = new URL(url.trim()); } catch (MalformedURLException e) { } } diff --git a/bundles/org.openhab.binding.weatherunderground/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.weatherunderground/src/main/resources/ESH-INF/thing/thing-types.xml index c9866619b9448..ed2b6bc56b2c6 100644 --- a/bundles/org.openhab.binding.weatherunderground/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.weatherunderground/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,13 +7,13 @@ - + Provides various weather data from the Weather Underground service - + This is the weather forecast for today @@ -161,29 +161,29 @@ This is the current weather - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -191,22 +191,22 @@ This is the weather forecast - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -257,7 +257,7 @@ Minimum temperature Temperature - + @@ -265,7 +265,7 @@ Maximum temperature Temperature - + @@ -273,7 +273,7 @@ Dew Point temperature Temperature - + @@ -281,7 +281,7 @@ Heat index Temperature - + @@ -289,7 +289,7 @@ Wind chill temperature Temperature - + @@ -297,7 +297,7 @@ Feeling temperature Temperature - + @@ -356,7 +356,7 @@ Maximum wind speed Wind - + @@ -364,7 +364,7 @@ Average wind speed Wind - + @@ -372,7 +372,7 @@ Wind gust Wind - + @@ -393,7 +393,7 @@ Number:Length Visibility - + @@ -417,7 +417,7 @@ Rain fall during the day Rain - + @@ -425,7 +425,7 @@ Rain fall during the last hour Rain - + @@ -433,7 +433,7 @@ Snow fall Rain - + diff --git a/bundles/org.openhab.binding.wemo/pom.xml b/bundles/org.openhab.binding.wemo/pom.xml index 86a7c0a6f6623..0e9508543e51d 100644 --- a/bundles/org.openhab.binding.wemo/pom.xml +++ b/bundles/org.openhab.binding.wemo/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.wemo diff --git a/bundles/org.openhab.binding.wemo/src/main/feature/feature.xml b/bundles/org.openhab.binding.wemo/src/main/feature/feature.xml index 2ca1c88e87edc..ab8b96eb6b9f0 100644 --- a/bundles/org.openhab.binding.wemo/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.wemo/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.wemo/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.wemo/${project.version} + diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java index 9a02543bf6b19..ee98e59eeb988 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoBindingConstants.java @@ -128,5 +128,4 @@ public class WemoBindingConstants { THING_TYPE_BRIDGE, THING_TYPE_MZ100, THING_TYPE_MAKER, THING_TYPE_COFFEE, THING_TYPE_DIMMER, THING_TYPE_CROCKPOT, THING_TYPE_PURIFIER, THING_TYPE_HUMIDIFIER, THING_TYPE_HEATER) .collect(Collectors.toSet())); - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java index 62025e14ef713..39dbc8772318e 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/WemoHandlerFactory.java @@ -150,5 +150,4 @@ private synchronized void registerDeviceDiscoveryService(WemoBridgeHandler wemoB this.discoveryServiceRegs.put(wemoBridgeHandler.getThing().getUID(), bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>())); } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoDiscoveryParticipant.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoDiscoveryParticipant.java index 2450bcf6f2a0b..53c956e2cac3e 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoDiscoveryParticipant.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoDiscoveryParticipant.java @@ -159,5 +159,4 @@ public ThingUID getThingUID(@Nullable RemoteDevice device) { } return null; } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoDiscoveryService.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoDiscoveryService.java index 3683b3fa3e73a..741256a99fdf6 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoDiscoveryService.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoDiscoveryService.java @@ -74,5 +74,4 @@ protected synchronized void stopScan() { removeOlderResults(getTimestampOfLastScan()); super.stopScan(); } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoLinkDiscoveryService.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoLinkDiscoveryService.java index ad40b0af1ee6f..15f09d2970a6f 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoLinkDiscoveryService.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/discovery/WemoLinkDiscoveryService.java @@ -288,5 +288,4 @@ public void run() { startScan(); } } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBridgeHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBridgeHandler.java index 626612858ee2e..d7139dc8128a6 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBridgeHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoBridgeHandler.java @@ -64,5 +64,4 @@ public void initialize() { public void handleCommand(ChannelUID channelUID, Command command) { // Not needed, all commands are handled in the {@link WemoLightHandler} } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java index 80216899e7940..5444ff4b8dc8e 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCoffeeHandler.java @@ -468,5 +468,4 @@ public static String getCharacterDataFromElement(Element e) { @Override public void onStatusChanged(boolean status) { } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java index 99ba3da2b4c9b..a36d836a14933 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoCrockpotHandler.java @@ -303,5 +303,4 @@ public String getWemoURL(String actionService) { @Override public void onStatusChanged(boolean status) { } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java index fb8471bb18b7d..ca2d18bd0766c 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoDimmerHandler.java @@ -610,5 +610,4 @@ public void setTimerStart(String action, String argument, String value) { @Override public void onStatusChanged(boolean status) { } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java index ae0afa938596a..1e094266d263d 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHandler.java @@ -499,5 +499,4 @@ public boolean servicePing(String host, int port) throws IOException { @Override public void onStatusChanged(boolean status) { } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java index 34d0a301919a9..86539584422b4 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoHolmesHandler.java @@ -573,5 +573,4 @@ public static String getCharacterDataFromElement(Element e) { @Override public void onStatusChanged(boolean status) { } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java index 614bc9c823b03..4687dc8134da8 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoLightHandler.java @@ -430,5 +430,4 @@ public String getWemoURL() { } return null; } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java index 9f9910e4065c0..7becbdc4a985f 100644 --- a/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java +++ b/bundles/org.openhab.binding.wemo/src/main/java/org/openhab/binding/wemo/internal/handler/WemoMakerHandler.java @@ -303,5 +303,4 @@ public void onServiceSubscribed(String service, boolean succeeded) { @Override public void onValueReceived(String variable, String value, String service) { } - } diff --git a/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/binding/binding.xml index 62d68b319dd22..641b6012cf075 100644 --- a/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/binding/binding.xml @@ -1,5 +1,6 @@ - WeMo Binding diff --git a/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/thing/bridge.xml index be71ad7c2022f..b86fcdd539bb7 100644 --- a/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,5 +1,6 @@ - diff --git a/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/thing/thing-types.xml index 1ad878f40398b..8906a79bf523e 100644 --- a/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.wemo/src/main/resources/ESH-INF/thing/thing-types.xml @@ -9,7 +9,7 @@ This is a standard WeMo Switch - + @@ -27,18 +27,18 @@ This is a WeMo Insight Switch with energy measurement - - - - - - - - - - - - + + + + + + + + + + + + @@ -56,7 +56,7 @@ This is a WeMo LightSwitch - + @@ -73,8 +73,8 @@ This is a WeMo MotionSensor - - + + @@ -89,15 +89,15 @@ - + This is a standard WeMo light bulb with E27 socket - - + + @@ -119,8 +119,8 @@ This is a WeMo Maker - - + + @@ -137,15 +137,15 @@ This is a WeMo enabled coffee maker - - - - - - - - - + + + + + + + + + @@ -168,14 +168,14 @@ This is a WeMo DimmerSwitch - - - - - - - - + + + + + + + + @@ -219,28 +219,28 @@ Number Duration the device has been switched on for - + Number How long has the device been switched on today - + Number How long has the device been switched on totally - + Number Time used to measure average usage - + @@ -248,7 +248,7 @@ The average power consumption Energy - + @@ -256,7 +256,7 @@ The current power consumption Energy - + @@ -264,7 +264,7 @@ Todays power consumption Energy - + @@ -272,7 +272,7 @@ Total power consumption Energy - + @@ -280,7 +280,7 @@ Total power consumption Energy - + @@ -288,7 +288,7 @@ Appliance on standby Energy - + @@ -297,7 +297,8 @@ Dimmer The brightness channel allows to control the brightness of a light. - It is also possible to switch the light on and off. + It is also possible to switch the + light on and off. DimmableLight @@ -384,7 +385,7 @@ Number The fading duration time in minutes - + @@ -410,14 +411,14 @@ DateTime Time when the Night Mode starts - + DateTime Time when the Night Mode ends - + diff --git a/bundles/org.openhab.binding.wifiled/pom.xml b/bundles/org.openhab.binding.wifiled/pom.xml index 663029de86955..b015648616b76 100644 --- a/bundles/org.openhab.binding.wifiled/pom.xml +++ b/bundles/org.openhab.binding.wifiled/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.wifiled diff --git a/bundles/org.openhab.binding.wifiled/src/main/feature/feature.xml b/bundles/org.openhab.binding.wifiled/src/main/feature/feature.xml index f2283dce9e2cb..bf5bcebee063f 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.wifiled/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.wifiled/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.wifiled/${project.version} + diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/WiFiLEDBindingConstants.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/WiFiLEDBindingConstants.java index 83c3858b33a9f..c8f85abab7a52 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/WiFiLEDBindingConstants.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/WiFiLEDBindingConstants.java @@ -41,5 +41,4 @@ public class WiFiLEDBindingConstants { public static final String CHANNEL_WHITE2 = "white2"; public static final String CHANNEL_PROGRAM = "program"; public static final String CHANNEL_PROGRAM_SPEED = "programSpeed"; - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/WiFiLEDHandlerFactory.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/WiFiLEDHandlerFactory.java index e52718197dde5..f5063abbe66e0 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/WiFiLEDHandlerFactory.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/WiFiLEDHandlerFactory.java @@ -51,5 +51,4 @@ protected ThingHandler createHandler(Thing thing) { return null; } - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/configuration/WiFiLEDConfig.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/configuration/WiFiLEDConfig.java index 195fe13387ff1..935201232dee8 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/configuration/WiFiLEDConfig.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/configuration/WiFiLEDConfig.java @@ -83,5 +83,4 @@ public Integer getFadeSteps() { public void setFadeSteps(Integer fadeSteps) { this.fadeSteps = fadeSteps; } - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/discovery/WiFiLEDDiscoveryService.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/discovery/WiFiLEDDiscoveryService.java index 733233127f1fc..aebea1c5ce243 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/discovery/WiFiLEDDiscoveryService.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/discovery/WiFiLEDDiscoveryService.java @@ -139,5 +139,4 @@ private static String bytesToString(byte[] bytes) { return sb.toString(); } - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/AbstractWiFiLEDDriver.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/AbstractWiFiLEDDriver.java index 73022a6c228eb..3d07f457d99fe 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/AbstractWiFiLEDDriver.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/AbstractWiFiLEDDriver.java @@ -213,5 +213,4 @@ protected byte[] getBytesForColor(byte r, byte g, byte b, byte w, byte w2) { protected byte[] getBytesForPower(boolean on) { return new byte[] { 0x71, on ? (byte) 0x23 : 0x24 }; } - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/ClassicWiFiLEDDriver.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/ClassicWiFiLEDDriver.java index 17cd49b2ba8e6..8ac0b3fcac6fb 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/ClassicWiFiLEDDriver.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/ClassicWiFiLEDDriver.java @@ -203,5 +203,4 @@ public static String bytesToHex(byte[] bytes) { String string = builder.toString(); return string.substring(0, string.length() - 1); } - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/FadingWiFiLEDDriver.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/FadingWiFiLEDDriver.java index 4d3f8d4d6a725..6f4b85d0cd254 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/FadingWiFiLEDDriver.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/FadingWiFiLEDDriver.java @@ -335,5 +335,4 @@ private void sendLEDData(InternalLedState ledState, DataOutputStream out) throws currentState = ledState; } - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/InternalLedState.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/InternalLedState.java index 58c8810f8c911..6a5a7c9460db0 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/InternalLedState.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/InternalLedState.java @@ -213,5 +213,4 @@ public int hashCode() { public String toString() { return "InternalLedState{" + "r=" + r + ", g=" + g + ", b=" + b + ", w=" + w + '}'; } - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/LEDState.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/LEDState.java index c4c87b07cf958..2fc6b6d2f6dcf 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/LEDState.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/LEDState.java @@ -30,5 +30,4 @@ public LEDState(int state, int program, int programSpeed, int red, int green, in this.white = white; this.white2 = white2; } - } diff --git a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/WiFiLEDHandler.java b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/WiFiLEDHandler.java index d790538f684fc..aa15eef390d8a 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/WiFiLEDHandler.java +++ b/bundles/org.openhab.binding.wifiled/src/main/java/org/openhab/binding/wifiled/internal/handler/WiFiLEDHandler.java @@ -12,6 +12,10 @@ */ package org.openhab.binding.wifiled.internal.handler; +import java.io.IOException; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + import org.eclipse.smarthome.core.library.types.*; import org.eclipse.smarthome.core.thing.ChannelUID; import org.eclipse.smarthome.core.thing.Thing; @@ -27,10 +31,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - /** * The {@link WiFiLEDHandler} is responsible for handling commands, which are * sent to one of the channels. @@ -66,8 +66,11 @@ public void initialize() { break; case FADING: - int fadeDurationInMs = config.getFadeDurationInMs() == null ? FadingWiFiLEDDriver.DEFAULT_FADE_DURATION_IN_MS : config.getFadeDurationInMs(); - int fadeSteps = config.getFadeSteps() == null ? FadingWiFiLEDDriver.DEFAULT_FADE_STEPS : config.getFadeSteps(); + int fadeDurationInMs = config.getFadeDurationInMs() == null + ? FadingWiFiLEDDriver.DEFAULT_FADE_DURATION_IN_MS + : config.getFadeDurationInMs(); + int fadeSteps = config.getFadeSteps() == null ? FadingWiFiLEDDriver.DEFAULT_FADE_STEPS + : config.getFadeSteps(); driver = new FadingWiFiLEDDriver(config.getIp(), port, protocol, fadeDurationInMs, fadeSteps); break; } diff --git a/bundles/org.openhab.binding.wifiled/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.wifiled/src/main/resources/ESH-INF/binding/binding.xml index fe88a50228879..1b796cd2e6bf1 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.wifiled/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - WiFi LED Binding diff --git a/bundles/org.openhab.binding.wifiled/src/main/resources/ESH-INF/thing/wifiled.xml b/bundles/org.openhab.binding.wifiled/src/main/resources/ESH-INF/thing/wifiled.xml index 0257fddc0de9e..493ef2465efe4 100644 --- a/bundles/org.openhab.binding.wifiled/src/main/resources/ESH-INF/thing/wifiled.xml +++ b/bundles/org.openhab.binding.wifiled/src/main/resources/ESH-INF/thing/wifiled.xml @@ -9,12 +9,12 @@ WiFi LED Device - - - - - - + + + + + + @@ -22,8 +22,7 @@ IP address or host name of the WIFI LED Controller - + Used Port of the device 5577 diff --git a/bundles/org.openhab.binding.wifiled/src/test/java/org/openhab/binding/wifiled/internal/handler/LEDStateDTOTest.java b/bundles/org.openhab.binding.wifiled/src/test/java/org/openhab/binding/wifiled/internal/handler/LEDStateDTOTest.java index 3fde8a1ee98ad..1eab99599fe2e 100644 --- a/bundles/org.openhab.binding.wifiled/src/test/java/org/openhab/binding/wifiled/internal/handler/LEDStateDTOTest.java +++ b/bundles/org.openhab.binding.wifiled/src/test/java/org/openhab/binding/wifiled/internal/handler/LEDStateDTOTest.java @@ -16,7 +16,6 @@ import static org.junit.Assert.assertThat; import org.junit.Test; -import org.openhab.binding.wifiled.internal.handler.LEDStateDTO; /** * Test for LEDStateDTO diff --git a/bundles/org.openhab.binding.windcentrale/pom.xml b/bundles/org.openhab.binding.windcentrale/pom.xml index 2901f59e75d85..4fc5b6e4f1467 100644 --- a/bundles/org.openhab.binding.windcentrale/pom.xml +++ b/bundles/org.openhab.binding.windcentrale/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.windcentrale diff --git a/bundles/org.openhab.binding.windcentrale/src/main/feature/feature.xml b/bundles/org.openhab.binding.windcentrale/src/main/feature/feature.xml index 6c5ad248f539c..cd28bc0600852 100644 --- a/bundles/org.openhab.binding.windcentrale/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.windcentrale/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.windcentrale/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.windcentrale/${project.version} + diff --git a/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleBindingConstants.java b/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleBindingConstants.java index 031b284eff30c..72b4b3f574819 100644 --- a/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleBindingConstants.java +++ b/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleBindingConstants.java @@ -49,5 +49,4 @@ public final class WindcentraleBindingConstants { public static final String PROPERTY_MILL_ID = "millId"; public static final String PROPERTY_QTY_WINDDELEN = "wd"; public static final String PROPERTY_REFRESH_INTERVAL = "refreshInterval"; - } diff --git a/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleHandlerFactory.java b/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleHandlerFactory.java index a7c643c825793..c20fea5fb55c1 100644 --- a/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleHandlerFactory.java +++ b/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/WindcentraleHandlerFactory.java @@ -49,5 +49,4 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { return null; } - } diff --git a/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/config/MillConfig.java b/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/config/MillConfig.java index 81338a8e33622..5aa2ccb630e8b 100644 --- a/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/config/MillConfig.java +++ b/bundles/org.openhab.binding.windcentrale/src/main/java/org/openhab/binding/windcentrale/internal/config/MillConfig.java @@ -36,5 +36,4 @@ public class MillConfig { * Number of wind shares ("Winddelen") */ public int wd = 1; - } diff --git a/bundles/org.openhab.binding.windcentrale/src/main/resources/ESH-INF/thing/millThing.xml b/bundles/org.openhab.binding.windcentrale/src/main/resources/ESH-INF/thing/millThing.xml index 9ba4cce01dd26..c83b0f06f43c6 100644 --- a/bundles/org.openhab.binding.windcentrale/src/main/resources/ESH-INF/thing/millThing.xml +++ b/bundles/org.openhab.binding.windcentrale/src/main/resources/ESH-INF/thing/millThing.xml @@ -8,16 +8,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -59,59 +59,59 @@ Number Wind - + String - + Number:Dimensionless Energy - + Number:Dimensionless Run percentage this year Energy - + Number:Time Run time this year - + Number:Power Energy - + Number:Power Energy - + Number:Energy Energy - + Number:Energy Energy - + DateTime - + diff --git a/bundles/org.openhab.binding.xmltv/pom.xml b/bundles/org.openhab.binding.xmltv/pom.xml index ae401dc97e092..a732ed98f9952 100644 --- a/bundles/org.openhab.binding.xmltv/pom.xml +++ b/bundles/org.openhab.binding.xmltv/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.xmltv diff --git a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/discovery/XmlTVDiscoveryService.java b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/discovery/XmlTVDiscoveryService.java index 2d4ec2669a092..3ac1afa2bbdf7 100644 --- a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/discovery/XmlTVDiscoveryService.java +++ b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/discovery/XmlTVDiscoveryService.java @@ -70,5 +70,4 @@ protected void startScan() { } } } - } diff --git a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/handler/ChannelHandler.java b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/handler/ChannelHandler.java index 55c342ca005f8..e8321599866ff 100644 --- a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/handler/ChannelHandler.java +++ b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/handler/ChannelHandler.java @@ -246,5 +246,4 @@ private QuantityType getDurationInSeconds(Instant from, Instant to) { } return null; } - } diff --git a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/handler/XmlTVHandler.java b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/handler/XmlTVHandler.java index 31fdb322044b8..f5fbff2067253 100644 --- a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/handler/XmlTVHandler.java +++ b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/handler/XmlTVHandler.java @@ -126,5 +126,4 @@ public void handleCommand(ChannelUID channelUID, Command command) { public Tv getXmlFile() { return currentXmlFile; } - } diff --git a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/jaxb/Programme.java b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/jaxb/Programme.java index d2b882358738a..0f386c483dcb1 100644 --- a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/jaxb/Programme.java +++ b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/jaxb/Programme.java @@ -88,5 +88,4 @@ public List getIcons() { public String getChannel() { return channel; } - } diff --git a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/jaxb/WithLangType.java b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/jaxb/WithLangType.java index 21f006da2bf21..a494b2bc5d225 100644 --- a/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/jaxb/WithLangType.java +++ b/bundles/org.openhab.binding.xmltv/src/main/java/org/openhab/binding/xmltv/internal/jaxb/WithLangType.java @@ -45,5 +45,4 @@ public String getValue() { public String getLang() { return lang; } - } diff --git a/bundles/org.openhab.binding.xmltv/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.xmltv/src/main/resources/ESH-INF/thing/thing-types.xml index 4969134297925..dbc89996c368a 100644 --- a/bundles/org.openhab.binding.xmltv/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.xmltv/src/main/resources/ESH-INF/thing/thing-types.xml @@ -28,15 +28,15 @@ - + This represent a channel on a given TV file - - - + + + @@ -65,8 +65,8 @@ Properties of the current channel - - + + @@ -74,15 +74,15 @@ Program currently on air on this channel - - - - - - - - - + + + + + + + + + @@ -90,13 +90,13 @@ Program which will follow current program on this channel - - - - - - - + + + + + + + @@ -104,70 +104,70 @@ String Icon URL of the TV channel. - + String URL to an image of the program. - + String Program Title. - + String Program Category. - + DateTime Program Start Time - + DateTime Program End Time - + Number:Time Current time of currently playing program. - + Number:Time Time remaining until end of the program. - + Number:Time Time left before program start - + Number:Dimensionless Relative progression of the current program. - + diff --git a/bundles/org.openhab.binding.xmppclient/pom.xml b/bundles/org.openhab.binding.xmppclient/pom.xml index 12133008b20b3..2457aae37f655 100644 --- a/bundles/org.openhab.binding.xmppclient/pom.xml +++ b/bundles/org.openhab.binding.xmppclient/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.xmppclient diff --git a/bundles/org.openhab.binding.xmppclient/src/main/feature/feature.xml b/bundles/org.openhab.binding.xmppclient/src/main/feature/feature.xml index efc53852539bc..6207675a23b63 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.xmppclient/src/main/feature/feature.xml @@ -1,23 +1,23 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - - mvn:org.igniterealtime.smack/smack-extensions/4.3.3 - mvn:org.igniterealtime.smack/smack-im/4.3.3 - mvn:org.igniterealtime.smack/smack-tcp/4.3.3 - mvn:org.jxmpp/jxmpp-core/0.6.3 - mvn:org.jxmpp/jxmpp-jid/0.6.3 - mvn:org.jxmpp/jxmpp-util-cache/0.6.3 - mvn:org.minidns/minidns-core/0.3.3 - mvn:org.igniterealtime.smack/smack-core/4.3.3 - mvn:org.igniterealtime.smack/smack-sasl-javax/4.3.3 - mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xpp3/1.1.4c_7 - - mvn:org.igniterealtime.smack/smack-resolver-javax/4.3.3 - mvn:org.igniterealtime.smack/smack-java7/4.3.3 - mvn:org.openhab.addons.bundles/org.openhab.binding.xmppclient/${project.version} - + + openhab-runtime-base + + mvn:org.igniterealtime.smack/smack-extensions/4.3.3 + mvn:org.igniterealtime.smack/smack-im/4.3.3 + mvn:org.igniterealtime.smack/smack-tcp/4.3.3 + mvn:org.jxmpp/jxmpp-core/0.6.3 + mvn:org.jxmpp/jxmpp-jid/0.6.3 + mvn:org.jxmpp/jxmpp-util-cache/0.6.3 + mvn:org.minidns/minidns-core/0.3.3 + mvn:org.igniterealtime.smack/smack-core/4.3.3 + mvn:org.igniterealtime.smack/smack-sasl-javax/4.3.3 + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.xpp3/1.1.4c_7 + + mvn:org.igniterealtime.smack/smack-resolver-javax/4.3.3 + mvn:org.igniterealtime.smack/smack-java7/4.3.3 + mvn:org.openhab.addons.bundles/org.openhab.binding.xmppclient/${project.version} + diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/action/XMPPActions.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/action/XMPPActions.java index 40c3979f30d5d..da7ce3baff1af 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/action/XMPPActions.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/action/XMPPActions.java @@ -17,8 +17,8 @@ import org.eclipse.smarthome.core.thing.binding.ThingActions; import org.eclipse.smarthome.core.thing.binding.ThingActionsScope; import org.eclipse.smarthome.core.thing.binding.ThingHandler; -import org.openhab.binding.xmppclient.internal.XMPPClient; import org.openhab.binding.xmppclient.handler.XMPPClientHandler; +import org.openhab.binding.xmppclient.internal.XMPPClient; import org.openhab.core.automation.annotation.ActionInput; import org.openhab.core.automation.annotation.RuleAction; import org.slf4j.Logger; @@ -47,8 +47,7 @@ public void setThingHandler(@Nullable ThingHandler handler) { } @RuleAction(label = "publishXMPP", description = "Publish to XMPP") - public void publishXMPP( - @ActionInput(name = "to", label = "To", description = "Send to") @Nullable String to, + public void publishXMPP(@ActionInput(name = "to", label = "To", description = "Send to") @Nullable String to, @ActionInput(name = "text", label = "Text", description = "Message text") @Nullable String text) { XMPPClientHandler clientHandler = handler; if (clientHandler == null) { @@ -69,7 +68,7 @@ public void publishXMPP( } public static void publishXMPP(@Nullable ThingActions actions, @Nullable String to, @Nullable String text) { - if(actions == null) { + if (actions == null) { logger.warn("Sending error, actions is NULL"); throw new IllegalArgumentException("actions is NULL"); } diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/PublishTriggerChannel.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/PublishTriggerChannel.java index 3344f35f42f52..a096b087fa8ff 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/PublishTriggerChannel.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/PublishTriggerChannel.java @@ -16,7 +16,7 @@ import org.openhab.binding.xmppclient.internal.XMPPClient; /** - * Subscribes to a chat and calls {@link AbstractBrokerHandler#triggerChannel(ChannelUID, String)} if a value has been + * Subscribes to a chat and calls {@link AbstractBrokerHandler#triggerChannel(ChannelUID, String)} if a value has been * received. * * @author Pavel Gololobov - Initial contribution @@ -27,7 +27,8 @@ public class PublishTriggerChannel implements XMPPClientMessageSubscriber { private final ChannelUID uid; private final XMPPClientHandler handler; - PublishTriggerChannel(PublishTriggerChannelConfig config, ChannelUID uid, XMPPClient connection, XMPPClientHandler handler) { + PublishTriggerChannel(PublishTriggerChannelConfig config, ChannelUID uid, XMPPClient connection, + XMPPClientHandler handler) { this.config = config; this.uid = uid; this.connection = connection; @@ -50,7 +51,7 @@ public void processMessage(String from, String payload) { return; } String eventValue = ""; - if(!config.separator.isEmpty()) { + if (!config.separator.isEmpty()) { eventValue = from + config.separator + payload; } else { eventValue = payload; diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/XMPPClientHandler.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/XMPPClientHandler.java index db04332938f0a..be5de1b40865d 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/XMPPClientHandler.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/XMPPClientHandler.java @@ -12,30 +12,27 @@ */ package org.openhab.binding.xmppclient.handler; -import org.jivesoftware.smack.*; - +import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; -import org.openhab.binding.xmppclient.action.XMPPActions; -import org.openhab.binding.xmppclient.internal.XMPPClient; -import org.openhab.binding.xmppclient.handler.XMPPClientConfiguration; +import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Channel; import org.eclipse.smarthome.core.thing.ChannelUID; -import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.ThingStatus; import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; import org.eclipse.smarthome.core.types.Command; +import org.jivesoftware.smack.*; +import org.openhab.binding.xmppclient.action.XMPPActions; +import org.openhab.binding.xmppclient.internal.XMPPClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; - /** * The {@link XMPPClientHandler} is responsible for handling commands, which are * sent to one of the channels. @@ -97,8 +94,9 @@ private void doConnect() { return; } - for(Channel channel : thing.getChannels()) { - final PublishTriggerChannelConfig channelConfig = channel.getConfiguration().as(PublishTriggerChannelConfig.class); + for (Channel channel : thing.getChannels()) { + final PublishTriggerChannelConfig channelConfig = channel.getConfiguration() + .as(PublishTriggerChannelConfig.class); PublishTriggerChannel c = new PublishTriggerChannel(channelConfig, channel.getUID(), xmppClient, this); channelStateByChannelUID.put(channel.getUID(), c); logger.info("XMPP added channel {} payload {}", channel.getUID().toString(), channelConfig.payload); diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/XMPPClientMessageSubscriber.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/XMPPClientMessageSubscriber.java index c55629058168b..8ffc1c78dd16e 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/XMPPClientMessageSubscriber.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/handler/XMPPClientMessageSubscriber.java @@ -19,5 +19,6 @@ */ public interface XMPPClientMessageSubscriber { public void processMessage(String from, String payload); + public String getName(); } diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClient.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClient.java index 07553aba4c300..93bac0845c54f 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClient.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClient.java @@ -12,6 +12,10 @@ */ package org.openhab.binding.xmppclient.internal; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + import org.jivesoftware.smack.*; import org.jivesoftware.smack.chat2.Chat; import org.jivesoftware.smack.chat2.ChatManager; @@ -21,16 +25,10 @@ import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity; - import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.stringprep.XmppStringprepException; import org.openhab.binding.xmppclient.handler.XMPPClientMessageSubscriber; - -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,11 +53,11 @@ public void unsubscribe(XMPPClientMessageSubscriber channel) { subscribers.remove(channel); } - public void connect(String host, Integer port, String login, String domain, String password) + public void connect(String host, Integer port, String login, String domain, String password) throws XMPPException, SmackException, IOException { disconnect(); String serverHost = domain; - if((host != null) && !host.isEmpty()) { + if ((host != null) && !host.isEmpty()) { serverHost = host; } @@ -90,17 +88,17 @@ public void connect(String host, Integer port, String login, String domain, Stri } public void disconnect() { - if(connection != null) { + if (connection != null) { connection.disconnect(); } } public void sendMessage(String to, String message) { - if(connection == null) { + if (connection == null) { logger.warn("XMPP connection is null"); return; } - if(chatManager == null) { + if (chatManager == null) { logger.warn("XMPP chatManager is null"); return; } @@ -116,7 +114,7 @@ public void sendMessage(String to, String message) { @Override public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) { logger.debug("XMPP {} says {}", from.asBareJid().toString(), message.getBody()); - for(XMPPClientMessageSubscriber subscriber : subscribers) { + for (XMPPClientMessageSubscriber subscriber : subscribers) { logger.debug("Push to subscriber {}", subscriber.getName()); subscriber.processMessage(from.asBareJid().toString(), message.getBody()); } @@ -140,7 +138,7 @@ public void connectionClosed() { @Override public void connectionClosedOnError(Exception e) { logger.debug("Connection to XMPP server was lost."); - if(connection != null) { + if (connection != null) { connection.disconnect(); try { connection.connect().login(); diff --git a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientHandlerFactory.java b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientHandlerFactory.java index e193f95e5cc06..6daf6409c7c35 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientHandlerFactory.java +++ b/bundles/org.openhab.binding.xmppclient/src/main/java/org/openhab/binding/xmppclient/internal/XMPPClientHandlerFactory.java @@ -15,14 +15,14 @@ import java.util.Collections; import java.util.Set; -import org.openhab.binding.xmppclient.XMPPClientBindingConstants; -import org.openhab.binding.xmppclient.handler.XMPPClientHandler; import org.eclipse.smarthome.core.thing.Bridge; import org.eclipse.smarthome.core.thing.Thing; import org.eclipse.smarthome.core.thing.ThingTypeUID; import org.eclipse.smarthome.core.thing.binding.BaseThingHandlerFactory; import org.eclipse.smarthome.core.thing.binding.ThingHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerFactory; +import org.openhab.binding.xmppclient.XMPPClientBindingConstants; +import org.openhab.binding.xmppclient.handler.XMPPClientHandler; import org.osgi.service.component.annotations.Component; /** @@ -33,8 +33,8 @@ */ @Component(configurationPid = "binding.xmppclient", service = ThingHandlerFactory.class) public class XMPPClientHandlerFactory extends BaseThingHandlerFactory { - private static final Set SUPPORTED_THING_TYPES_UIDS = - Collections.singleton(XMPPClientBindingConstants.BRIDGE_TYPE_XMPP); + private static final Set SUPPORTED_THING_TYPES_UIDS = Collections + .singleton(XMPPClientBindingConstants.BRIDGE_TYPE_XMPP); @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { diff --git a/bundles/org.openhab.binding.xmppclient/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.xmppclient/src/main/resources/ESH-INF/thing/thing-types.xml index 84d9d7d0ee19f..b9841ddce73f1 100644 --- a/bundles/org.openhab.binding.xmppclient/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.xmppclient/src/main/resources/ESH-INF/thing/thing-types.xml @@ -37,7 +37,8 @@ trigger - This channel is triggered when a message is received on the configured XMPP account. The event payload will be the received text. + This channel is triggered when a message is received on the configured XMPP account. The event payload + will be the received text. @@ -46,7 +47,9 @@ - The trigger channel payload usually only contains the received text. If you define a separator character, for example '#', the sender UID and received text will be in the trigger channel payload. For example: pavel@example.com#My Message Text. + The trigger channel payload usually only contains the received text. If you define a separator + character, for example '#', the sender UID and received text will be in the trigger channel payload. For example: + pavel@example.com#My Message Text. diff --git a/bundles/org.openhab.binding.yamahareceiver/pom.xml b/bundles/org.openhab.binding.yamahareceiver/pom.xml index 4f2616067c6b8..3f92a5a4f3049 100644 --- a/bundles/org.openhab.binding.yamahareceiver/pom.xml +++ b/bundles/org.openhab.binding.yamahareceiver/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.yamahareceiver diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/feature/feature.xml b/bundles/org.openhab.binding.yamahareceiver/src/main/feature/feature.xml index 86572608dbfb3..780981e96c3f0 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - mvn:org.openhab.addons.bundles/org.openhab.binding.yamahareceiver/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + mvn:org.openhab.addons.bundles/org.openhab.binding.yamahareceiver/${project.version} + diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/ChannelsTypeProviderPreset.java b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/ChannelsTypeProviderPreset.java index f80b99ec21dc0..848498eaad275 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/ChannelsTypeProviderPreset.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/ChannelsTypeProviderPreset.java @@ -104,5 +104,4 @@ public void setThingHandler(ThingHandler handler) { public @Nullable ThingHandler getThingHandler() { return this.handler; } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/handler/YamahaBridgeHandler.java b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/handler/YamahaBridgeHandler.java index 7156d6d8c7be4..45c25b7a2b488 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/handler/YamahaBridgeHandler.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/handler/YamahaBridgeHandler.java @@ -34,7 +34,6 @@ import org.eclipse.smarthome.core.thing.ThingStatusDetail; import org.eclipse.smarthome.core.thing.binding.BaseBridgeHandler; import org.eclipse.smarthome.core.thing.binding.ThingHandlerService; -import org.eclipse.smarthome.core.thing.binding.builder.ThingStatusInfoBuilder; import org.eclipse.smarthome.core.types.Command; import org.eclipse.smarthome.core.types.RefreshType; import org.openhab.binding.yamahareceiver.internal.config.YamahaBridgeConfig; @@ -224,6 +223,7 @@ private void setupRefreshTimer(int initialWaitTime) { private void cancelRefreshTimer() { if (refreshTimer != null) { refreshTimer.cancel(false); + refreshTimer = null; } } @@ -255,13 +255,8 @@ void updateAllZoneInformation() { YamahaZoneThingHandler handler = (YamahaZoneThingHandler) thing.getHandler(); // Ensure the handler has been already assigned - if (handler != null) { - // If thing still thinks that the bridge is offline, update its status. - if (thing.getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_OFFLINE) { - handler.bridgeStatusChanged(ThingStatusInfoBuilder.create(bridge.getStatus()).build()); - } else if (handler.isCorrectlyInitialized()) { - handler.updateZoneInformation(); - } + if (handler != null && handler.isCorrectlyInitialized()) { + handler.updateZoneInformation(); } } } catch (IOException e) { @@ -358,7 +353,8 @@ public void initialize() { @Override public void onConnectionCreated(AbstractConnection connection) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, "Waiting for connection with Yamaha device"); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_PENDING, + "Waiting for connection with Yamaha device"); this.connection = connection; this.systemControl = null; @@ -372,6 +368,7 @@ public void onConnectionCreated(AbstractConnection connection) { /** * Attempts to perform a one-time initialization after a connection is created. + * * @return true if initialization was successful */ private boolean ensureConnectionInitialized() { @@ -402,7 +399,9 @@ private boolean ensureConnectionInitialized() { private void onConnectivityError(Exception e) { String description = e.getMessage(); - logger.debug("Communication error. Either the Yamaha thing configuration is invalid or the device is offline. Details: {}", description); + logger.debug( + "Communication error. Either the Yamaha thing configuration is invalid or the device is offline. Details: {}", + description); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, description); } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/handler/YamahaZoneThingHandler.java b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/handler/YamahaZoneThingHandler.java index 3f3f3ce689cea..0cdd22debafbe 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/handler/YamahaZoneThingHandler.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/handler/YamahaZoneThingHandler.java @@ -169,22 +169,8 @@ public void initialize() { zoneConfig = getConfigAs(YamahaZoneConfig.class); logger.trace("Initialize {} with zone '{}'", getThing().getLabel(), zoneConfig.getZoneValue()); - if (zoneConfig.getZone() == null) { - String msg = String.format("Zone not set or invalid zone name used: '%s'. It needs to be on of: '%s'", - zoneConfig.getZoneValue(), Arrays.toString(Zone.values())); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); - logger.warn("{}", msg); - return; - } - - YamahaBridgeHandler bridgeHandler = getBridgeHandler(); - if (bridgeHandler != null) { - bridgeStatusChanged(bridgeHandler.getThing().getStatusInfo()); - } - } - - @Override - public void dispose() { + Bridge bridge = getBridge(); + initializeThing(bridge != null ? bridge.getStatus() : null); } protected YamahaBridgeHandler getBridgeHandler() { @@ -205,23 +191,40 @@ protected AbstractConnection getConnection() { @Override public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { - if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) { - if (zoneControl == null) { - YamahaBridgeHandler brHandler = getBridgeHandler(); + initializeThing(bridgeStatusInfo.getStatus()); + } - zoneControl = getProtocolFactory().ZoneControl(getConnection(), zoneConfig, this, - brHandler::getInputConverter, getDeviceInformationState()); - zoneAvailableInputs = getProtocolFactory().ZoneAvailableInputs(getConnection(), zoneConfig, this, - brHandler::getInputConverter, getDeviceInformationState()); + private void initializeThing(ThingStatus bridgeStatus) { + YamahaBridgeHandler bridgeHandler = getBridgeHandler(); + if (bridgeHandler != null && bridgeStatus != null) { + if (bridgeStatus == ThingStatus.ONLINE) { + if (zoneConfig == null || zoneConfig.getZone() == null) { + String msg = String.format( + "Zone not set or invalid zone name used: '%s'. It needs to be on of: '%s'", + zoneConfig.getZoneValue(), Arrays.toString(Zone.values())); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, msg); + logger.info("{}", msg); + } else { + if (zoneControl == null) { + YamahaBridgeHandler brHandler = getBridgeHandler(); + + zoneControl = getProtocolFactory().ZoneControl(getConnection(), zoneConfig, this, + brHandler::getInputConverter, getDeviceInformationState()); + zoneAvailableInputs = getProtocolFactory().ZoneAvailableInputs(getConnection(), zoneConfig, + this, brHandler::getInputConverter, getDeviceInformationState()); + + updateZoneInformation(); + } - updateZoneInformation(); + updateStatus(ThingStatus.ONLINE); + } + } else { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); + zoneControl = null; + zoneAvailableInputs = null; } - - updateStatus(ThingStatus.ONLINE); } else { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); - zoneControl = null; - zoneAvailableInputs = null; + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED); } } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/InputConverter.java b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/InputConverter.java index 15e89c1040a3a..d86d50a8e974a 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/InputConverter.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/InputConverter.java @@ -37,5 +37,4 @@ public interface InputConverter { * @return canonical name */ String fromStateName(String name); - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/SystemControl.java b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/SystemControl.java index 1e66027a57ac6..e148eb7257377 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/SystemControl.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/SystemControl.java @@ -56,5 +56,4 @@ public interface SystemControl extends IStateUpdatable { * @throws ReceivedMessageParseException */ void setPartyModeVolume(boolean increment) throws IOException, ReceivedMessageParseException; - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/XMLConstants.java b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/XMLConstants.java index da69508d767b5..a0b3f3b63c66d 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/XMLConstants.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/XMLConstants.java @@ -57,5 +57,4 @@ public static class Commands { FEATURE_BY_YNC_TAG.put("USB", Feature.USB); FEATURE_BY_YNC_TAG.put("NET_USB", Feature.NET_USB); } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/state/AvailableInputState.java b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/state/AvailableInputState.java index 74784c3330dc3..87df6bc9f4347 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/state/AvailableInputState.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/state/AvailableInputState.java @@ -24,5 +24,4 @@ public class AvailableInputState { // List of inputs with public Map availableInputs = new TreeMap<>(); - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/state/DeviceInformationState.java b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/state/DeviceInformationState.java index 13bfc7e2426d9..ef8941268fbac 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/state/DeviceInformationState.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/java/org/openhab/binding/yamahareceiver/internal/state/DeviceInformationState.java @@ -53,5 +53,4 @@ public void invalidate() { features.clear(); properties.clear(); } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.yamahareceiver/src/main/resources/ESH-INF/binding/binding.xml index 75f175ef448fd..a6a9805b62081 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/resources/ESH-INF/binding/binding.xml @@ -1,6 +1,6 @@ - YamahaReceiver Binding diff --git a/bundles/org.openhab.binding.yamahareceiver/src/main/resources/ESH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.yamahareceiver/src/main/resources/ESH-INF/thing/thing-types.xml index 1473b13479651..3217a76a26e8b 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/main/resources/ESH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.yamahareceiver/src/main/resources/ESH-INF/thing/thing-types.xml @@ -7,19 +7,20 @@ Yamaha Receiver of product line CX-A5000, RX-A30xx, RX-A20xx, RX-A10xx, RX-Vxxx, RX-Z7, DSP-Z7, - RX-S600, HTR-xxxx + RX-S600, + HTR-xxxx - - - - + + + + - - + + host @@ -46,7 +47,8 @@ When the album image is not provided by the Yamaha input source, you can specify the default image - URL to apply. + URL + to apply. data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD//gBKRmlsZSBzb3VyY2U6IGh0dHBzOi8vY29tbW9ucy53aWtpbWVkaWEub3JnL3dpa2kvRmlsZTpSZWNvcmQtQWxidW0tMDIuanBn/+ICHElDQ19QUk9GSUxFAAEBAAACDGxjbXMCEAAAbW50clJHQiBYWVogB9wAAQAZAAMAKQA5YWNzcEFQUEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAAA0y1sY21zAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKZGVzYwAAAPwAAABeY3BydAAAAVwAAAALd3RwdAAAAWgAAAAUYmtwdAAAAXwAAAAUclhZWgAAAZAAAAAUZ1hZWgAAAaQAAAAUYlhZWgAAAbgAAAAUclRSQwAAAcwAAABAZ1RSQwAAAcwAAABAYlRSQwAAAcwAAABAZGVzYwAAAAAAAAADYzIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdGV4dAAAAABGQgAAWFlaIAAAAAAAAPbWAAEAAAAA0y1YWVogAAAAAAAAAxYAAAMzAAACpFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z2N1cnYAAAAAAAAAGgAAAMsByQNjBZIIawv2ED8VURs0IfEpkDIYO5JGBVF3Xe1rcHoFibGafKxpv33Tw+kw////2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAClANwDASIAAhEBAxEB/8QAHAAAAAcBAQAAAAAAAAAAAAAAAAECAwQFBgcI/8QAQxAAAgEDAQUFBQYCCAUFAAAAAQIDAAQRBQYSITFBEyJRYXEHMoGRoRRCUrHB0WJyIzNDgpKi4fAIFRYkUzSDstLx/8QAGgEAAgMBAQAAAAAAAAAAAAAAAgMBBAUABv/EACwRAAICAQMDAwMEAwEAAAAAAAECAAMREiExBCJBUWHwE3HBMqGx4QUzgUL/2gAMAwEAAhEDEQA/APMv3vIgGiPM8uQ50XUcuooxksAOZGPGr0RFDiT54NK6nx4VJi0+6kQydj2cIHGSU7ij4molxLFESI5O2fqwBC/XifkKIqVGW2gBgxwu8cHM+AP6U20yL1zx6VDeRn5n4dKRSzb6Rgr9ZKN1gd1R8eNINxIevD5UxR0OsmHpEWZGPWiLsebH50mjrskzsQ8k9TQ+NFR4NEJ0Ug8zVpYouRnBHmAarUiZjwFXOkQRqQJn3RnjVmhSWAxK/UMAssZBB9mKmGDOPeCYPzBqkeR4JC0EjoR1ViD8xxq42jdGjjFowYAccDBrMtI59459aude4DaAOPMrdIhZdR8y8s9p9XtSNy+mYeEh7Qf5uP1q+stvpwAt9aQSjq0ZMbfLiKwy8VzxFGaqL1FicNHP0lL8rN7/ANRWjast7au8OcFllXGCOB4jgRXR7FvtunpexRObdju74GVDeGeVeeVZlPdJFXOgbT6toUu/pl9PbZ95Y2yjfzIe6flVivriP1iVbf8AHBt1M7kIFI4AVValazjUY7i3z3YuzwOB5/WqjQvaVZ3m7HrtkIZDwN1YjA9Wi/8Ar8q3Nsba+tBdafcQ3lqf7SI5x5MOYPrV5bVtHaZSNL0nuG0xGsWtnPazSXmnWzzKhYSGLdcEDhxqPtTawS6Js/b3qs9uRGxCtulid/Iz6YrSbVssWiXu4B/VFfnw/WqjaPThfX+l2rM4SFLbgPHcz+tLtXsYDk4nfUGtD4GfxK620nRLbjBo1qX8ZWaX6E4rQaal5cz26Kewt4mDbiKEUAdAorQR6ZEGPAk56cPyqakEVun3Yx58KBatJ5/EY9oYY5jSxnwpE00cT7r53sdBmmtQ1e2tEbDZbHx+X6ms8bLWNWJu4DHFE3BQ7lSR48q5798JuYtaM7tsJzW30GAEGeSSU+A7o/ejvb+w0cGOCCNrn8Cjl/Mf051C1vXsb1vp7eTTD8l/esyck5J41Tu6lKu2gb+sv09NZd3Xk49JL1DUbnUJN65kLAckHBV9BUShQrNYljljkzTVQgwowIKFHRVEKCjoUKkSIdChRgUwSIKUCPCiApQx4kUQkRyJ+QCk1bWdtLMO4VX+Y4qqjYD7zE1ZRiRYTJ2fcHNt7GPrVqjGreVr8+I3cOI2KSEAiojhW5EGnJnEvVW9TTAG70IobGyYSLge8PGBimiDSyxzw+lDIxSjGjaN8RQ50sqCOFIKEUJkwxkEHrVro+tXumXIntLiWCXl2kRwSPAjkw9aqVJHPlTygEZFSrFTkQXUEYM6tee0W62h2fGkXul6T2knZxrewQFJcBgTnieJxx5VN2z1BtL2vhVJFRY5Y99DjDhY4xjPTrXNdkITPtPp8SgnfkHAdeI6VvNvZ7RduZDfQLPGs0rMB76gSbuR4+7yq8js1ROd8zKuRRcARkAfP4mll2jmmyIYkTPRCz/lTCjVL5v6OORQep7o/etjp0NleWkV3ZMk1tKMpIpyD+xHUdKsUtlX3RgelOKFuTA+oB+kTJ6ZsyqOJb5u1ccQn3Qf1+NaRYd1QAOFTlh408sIxyqVATYRTFnO88Y0dChisCejgFHRUK6dBR0VHRCRBR0KMDNGBIgoCnkhzxY/AU+qqg5BaYFgFwJFWN25KxpYgkP3R860+jbJa/rIDabo97PGeUnZ7qf4mwK1Np7H9rZlBkgsbfylulz9M05aGPiKN85pFE6sMgfOrCaVltQisxzzWuhv7F9qlXKvpbnwFzj8xVVqXsx2wslLNo0k6L1tpFl+gOacqOgOBFM4Ygmc8IO9xBB8xSmOMAVZXtrPZTmC9gmt5h/ZzIUb5GoxhUngMHyquVIjhYDzI2KQw4cONOzIy8xlfEU0OFAYwHO8IEjzp1MMKLAbHQ9MdaG6QeHP86icd4sxg9KTgoeHOnYm3ufP8qcaPI5VOIvVjYzS+yuH7X7QtHjGQe2QcP5hT3tLmMm2VxIrYPekBHTeldv1qf7CbcP7SbBm4iJu0+ABb9Ko9s27Taa6BOWRIkPruA/rVjij/spnfqT6afz/AHLrYPa250K8JUGW2cg3Frng4/Gngw/0Nd/064ttRsIb2wlE1rMN5HH1BHQjkR0ryhEWRlZCQwOQfCuk+zTa/wD5Hd7tyWOlzsBcxjiYX/8AIo/MdR5imU2k7GJur0nIncVi606sPCpSIrKrIyujAMrKchgeIIPhinBFw4YppMWBPDXZGkshFTu2QjmKYkYMeFZpUTaVieRI2KGKkxIGyTRMg7xHIcKDRC1eJHxR4p5Ii65ojC1donahGwCTT8SUmNa2ns02RfazXhBIWTTrcCS6kXnu9FHmadVWWIUcxdjhRkwbC7C6ptbLvWwFtp6HEl3IO6PJR9413nZXYHZ3ZpUeGzW7vRzuroB2z5DkvwrR2sEFhZw2llCkNvEu7HGgwFFOqOprWroWsbcyizluZI7ZmAHQchRqX/FimhShIB1phkR0b34jTis4NNLID1p1TmhMmI1GxsNYtjbavZW95Cfuzxh/keYrk+2vsRikjku9jpTHIO8bCd8q3kjniD5H512BBmpMJKHypLqG5hCeJry0uLK7mtb2CS3uYm3JIpFwynwIqDcWuMvEPVa9b+1b2fW+2Wkvd2SJHr1shMMgGO2Uf2bePkehry4YnjkZJEZJEJVlYYKkcCDVRqoX1ChzKNR15jqKeUbwwefQ+NP3lv2bh1HcbmPA00q8cePL1qsRpODH6wwyIjdIOeo+tSYe8BRFcqHAOfD9KOIbsgA+9y9en7VI2gscidH9gcQ/6v1C5I/9PaXMn+GFqxe1UmdrNVYclm3MeSgD9K6J7Abdiu1F/uN2aWcke9jhvSOqAZ8cMa5xtBiTXdTlXk93Kf8AOcU5/wDSuPf5+8rV/wC98+3z9pHC8ARyNSrKb7PMJD7nuyDxHj8KYtOKsjchxHp1/enlGD3h5NQp6iS+N1M757HNoTNE2z95Jl4VMlk7H3o+sfwzkeR8q6gEOK8r7NahPZSQXNsxF1p8gdDnmvQfEZWvVGi3kWsaVbX9qQYp0Djjyz0qy3AMqIdyp8TwUDR5pAo6yQxm9iLDHPOj3jypsUYogxnYjiysvAHhS1lY5HjTFOQDL48qJWJgkCSY18a9LexbSk07YW2n3QJr5muJD1xnCj5D615tVcj4V6m9mc63GwOiPHyWDsz6qSDWn0Q3JlG85xNGOLE04KbXmfWnBV8xIiSSSAOZqZDAgGWBbhk45momCrq2OVTc9pEwU8wV+BGKEyRMpsZtgNo9R+xPpz20nYPO4IYdgQ+6ImLAbzle9w4DPXnWuki3OK8vCq7RtCisboT78rFARGrybwXIxnlzxVxMw3d0cSaWdjtCA9YUQyKlIlNQJgCpiLgcaUxhAR60BBwOnKvNft60CPSNvpLi3QLBqUQusAcA/J/qM/GvTVqneriH/EvuPrOz8Q/rEtpWb0LDH5GlA5bEG7ZMzhlxb79u646ZHwqoC90VrUt+4xI4bp/Ks0qd08KTcu4g9OxwYI1yT5gN+9IK4U/wmpUCd6P+Vv8A5U3OuEmPguaXp2jA287/AOxe33PZQ7HgZpAD/ekPGoG1/sF1COeaXZzVLe9Ejswt7sdjIOOeDjKn1O76VX+yDbFf+W6Ts09kXinmhWOeDLOHDDIZPDnxHL0r0siZdnb3mPrgeFMyCokEEMZ4h1vZnXNmLtE17SbyxG9jfljJRgfBxlT86ivHh8Ecxg+o4V6K9t+s2etpNshDtJY6UbZklvFuYpnWRiMqm9GpC44E5HMjwrk11sHrbQmfTEtNbhTvPJpFytyVGBkmMf0g455rXVkcGLtDbECZzR3KX8PTtVMZ9eY+o+tdl9nO0Z0/Z9rN7hYhBOyoGP3SAwx6Zx8K4qMwMWIKvBMrFSMFSGGQR051or2x7W4Yh2ULw4HHXP61cRNS4EzbbAj5Pn5+ZyKhQoVgiepgoxQoVInQ6XE27IpPKkgUKYoxBMtUFdo9g20KBbjZ65fDljPa5PvfiX9a4nYyh13G99eXmKs7SWW2uIri2kaKeJg6OpwVI61o9O+k6hKFoPBnrl0wcilqM1iPZ57QbTaOKOy1N47XWAMYY7qXHmp6HyremEqeAwfA1oZzEiJCDFLWPB7pxQXI5inkxQkwhAqv+I1IijA50SCpCYzS2MMCOxJUqNcnFNRITyFT4kWNGeQqqKMszHAUeJPSkM2IYEdgQIpZyFUDeZjyA6mvL3tI1obU7aXl/CSbRMW9t5ovX4nJrf8AtP8AaCmpQy6Js7KTaN3bq8Xh2g/Anl4nrXMYrYKBgYHSoRSNzK1zhthxKfUALexlbqV3R6nhWWEWEGaudb1Jbi77CDDQRni34j1NRIhHK3f4Ko3m9P8AfCgbubaQDpXeMwwkOOHuoB8Tx/ao1+u5a3LeQWrhYtyJnYd5iWP7fl8qg6hazTW8dtbRPNczOqJGgyzsxwFA6nlROulDFVWarAPeaT2EbJajtJrt/cW17e6fZ6ZAZ5Lu1n7F0kx3VRyCFY8cnHIEHnXZdoNtNrNgdJhvNVurPXLGdhFbyX1ubS8ViuQwKZSVV6n96tPZnsvZ6XsdpOmaVPDcB0Nxfyq26xmPFwQcHgAEHgFPWvP/ALcduztXtofsjiXS9Ozb2oPBXxwZ8D8R+gFVTpSoHkn9pfBd7TttKDULue+vJ7m5kaWaZ2lkdubsTkk/OrOHfgS3mhd4pk3CskbFWU4PEEcRVHZym5txMybpOeANaC4UxhU6qwU5/hUL+YNW6FGmZ3UudYHBj20Ot3+tW+9qtw11cQRlRcSgGVl4EBnxvPjHNiTVzcZEnqqn/KKydy2YJhjixCj4kCtrcwE3Eij7mF+QFW+nXkD2/MzetfdS3v8AicNoxRUBXnBPZQ6OhR4pgEiGvhSt0n1/OkgcccjT8eCN1udNUQScREeQQykhhxBq2tLlZMLJ3X+hqAUwcngfxdD6+FKxjgw401GKcRFgDiXQHzHEeIrfbK+1HXdESO3vCuqWa8Ak5xIo8n/fNcuiupIuHvr4GpkV7C/vEofOrSXDwcSo1TLvPSWje1fZi/CreSXGmynms8e8ufJlz+Va6x2g0C9ANrrWmyZ8LhQfkcV5KiKsMqwI8jUkQjdXKg/CnhsxRtK8z1+t1pwXeN/ZBfE3CfvUa62p2asFJutc01MdFmDt8lzXk1IFz7g+VTYIOWFA+FdpzAbq9PAnoLVfa/odqrJo9rdanL0Yr2UWfU8T8q53tJtlru1BMd/OIbLPC0t8qn97q3xrKQta2yA3E8SfzNx+VMXO0lrD3bOJ55PEjdX96WdKmdqssGTL6KNY4y7lUjUcWJwAKzeu679pRrXTiRGeDy8i3kPAVVX1/d6gR9qlxGOUa8APhTcUZZTu4SNfedjhR6n/AGaAsW2E7AXcxuOIkqkalmJwMdasLO2D4IwYUOSw5SMPD+EdPE8actbTfXiGWE8GY8GkHhj7q+XM9alu2/mOHCoo7zdFH706uvG5lW2/JwPnz5vGG78hJ/q04t5noKk6NqF3ouo2e0FrEssun3Hbxxsm+JCqnJI/CN4ZPTIxTcEP2p+zQmO2iwZHAyRnwHVjyA/SrjU76LZ3R3vHjAnKiKCHOd3mQuevVmPU5o2rDqdRwPJiRc1TroGWJ2E1W1Xtt0LXNjb8zbNxR7RzxmATxuUhIZSN9t1gWIzwU548civPEK9o+CfWmpWeWZ5ZCC7sWY4xknnVnpduYy0kq4PIAj61gompsCeodtC5MvNIEbdju4McY3m9BxwasJ5Dv97mo4+p4mqqG2MSdvBIYZW7xHNSvQEeZ/KjE8xO5NHhmOSynINaiOUXBExbKw7llMtdKh+2atp9t/5J1Zv5R3jVxrM9/JfM1hGWQ8X8mJJH+UrTGxsBaW+1B+6kSfZYj/G/vH4Ln510X2d6fFe6A99Io/7ud5VB6JwVf8qimszLUNBwSf2EqhVfqDqGQo/c/wBfxPMooUKOsUDM9TAKWtIpa8DTUgmPCLI6/qKNVxgMPQinYsHHjT+4DnkPyNPC5iC+NjGkOBx4jxpWAR3SMeB5f6Ul42TiOHry+f70jOD3gVP513HMHGdxDK46FfqKWoz03h5caCMQeBBp1ShP9ImD44xXAAyCSI/YRh5VAGTnlVrqTt3QCyEDHOmdMUxyrNEC+70YkindRL3MpdyqZPu4zWig00keTKFjarR6CV/bz9J3+Bo9+R/fmkP9404sAz70Z/un96kxW4/HGP8A2gfzzVQho3UviR4kjJAUbzeHM1J7Nl94LEp/Gd3Pw50//RBcPO5XwD7o+QxS4ZI0/qIcn8QHP40SpF2XHGwhQWu9xVC/8UmUX5e8fpU5Y4od15mEjr7uRhV/lUcqimZz78ioPBeJo4WZyTbRlsc5WPAerHgKsLgcSk+puT8+8mSSs4zITHH4feb9qOCJ7sJugxW2cAqMlj4KPvN58h1NLs9OMh7SXEnXefIjHw5t9B61bI6Q8UJaQjBduePAdAPIcKsJWW3MqPaqbLuY/axR2ka5RVKZKRg5CE82J+8x6n4DArK7ewXV+tr9nCyJFvFkDd7Jxxx8KtLzUAgbDAnqegrN39+0pKqTg8z40HUshrNcPoarBcLvImesrZjLvyqQqnkepq4t07V8tncXnjr5Cm40aVjg4A4sx6VJJCKEQYx9PM+ZrNrQKJtW2FzHJX3mxwwDk45Z/YcqaG+7qsSl5pGCRqOZJ5CkMRg8QFHM1q9krJbG1bX78iLCN9k3vuKPemPpyXxPpTUBtbSJXtYdOmo/89zJOsQjTNIs9BtTv3EpMTlfvO2O1b8kHr5Vu01Sy2ctbXTpphG0cQOAfX9QaxuxVudR1S416+Ux21uN2FX+6By+I4k+Z8q6TsJ7KLT2i6K+020N1c2v2yd/sUceB/2y4VGIPiQ59CKm7qAvcOOB9hF0dMQNLc8n7meTyMUdTr2ye0k3Jgdz7r/vUSSJo+fEeNUChU4m6rhhkRIFHjHp40VOxnxHA1KjMkmCOQp5ipcUob9qYMAIyhA/L59PjTZRkOGBBpoysWQrS0Qg5wfhSTGp5DHpy+VQklZefGpEdwDzOPWj1gxJrI4ivs2TwHyOPoaWkUqHgT8Qf0zS45FP+hqZbsCRg0SoDxFO7DmWeiws8DybxjKg5KkVAvSzSH+jd/PjU6Id3OaIxRsctGhPjir1mSgUTPVsOWMqlRieEEnyNSEhm4Ys5CPNTVikMWf6pPlUhIYQeEEOf5BVf6RjD1A9JVokwPBYUPmy5Hw4mpUdlPLjed2H8CHHzbH5VZKwQcCqjwGBSvtEYPFyfSmrUPJlZ72P6RGrfS0XBkCZ8XO+flwFWCpEmCF32XkX449ByHwFV8uoJGOg/mNV1zq2chSW9OApv1K64n6Vtx3l9PeKpO82T4Cqm91TA3c/3RVLNeSSZ47o8BTKK8hO4pOOZ6D1NIs6otsJbq6FU3aPXFy8p7xwPAUmKJpMEkqh69T6ClrEkY3pCGP0+XX8vWiklLZ5gcsnmf8AfhVY5O7S4ABssdLBQFjAGPjj9z500W545dTTTyADJO6orRaBs59ojS/1oNBp+N+ODO684HU59xPFj8KlVaw6VgWWJSupzBsvoY1Ii91BWXSo2wF5NcuPuL5Dq3QVNvbmfazWEsbEgWSMN90GEIXgMD8C8lHU8ajarqtxtFcrpukIEswvZlkG6hQfdUfdj+rVprSEbP2cGn6VbveaxeOIoYYx35ZDwAHh+gppKhSint8n19hEIru4tsHd/wCR6e59/n2vtK0B9p9b07YrSMx2W72upXC/2Nsp73H8THujzOeleqLS2gtLSG2tYlhtoEWKKNRwRFGAo9AKxnso2Jj2K2faK4dLjW75hPqNyvJ5McEU/gQHA+J4ZrdDlWdY5dszRrTSMTwHELbU7Ue62Rkjn8vKs/qOmS2DEopktz05kVp9Z2emsp2u9HXHHee3BwD5p4Hy/wDyollqsN2jR3A3XHdYMMYPgw6VuW0Bzos7W8HwZm1WlBrqOV8jyJkjbJKu/bsP5Ty/0psIUbdYFH8D1rTaloJZjPYNuOeO7ng1UrzGNuw1CHcI/EOH+lZ1lBqOHGPfxNKrqBaOw59vMaUEHqpp1Twww4eQ4fKnkgBUGCQFT91zkfBqQ6GP+sVo/M8VPx5V2krOLAxtoI393uny4/SmTbuPdw3oePyqSVPPAI8RQBI4Z+BoSohByJFCshwQVPnwqZZu/bIoOcmloxxgjh5H9OVTLFIzKrFBkHPu/tR1V5YYMXZZ2nIlteKLe0RuJZuHGqR71t73RVxfukyorcAo8SKqvs0Jbi7f4x+1WuozqwvEpU6cZYRIvn/D9aWL9+irShaQ/wDkf/GtKFrbjnI/+MfoKr6X9Y0mv0jZvpiOGB6Cm3uZW96Q49cVJ7G1HTe/vsf0o8wp7kS+u5+5NdpbyZwKeFkFQ8jYRWdvIZNOrbSE94qnkTk/IU+8zEYIAXwY8Plyplpc8N4keC8BQ6QOYQYniKEUMfvZdv4v2H6mg8p6DCjlnp6DkKZZ8DPBR4mnLCzvNSk3bC2luPFgMIvqx4Cu9hJOANTGNs+TkcT4ml2Frdalc9hYQPcTczu+6o8WPID1rRQ7M2llD9p2gv49wc4YX3U9DIefooNN3W04MQsNm7NUgzgER7qE+IXmx82+VFoC72HH8xZtZtqVz7nYD58MlW+naXs5Et5q00V5efcXG9Eh/gXnI3me6POoM02p7W3TKd+KyLAvvHO9jkXPU+CjgKd07ZyWeY3mtzs8h5hm4+hPQeQrQWT3N9qEWi7MWTXeoMMCOMbqxL1Z25Ivrx+dNI7e7tX08n7xSV9+rOp/XwPtBALbQIYrSwhe41CdhHHFGu9JLIeAAHU+XIV3v2Qezxtmw2ubQ7k201ym6ADvJYxnnGh6sfvN8BwySj2X+ziz2SzqOoSrqG0Uq7r3RXuQKfuQg+6PE8z5cq6PESSBzY8OHWqtrF9sYA8S2iBN+T6ychp4OMVkto9stE2bcw6jehr4LvCytV7a4I58UHujzYqPOuV6t7f1ivXSys9LjhXgFuJpZn+LRDc+AJ9aQUJjQZjpYVdcNxzWZ1/Z21v5BIGaG6A7s6c/j4ihQr2ZrW0aXGRPNB2r70ODMTpepzpNNbndbsmIJxwbBxy6fCtB2FvqVmhuIFZWGcHiR6GhQrL/AMextTS+4/uafXKK21JsdpnNc0VdKVZ7O4kVWPuEZ+tV9pqMhkETKOJxkcM+ooUKz+tUUdToq2G0u9Gxvo1WbmTTFEzkbm434ozu/TlSbqBrdA2+HU9CvGhQrmUaSYIY6gIzCVkPBd30NWtimDzJoUKLptyDB6jbaOXOQTxqEXweQNChRW/qi6hkQ+259wUYmJ5KBQoUvMYVEMlyud4D4UySTzY0KFcZyxiWXc+7n1NX+zmz7a0pd7wwIvEqkeSfiT+lChUUKHt0txA6xzVTrTmXMGj6XZXBRbMXEy8e1unMn+XgKpNQ2uvZZ2tLZEgRDugnvY9FwFHyoUKHqnatOzbeP6KlLbM2DOBneK07RzrN0Zb+7mlZRnLcT6DoPlWlitLbTIR9lhUEkLvHmc+JoUKf0iKKvqY39YPWEm76fjbaFsvYz7Y7ZroJvHsYVQySTRKGcgYyFzwU8efGvS2yGzGk7KaaLTRbVII2IZ35ySN+J25sf9ihQpGS2WbnJjXUIdK8S21rURpOiXuovCZxawtN2Qfc38DlnBx8jXnHa/2wbQ6posd5A/8Ay2wuWdFtLJzG/A4/pJvfb0XcoUKEgYz95y8zk17qt3do0ckgSBjvGGIbiE88kfePm2TULNChVcmME//Z @@ -58,7 +60,8 @@ Some Yamaha models return different input values on status update than required in the change input commands. For example: HDMI1 command may be reported as HDMI_1 after status update. - There are other related edge cases (USB, iPad_USB). This setting allows the user to customize the + There are other related edge + cases (USB, iPad_USB). This setting allows the user to customize the return input mapping to meet their AVR model. The setting is a comma separated list of value mapping from to. @@ -72,15 +75,15 @@ - + Yamaha Receiver Zone - - - + + + zone @@ -118,17 +121,17 @@ Control the zone - + - - - - - - + + + + + + @@ -210,7 +213,7 @@ Set the volume level (dB) SoundVolume - + @@ -225,7 +228,7 @@ Set the dialogue level SoundVolume - + @@ -247,14 +250,14 @@ Control the playback for the current zone and allow to select preset channels - - - - - - - - + + + + + + + + @@ -262,35 +265,35 @@ String Current station name - + String Artist - + String Album - + String Track title - + String Track picture URL - + @@ -378,15 +381,15 @@ Allow to navigate for inputs like USB, iPOD, NET_RADIO - - - - - - - - - + + + + + + + + + @@ -394,9 +397,11 @@ String Shows the current navigation menu and allows to change to a channel by a full path. - For example for net radio: Bookmarks/__My_Favorites/radio_station_name. You can also just use the station + For example for net + radio: Bookmarks/__My_Favorites/radio_station_name. You can also just use the station name - without a full path if the AVR is in that navigation menu already. + without a full path if the + AVR is in that navigation menu already. Navigation @@ -406,7 +411,7 @@ Shows the current item number Navigation - + @@ -414,7 +419,7 @@ Shows the maximum item number Navigation - + @@ -422,7 +427,7 @@ Hierarchical level Navigation - + diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/ResponseLoader.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/ResponseLoader.java index 12b8caf726f64..3d845d99d2fd5 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/ResponseLoader.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/ResponseLoader.java @@ -12,11 +12,11 @@ */ package org.openhab.binding.yamahareceiver.internal; -import org.apache.commons.io.IOUtils; - import java.io.IOException; import java.io.InputStream; +import org.apache.commons.io.IOUtils; + /** * Helper for loading XML files from classpath. * @@ -36,5 +36,4 @@ public String load(String path) throws IOException { public String load(String path, String model) throws IOException { return load(String.format("/%s/%s", model, path)); } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/TestModels.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/TestModels.java index b1ee87475994a..42112474ed0d9 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/TestModels.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/TestModels.java @@ -22,5 +22,4 @@ public class TestModels { public static final String RX_S601D = "RX-S601D"; public static final String RX_V3900 = "RX-V3900"; public static final String HTR_4069 = "HTR-4069"; - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/XMLProtocolFactoryTest.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/XMLProtocolFactoryTest.java index e818abb58a04e..fd3ef99d8e91c 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/XMLProtocolFactoryTest.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/XMLProtocolFactoryTest.java @@ -88,5 +88,4 @@ public void given_RXS601D_without_ZONEB_then_Zone2_control_is_ZoneControlXML() // assert assertTrue("Created Zone control", zoneControl instanceof ZoneControlXML); } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/AbstractXMLProtocolTest.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/AbstractXMLProtocolTest.java index e1b87a33071ba..bfdab8d1dd149 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/AbstractXMLProtocolTest.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/AbstractXMLProtocolTest.java @@ -12,11 +12,11 @@ */ package org.openhab.binding.yamahareceiver.internal.protocol.xml; +import static org.mockito.MockitoAnnotations.initMocks; + import org.junit.Before; import org.mockito.Mock; -import static org.mockito.MockitoAnnotations.initMocks; - /** * Baseline for tests for the XML protocol implementation. * @@ -39,5 +39,4 @@ public void setUp() throws Exception { protected void onSetUp() throws Exception { } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/AbstractZoneControlXMLTest.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/AbstractZoneControlXMLTest.java index 04df9b52eca37..e2517d43d7ef9 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/AbstractZoneControlXMLTest.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/AbstractZoneControlXMLTest.java @@ -12,15 +12,15 @@ */ package org.openhab.binding.yamahareceiver.internal.protocol.xml; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; + import org.mockito.Mock; import org.openhab.binding.yamahareceiver.internal.config.YamahaZoneConfig; import org.openhab.binding.yamahareceiver.internal.protocol.InputConverter; import org.openhab.binding.yamahareceiver.internal.state.DeviceInformationState; import org.openhab.binding.yamahareceiver.internal.state.ZoneControlStateListener; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; - /** * Common zone test. * @@ -51,5 +51,4 @@ protected void onSetUp() throws Exception { when(inputConverter.fromStateName(anyString())).thenAnswer(p -> p.getArgument(0)); when(inputConverter.toCommandName(anyString())).thenAnswer(p -> p.getArgument(0)); } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/DeviceDescriptorXMLTest.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/DeviceDescriptorXMLTest.java index 4c8784e8c59eb..67badb6fb9165 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/DeviceDescriptorXMLTest.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/DeviceDescriptorXMLTest.java @@ -101,7 +101,6 @@ private void parsesDescriptor(String model, List%s", ZONE_INPUT_QUERY), "Main_Zone_Input_Input_Sel_Item.xml"); + ctx.respondWith(String.format("%s", ZONE_INPUT_QUERY), + "Main_Zone_Input_Input_Sel_Item.xml"); } @Test @@ -84,5 +85,4 @@ public void when_mapping_fromStateName_takesUserMappingAboveAll() { assertEquals("HDMI 1", hdmi1); assertEquals("BLUETOOTH", bluetooth); } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/InputWithPlayControlXMLTest.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/InputWithPlayControlXMLTest.java index 39871eb5335b0..cac736be8045f 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/InputWithPlayControlXMLTest.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/InputWithPlayControlXMLTest.java @@ -12,6 +12,15 @@ */ package org.openhab.binding.yamahareceiver.internal.protocol.xml; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.openhab.binding.yamahareceiver.internal.TestModels.*; +import static org.openhab.binding.yamahareceiver.internal.YamahaReceiverBindingConstants.Inputs.*; + +import java.util.function.Consumer; + import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Captor; @@ -20,15 +29,6 @@ import org.openhab.binding.yamahareceiver.internal.state.PlayInfoState; import org.openhab.binding.yamahareceiver.internal.state.PlayInfoStateListener; -import java.util.function.Consumer; - -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.openhab.binding.yamahareceiver.internal.TestModels.*; -import static org.openhab.binding.yamahareceiver.internal.YamahaReceiverBindingConstants.Inputs.*; - /** * Unit test for {@link InputWithPlayControlXML}. * @@ -95,7 +95,6 @@ public void given_RX_S601D_and_Spotify_when_nextPrevious_then_sendsProperCommand verify(con).send(eq("Skip Rev")); } - @Test public void given_RX_S601D_and_Bluetooth_when_playStopPause_then_sendsProperCommand() throws Exception { given(RX_S601D, INPUT_BLUETOOTH, ctx -> { @@ -143,7 +142,6 @@ public void given_RX_S601D_and_NET_RADIO_when_nextPrevious_then_sendsProperComma verify(con).send(eq("Skip Rev")); } - @Test public void given_RX_S601D_and_Spotify_when_update_then_stateIsProperlyRead() throws Exception { given(RX_S601D, INPUT_SPOTIFY, ctx -> { @@ -249,7 +247,6 @@ public void given_RX_V3900_and_NET_RADIO_when_update_then_stateIsProperlyRead() ctx.respondWith("GetParam", "NET_USB_Play_Info.xml"); }); - // when subject.update(); diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ModelContext.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ModelContext.java index 41831b558adf8..0cfe55132e4cb 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ModelContext.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ModelContext.java @@ -12,16 +12,16 @@ */ package org.openhab.binding.yamahareceiver.internal.protocol.xml; -import java.io.FileNotFoundException; -import java.io.IOException; - -import org.openhab.binding.yamahareceiver.internal.ResponseLoader; - import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; import static org.openhab.binding.yamahareceiver.internal.protocol.xml.XMLConstants.Commands.SYSTEM_STATUS_CONFIG_CMD; import static org.openhab.binding.yamahareceiver.internal.protocol.xml.XMLConstants.Commands.ZONE_BASIC_STATUS_CMD; +import java.io.FileNotFoundException; +import java.io.IOException; + +import org.openhab.binding.yamahareceiver.internal.ResponseLoader; + /** * Testing context for a selected Yamaha model. * diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/SystemControlXMLTest.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/SystemControlXMLTest.java index 07b982ab67778..ea82c52499a2c 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/SystemControlXMLTest.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/SystemControlXMLTest.java @@ -118,5 +118,4 @@ public void given_RX_V3900_when_update_then_parsesStateAndDoesNotUpdateStateForP assertTrue(state.power); assertFalse(state.partyMode); } - } diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ZoneBControlXMLTest.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ZoneBControlXMLTest.java index c1ca5e491ff82..9a2ce3acaa29e 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ZoneBControlXMLTest.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ZoneBControlXMLTest.java @@ -12,10 +12,6 @@ */ package org.openhab.binding.yamahareceiver.internal.protocol.xml; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.openhab.binding.yamahareceiver.internal.state.ZoneControlState; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.eq; @@ -23,6 +19,10 @@ import static org.mockito.Mockito.when; import static org.openhab.binding.yamahareceiver.internal.TestModels.HTR_4069; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.openhab.binding.yamahareceiver.internal.state.ZoneControlState; + /** * Unit test for {@link ZoneBControlXML}. * @@ -39,7 +39,8 @@ private void given(String model) throws Exception { DeviceInformationXML deviceInformation = new DeviceInformationXML(con, deviceInformationState); deviceInformation.update(); - subject = new ZoneBControlXML(con, zoneConfig, zoneControlStateListener, deviceInformationState, () -> inputConverter); + subject = new ZoneBControlXML(con, zoneConfig, zoneControlStateListener, deviceInformationState, + () -> inputConverter); } @Test @@ -52,7 +53,8 @@ public void given_HTR_4069_when_power_then_sendsProperCommand() throws Exception // then verify(con).send(eq("On")); - verify(con).send(eq("Standby")); + verify(con) + .send(eq("Standby")); } @Test @@ -68,7 +70,6 @@ public void given_HTR_4069_when_mute_then_sendsProperCommand() throws Exception verify(con).send(eq("Off")); } - @Test public void given_HTR_4069_when_volume_then_sendsProperCommand() throws Exception { given(HTR_4069); @@ -77,7 +78,8 @@ public void given_HTR_4069_when_volume_then_sendsProperCommand() throws Exceptio subject.setVolumeDB(-2); // then - verify(con).send(eq("-201dB")); + verify(con).send(eq( + "-201dB")); } @Test diff --git a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ZoneControlXMLTest.java b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ZoneControlXMLTest.java index 25a329ea1afb7..140b36166a172 100644 --- a/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ZoneControlXMLTest.java +++ b/bundles/org.openhab.binding.yamahareceiver/src/test/java/org/openhab/binding/yamahareceiver/internal/protocol/xml/ZoneControlXMLTest.java @@ -12,10 +12,6 @@ */ package org.openhab.binding.yamahareceiver.internal.protocol.xml; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.openhab.binding.yamahareceiver.internal.state.ZoneControlState; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.eq; @@ -23,6 +19,10 @@ import static org.openhab.binding.yamahareceiver.internal.TestModels.*; import static org.openhab.binding.yamahareceiver.internal.YamahaReceiverBindingConstants.Zone.Main_Zone; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.openhab.binding.yamahareceiver.internal.state.ZoneControlState; + /** * Unit test for {@link ZoneControlXML}. * @@ -38,7 +38,8 @@ private void given(String model) throws Exception { DeviceInformationXML deviceInformation = new DeviceInformationXML(con, deviceInformationState); deviceInformation.update(); - subject = new ZoneControlXML(con, Main_Zone, zoneConfig, zoneControlStateListener, deviceInformationState, () -> inputConverter); + subject = new ZoneControlXML(con, Main_Zone, zoneConfig, zoneControlStateListener, deviceInformationState, + () -> inputConverter); } @Test @@ -76,7 +77,6 @@ public void given_RX_S601D_when_mute_then_sendsProperCommand() throws Exception verify(con).send(eq("Off")); } - @Test public void given_RX_V3900_when_mute_then_sendsProperCommand() throws Exception { given(RX_V3900); @@ -98,7 +98,8 @@ public void given_RX_S601D_when_volume_then_sendsProperCommand() throws Exceptio subject.setVolumeDB(-2); // then - verify(con).send(eq("-201dB")); + verify(con).send( + eq("-201dB")); } @Test @@ -140,7 +141,8 @@ public void given_RX_S601D_when_surroundProgram_then_sendsProperCommand() throws subject.setSurroundProgram("Adventure"); // then - verify(con).send(eq("Adventure")); + verify(con).send(eq( + "Adventure")); } @Test @@ -151,10 +153,10 @@ public void given_RX_V3900_when_surroundProgram_then_sendsProperCommand() throws subject.setSurroundProgram("Adventure"); // then - verify(con).send(eq("OffAdventure")); + verify(con).send(eq( + "OffAdventure")); } - @Test public void given_RX_S601D_when_surroundProgramStraight_then_sendsProperCommand() throws Exception { given(RX_S601D); @@ -163,7 +165,8 @@ public void given_RX_S601D_when_surroundProgramStraight_then_sendsProperCommand( subject.setSurroundProgram("Straight"); // then - verify(con).send(eq("On")); + verify(con).send(eq( + "On")); } @Test @@ -185,7 +188,8 @@ public void given_HTR_4069_when_dialogueLevel_then_sendsProperCommand() throws E subject.setDialogueLevel(10); // then - verify(con).send(eq("10")); + verify(con).send(eq( + "10")); } @Test diff --git a/bundles/org.openhab.binding.yeelight/README.md b/bundles/org.openhab.binding.yeelight/README.md index 194f0244b09ca..059864aaca7f9 100644 --- a/bundles/org.openhab.binding.yeelight/README.md +++ b/bundles/org.openhab.binding.yeelight/README.md @@ -5,7 +5,7 @@ This binding integrates the [Yeelight Lighting Product](https://www.yeelight.com ## Supported Things - [Yeelight LED White Bulb](https://www.yeelight.com/zh_CN/product/wifi-led-w) (Thing type `dolphin`) -- [Yeelight LED Color Bulb](https://www.yeelight.com/zh_CN/product/wifi-led-c)(Thing type `wonder`) +- [Yeelight LED Color Bulb](https://www.yeelight.com/zh_CN/product/wifi-led-c) (Thing type `wonder`) - [Yeelight LED Color Stripe](https://www.yeelight.com/zh_CN/product/pitaya) (Thing type `stripe`) - [Yeelight LED Ceiling Light](https://www.yeelight.com/en_US/product/luna) (Thing type `ceiling`) @@ -40,7 +40,7 @@ All devices support some of the following channels: |`colorTemperature` | `Dimmer` | This channel supports adjusting the color temperature, it is available on `wonder` and `stripe` and `ceiling`.| |`command` | `String` | This channel sends a command directly to the device, it is available on all Yeelight Things.| |`backgroundColor` | `Color` or `Dimmer` | This channel supports color control for the ambient light, it is available on `ceiling4`.| -|`nightlight` | `Switch` | This supports switching to nightlight mode, it is available on `ceiling4`.| +|`nightlight` | `Switch` | This supports switching to nightlight mode, it is available on `ceiling1` or `ceiling4`.| ## Full Example diff --git a/bundles/org.openhab.binding.yeelight/pom.xml b/bundles/org.openhab.binding.yeelight/pom.xml index f691673a89712..48abd25eb985a 100644 --- a/bundles/org.openhab.binding.yeelight/pom.xml +++ b/bundles/org.openhab.binding.yeelight/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.yeelight diff --git a/bundles/org.openhab.binding.yeelight/src/main/feature/feature.xml b/bundles/org.openhab.binding.yeelight/src/main/feature/feature.xml index c2e4588f0afac..60dea3e55d332 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.yeelight/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.yeelight/${project.version} + diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/YeelightHandlerFactory.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/YeelightHandlerFactory.java index fdb620a9098b1..b88f0adc20cc7 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/YeelightHandlerFactory.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/YeelightHandlerFactory.java @@ -29,6 +29,7 @@ * The {@link YeelightHandlerFactory} is responsible for returning supported things and handlers for the devices. * * @author Coaster Li - Initial contribution + * @author Nikita Pogudalov - Added YeelightCeilingWithNightHandler for Ceiling 1 */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.yeelight") public class YeelightHandlerFactory extends BaseThingHandlerFactory { @@ -61,9 +62,11 @@ protected ThingHandler createHandler(Thing thing) { return new YeelightColorHandler(thing); } else if (thingTypeUID.equals(THING_TYPE_STRIPE)) { return new YeelightStripeHandler(thing); - } else if (thingTypeUID.equals(THING_TYPE_CEILING) || thingTypeUID.equals(THING_TYPE_CEILING1) - || thingTypeUID.equals(THING_TYPE_CEILING3) || thingTypeUID.equals(THING_TYPE_DESKLAMP)) { + } else if (thingTypeUID.equals(THING_TYPE_CEILING) || thingTypeUID.equals(THING_TYPE_CEILING3) + || thingTypeUID.equals(THING_TYPE_DESKLAMP)) { return new YeelightCeilingHandler(thing); + } else if (thingTypeUID.equals(THING_TYPE_CEILING1)) { + return new YeelightCeilingWithNightHandler(thing); } else if (thingTypeUID.equals(THING_TYPE_CEILING4)) { return new YeelightCeilingWithAmbientHandler(thing); } else { diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/discovery/YeelightDiscoveryService.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/discovery/YeelightDiscoveryService.java index 051868c3c6b77..0e6c8510d06b9 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/discovery/YeelightDiscoveryService.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/discovery/YeelightDiscoveryService.java @@ -85,9 +85,10 @@ public void onDeviceLost(DeviceBase device) { private ThingUID getThingUID(DeviceBase device) { switch (device.getDeviceType()) { case ceiling: - case ceiling1: case ceiling3: return new ThingUID(YeelightBindingConstants.THING_TYPE_CEILING, device.getDeviceId()); + case ceiling1: + return new ThingUID(YeelightBindingConstants.THING_TYPE_CEILING1, device.getDeviceId()); case ceiling4: return new ThingUID(YeelightBindingConstants.THING_TYPE_CEILING4, device.getDeviceId()); case color: diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/handler/YeelightCeilingWithNightHandler.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/handler/YeelightCeilingWithNightHandler.java new file mode 100644 index 0000000000000..740cd2a774991 --- /dev/null +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/handler/YeelightCeilingWithNightHandler.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.yeelight.internal.handler; + +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.thing.Thing; +import org.openhab.binding.yeelight.internal.YeelightBindingConstants; +import org.openhab.binding.yeelight.internal.lib.device.DeviceStatus; +import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode; + +/** + * The {@link YeelightCeilingWithNightHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Nikita Pogudalov - Initial contribution + */ +public class YeelightCeilingWithNightHandler extends YeelightCeilingHandler { + + public YeelightCeilingWithNightHandler(Thing thing) { + super(thing); + } + + @Override + protected void updateUI(DeviceStatus status) { + super.updateUI(status); + + updateState(YeelightBindingConstants.CHANNEL_NIGHTLIGHT, + (status.getActiveMode() == ActiveMode.MOONLIGHT_MODE) ? OnOffType.ON : OnOffType.OFF); + } +} diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/handler/YeelightHandlerBase.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/handler/YeelightHandlerBase.java index eb3172ec14d92..8dff821bc2053 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/handler/YeelightHandlerBase.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/handler/YeelightHandlerBase.java @@ -40,6 +40,7 @@ * * @author Coaster Li - Initial contribution * @author Joe Ho - Added Duration Thing parameter + * @author Nikita Pogudalov - Added DeviceType for ceiling 1 */ public abstract class YeelightHandlerBase extends BaseThingHandler implements DeviceConnectionStateListener, DeviceStatusChangeListener { @@ -73,6 +74,8 @@ public void initialize() { private DeviceType getDeviceModel(ThingTypeUID typeUID) { if (typeUID.equals(THING_TYPE_CEILING)) { return DeviceType.ceiling; + } else if (typeUID.equals(THING_TYPE_CEILING1)) { + return DeviceType.ceiling1; } else if (typeUID.equals(THING_TYPE_CEILING3)) { return DeviceType.ceiling3; } else if (typeUID.equals(THING_TYPE_CEILING4)) { @@ -339,6 +342,5 @@ int getDuration() { // Duration should not be null, but just in case do a null check. return getThing().getConfiguration().get(PARAMETER_DURATION) == null ? 500 : ((Number) getThing().getConfiguration().get(PARAMETER_DURATION)).intValue(); - } } diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/CeilingDeviceWithAmbientDevice.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/CeilingDeviceWithAmbientDevice.java index 8b129c84291a9..4d51717744ace 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/CeilingDeviceWithAmbientDevice.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/CeilingDeviceWithAmbientDevice.java @@ -72,7 +72,6 @@ public void onNotify(String msg) { } super.onNotify(msg); - } @Override diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/CeilingDeviceWithNightDevice.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/CeilingDeviceWithNightDevice.java new file mode 100644 index 0000000000000..db27cb65bd9ab --- /dev/null +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/CeilingDeviceWithNightDevice.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.yeelight.internal.lib.device; + +import org.openhab.binding.yeelight.internal.lib.enums.ActiveMode; +import org.openhab.binding.yeelight.internal.lib.enums.DeviceType; +import org.openhab.binding.yeelight.internal.lib.enums.MethodAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * The {@link CeilingDeviceWithNightDevice} contains methods for handling the ceiling device with ambient light. + * + * @author Nikita Pogudalov - Initial contribution + */ +public class CeilingDeviceWithNightDevice extends CeilingDevice implements DeviceWithNightlight { + private final Logger logger = LoggerFactory.getLogger(CeilingDeviceWithNightDevice.class); + + public CeilingDeviceWithNightDevice(String id) { + super(id); + + mDeviceType = DeviceType.ceiling1; + } + + @Override + public void onNotify(String msg) { + logger.debug("Got state: {}", msg); + + JsonObject result = new JsonParser().parse(msg).getAsJsonObject(); + + if (result.has("id")) { + String id = result.get("id").getAsString(); + // for cmd transaction. + + if (mQueryList.contains(id)) { + JsonArray status = result.get("result").getAsJsonArray(); + + final int activeMode = status.get(8).getAsInt(); + mDeviceStatus.setActiveMode(ActiveMode.values()[activeMode]); + } + } + + super.onNotify(msg); + } + + @Override + public void toggleNightlightMode(boolean turnOn) { + if (turnOn) { + mConnection.invoke( + new DeviceMethod(MethodAction.SCENE, new Object[] { "nightlight", mDeviceStatus.getBrightness() })); + } else { + mConnection.invoke(MethodFactory.buildCTMethod(mDeviceStatus.getCt(), DeviceMethod.EFFECT_SMOOTH, 500)); + } + } +} diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/ColorFlowItem.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/ColorFlowItem.java index 51001596735a9..6aa918d775430 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/ColorFlowItem.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/ColorFlowItem.java @@ -26,5 +26,4 @@ public String toString() { return "ColorFlowItem [duration=" + duration + ", mode=" + mode + ", value=" + value + ", brightness=" + brightness + "]"; } - } diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceBase.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceBase.java index ef78b5b1fea3e..5dd929fc8d76e 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceBase.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceBase.java @@ -397,7 +397,6 @@ public DeviceStatus getDeviceStatus() { public void registerConnectStateListener(DeviceConnectionStateListener listener) { mConnectionListeners.add(listener); - } public void registerStatusChangedListener(DeviceStatusChangeListener listener) { @@ -431,5 +430,4 @@ private void checkAutoConnect() { connect(); } } - } diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceFactory.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceFactory.java index 72b1debf03a2c..5ed0ce4e9da30 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceFactory.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceFactory.java @@ -23,6 +23,7 @@ * The {@link DeviceFactory} creates device handler classes. * * @author Coaster Li - Initial contribution + * @author Nikita Pogudalov - Added CeilingDeviceWithNightDevice for Ceiling 1 */ public class DeviceFactory { private static final Logger LOGGER = LoggerFactory.getLogger(DeviceFactory.class); @@ -33,9 +34,10 @@ public static DeviceBase build(String model, String id) { DeviceType type = DeviceType.valueOf(model); switch (type) { case ceiling: - case ceiling1: case ceiling3: return new CeilingDevice(id); + case ceiling1: + return new CeilingDeviceWithNightDevice(id); case ceiling4: return new CeilingDeviceWithAmbientDevice(id); case color: @@ -70,5 +72,4 @@ public static DeviceBase build(Map bulbInfo) { LOGGER.debug("{}: DeviceFactory Device info = {}, port = {}", TAG, device.getAddress(), device.getPort()); return device; } - } diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceMethod.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceMethod.java index 747b2e1ac1f88..15cc7ac00678b 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceMethod.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceMethod.java @@ -100,5 +100,4 @@ public String getCustomParamsStr() { public String getCmdId() { return String.valueOf(mIndex); } - } diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceStatus.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceStatus.java index f7c9e04b38fd4..fe17f0bc85307 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceStatus.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/DeviceStatus.java @@ -266,5 +266,4 @@ public int getFlowEndAction() { public void setFlowEndAction(int flowEndAction) { this.flowEndAction = flowEndAction; } - } diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/MethodFactory.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/MethodFactory.java index 3d445d1b157bd..abcd39500eb58 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/MethodFactory.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/MethodFactory.java @@ -17,6 +17,7 @@ /** * @author Coaster Li - Initial contribution + * @author Nikita Pogudalov - Added DeviceMethod for Ceiling 1 */ public class MethodFactory { public static DeviceMethod buildBrightnessMethd(int brightness, String effect, int duration) { @@ -172,6 +173,7 @@ public static DeviceMethod buildQuery(DeviceBase device) { case desklamp: case ct_bulb: return new DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright", "ct" }); + case ceiling1: case ceiling4: return new DeviceMethod(MethodAction.PROP, new Object[] { "power", "name", "bright", "ct", "bg_power", "bg_bright", "bg_hue", "bg_sat", "active_mode" }); diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/connection/ConnectionBase.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/connection/ConnectionBase.java index 7e1cac5e6ce03..d2cba7287b756 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/connection/ConnectionBase.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/connection/ConnectionBase.java @@ -28,5 +28,4 @@ public interface ConnectionBase { boolean connect(); boolean disconnect(); - } diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/connection/WifiConnection.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/connection/WifiConnection.java index 02e26125bb2d6..c549f90c9d37f 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/connection/WifiConnection.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/device/connection/WifiConnection.java @@ -130,5 +130,4 @@ public boolean disconnect() { mDevice.setAutoConnect(false); return false; } - } diff --git a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/services/DeviceManager.java b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/services/DeviceManager.java index 55bb1cf9f02f5..9ea687d9dc0cd 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/services/DeviceManager.java +++ b/bundles/org.openhab.binding.yeelight/src/main/java/org/openhab/binding/yeelight/internal/lib/services/DeviceManager.java @@ -44,6 +44,7 @@ * * @author Coaster Li - Initial contribution * @author Joe Ho - Added duration + * @author Nikita Pogudalov - Added name for Ceiling 1 */ public class DeviceManager { private final Logger logger = LoggerFactory.getLogger(DeviceManager.class); @@ -319,9 +320,10 @@ public static String getDefaultName(DeviceBase device) { } switch (device.getDeviceType()) { case ceiling: - case ceiling1: case ceiling3: return "Yeelight LED Ceiling"; + case ceiling1: + return "Yeelight LED Ceiling with night mode"; case ceiling4: return "Yeelight LED Ceiling with ambient light"; case color: diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/binding/binding.xml index b5abeb92b9ff7..632ebbc77f452 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + Yeelight Binding This is the binding for Yeelight products. diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/config/config.xml index 766b5f9474be4..b2117b188172c 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/config/config.xml @@ -12,7 +12,8 @@ - Duration of transition of events such as on/off, change of brightness and change of color, in milliseconds. + Duration of transition of events such as on/off, change of brightness and change of color, in + milliseconds. milliseconds 500 diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling.xml index 0c1a147c520f1..e5bdf5ca9af9f 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling.xml @@ -1,5 +1,6 @@ - @@ -8,11 +9,11 @@ Yeelight LED Ceiling lamp - - - + + + - + diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling1.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling1.xml new file mode 100644 index 0000000000000..5401b3c40e5e9 --- /dev/null +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling1.xml @@ -0,0 +1,20 @@ + + + + + + Yeelight LED Ceiling lamp with Night Mode + + + + + + + + + + + diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling4.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling4.xml index 79bd57c42c975..3fa58fa1ecac2 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling4.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ceiling4.xml @@ -1,5 +1,6 @@ - @@ -9,7 +10,7 @@ - + diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/channels.xml index 54b8103b75939..a3e83a4715f42 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/channels.xml @@ -9,7 +9,8 @@ Dimmer The brightness channel allows to control the brightness of a light. - It is also possible to switch the light on and off. + It is also possible to switch the + light on and off. DimmableLight diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ct_bulb.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ct_bulb.xml index a8d1e4e2a1249..7c77d78084bf8 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ct_bulb.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/ct_bulb.xml @@ -9,11 +9,11 @@ Yeelight White LED Bulb v2 - - - + + + - + diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/desklamp.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/desklamp.xml index 9d64b21faa218..963a983c3a23b 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/desklamp.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/desklamp.xml @@ -1,5 +1,6 @@ - @@ -8,11 +9,11 @@ Yeelight MI LED Desk Lamp - - - + + + - + diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/dolphin.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/dolphin.xml index 093f84216c7ae..fa76ab70808b5 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/dolphin.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/dolphin.xml @@ -1,5 +1,6 @@ - @@ -8,10 +9,10 @@ Yeelight White LED Bulb - - + + - + diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/stripe.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/stripe.xml index 7f2944ecba283..47e051c0c3a17 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/stripe.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/stripe.xml @@ -1,5 +1,6 @@ - @@ -8,11 +9,11 @@ Yeelight Color LED Stripe - - - + + + - + diff --git a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/wonder.xml b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/wonder.xml index d988a91acc3a7..91785d237d1d5 100644 --- a/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/wonder.xml +++ b/bundles/org.openhab.binding.yeelight/src/main/resources/ESH-INF/thing/wonder.xml @@ -1,5 +1,6 @@ - @@ -8,11 +9,11 @@ Yeelight Color LED Bulb - - - + + + - + diff --git a/bundles/org.openhab.binding.yeelight/src/test/java/org/openhab/binding/yeelight/internal/YeelightHandlerFactoryTest.java b/bundles/org.openhab.binding.yeelight/src/test/java/org/openhab/binding/yeelight/internal/YeelightHandlerFactoryTest.java index 67431c9937c4e..660f0ca063f5c 100644 --- a/bundles/org.openhab.binding.yeelight/src/test/java/org/openhab/binding/yeelight/internal/YeelightHandlerFactoryTest.java +++ b/bundles/org.openhab.binding.yeelight/src/test/java/org/openhab/binding/yeelight/internal/YeelightHandlerFactoryTest.java @@ -38,6 +38,7 @@ * Unit tests for {@link YeelightHandlerFactory} * * @author Viktor Koop - Initial contribution + * @author Nikita Pogudalov - Added YeelightCeilingWithNightHandler for Ceiling 1 */ @RunWith(value = Parameterized.class) public class YeelightHandlerFactoryTest { @@ -46,7 +47,7 @@ public class YeelightHandlerFactoryTest { new Object[][] { { "dolphin", YeelightWhiteHandler.class }, { "ct_bulb", YeelightWhiteHandler.class }, { "wonder", YeelightColorHandler.class }, { "stripe", YeelightStripeHandler.class }, { "ceiling", YeelightCeilingHandler.class }, { "ceiling3", YeelightCeilingHandler.class }, - { "ceiling1", YeelightCeilingHandler.class }, { "desklamp", YeelightCeilingHandler.class }, + { "ceiling1", YeelightCeilingWithNightHandler.class }, { "desklamp", YeelightCeilingHandler.class }, { "ceiling4", YeelightCeilingWithAmbientHandler.class }, { "unknown", null } }); private final YeelightHandlerFactory factory = new YeelightHandlerFactory(); diff --git a/bundles/org.openhab.binding.zoneminder/pom.xml b/bundles/org.openhab.binding.zoneminder/pom.xml index 776533edf5e53..6a0f4acbcb362 100644 --- a/bundles/org.openhab.binding.zoneminder/pom.xml +++ b/bundles/org.openhab.binding.zoneminder/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.zoneminder diff --git a/bundles/org.openhab.binding.zoneminder/src/main/feature/feature.xml b/bundles/org.openhab.binding.zoneminder/src/main/feature/feature.xml index 0bb8e73d7aa14..f786d487a16ef 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.zoneminder/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.binding.zoneminder/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.zoneminder/${project.version} + diff --git a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/ZoneMinderConstants.java b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/ZoneMinderConstants.java index 2f86e4b9c975e..93ed92560613a 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/ZoneMinderConstants.java +++ b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/ZoneMinderConstants.java @@ -101,5 +101,4 @@ public class ZoneMinderConstants { public static final String MONITOR_EVENT_MOTION = "Motion"; public static final String MONITOR_EVENT_FORCED_WEB = "Forced Web"; public static final String MONITOR_EVENT_OPENHAB = "openHAB"; - } diff --git a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderBridgeServerConfig.java b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderBridgeServerConfig.java index 8ba7e99e0db33..3604966c0cca6 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderBridgeServerConfig.java +++ b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderBridgeServerConfig.java @@ -126,5 +126,4 @@ public Boolean getAutodiscoverThings() { public void setAutodiscoverThings(Boolean autodiscoverThings) { this.autodiscover_things = autodiscoverThings; } - } diff --git a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingConfig.java b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingConfig.java index 7367b3d398195..025f01bf2ec08 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingConfig.java +++ b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/config/ZoneMinderThingConfig.java @@ -27,5 +27,4 @@ public abstract class ZoneMinderThingConfig extends ZoneMinderConfig { public String getConfigId() { return ZoneMinderConstants.THING_ZONEMINDER_MONITOR; } - } diff --git a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/discovery/ZoneMinderDiscoveryService.java b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/discovery/ZoneMinderDiscoveryService.java index 32276bcaf62d9..8eab40fdd1433 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/discovery/ZoneMinderDiscoveryService.java +++ b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/discovery/ZoneMinderDiscoveryService.java @@ -112,7 +112,7 @@ protected synchronized void discoverMonitors() { } private boolean monitorThingExists(ThingUID newThingUID) { - return serverHandler.getThingByUID(newThingUID) != null ? true : false; + return serverHandler.getThing().getThing(newThingUID) != null ? true : false; } /** diff --git a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderBaseThingHandler.java b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderBaseThingHandler.java index 539e7b54c87e0..2d34aa67faa7d 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderBaseThingHandler.java +++ b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderBaseThingHandler.java @@ -351,7 +351,6 @@ protected State getChannelStringAsStringState(String channelValue) { } return state; - } protected State getChannelBoolAsOnOffState(boolean value) { @@ -392,5 +391,4 @@ protected void updateThingStatus(ThingStatus thingStatus, ThingStatusDetail stat } } } - } diff --git a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderHandler.java b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderHandler.java index 06c6ff4ab12d0..1747a8ca66983 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderHandler.java +++ b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderHandler.java @@ -42,5 +42,4 @@ void onBridgeConnected(ZoneMinderServerBridgeHandler bridge, IZoneMinderConnecti throws IllegalArgumentException, GeneralSecurityException, IOException, ZoneMinderUrlNotFoundException; void onBridgeDisconnected(ZoneMinderServerBridgeHandler bridge); - } diff --git a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderServerBridgeHandler.java b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderServerBridgeHandler.java index 5b76fc32e60c8..15cbe545419f9 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderServerBridgeHandler.java +++ b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderServerBridgeHandler.java @@ -881,7 +881,6 @@ synchronized void closeConnection() { logger.error("{}: closeConnection(): Error closing connection - {}", getLogIdentifier(), exception.getMessage()); } - } protected State getServerCpuLoadState() { @@ -990,7 +989,6 @@ public void onBridgeDisconnected(ZoneMinderServerBridgeHandler bridge) { thing.getBridgeUID(), thing.getUID(), thingHandler); } } - } /** @@ -1018,7 +1016,6 @@ protected void stopTask(ScheduledFuture task) { } } catch (Exception ex) { } - } public ArrayList getMonitors() { diff --git a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderThingMonitorHandler.java b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderThingMonitorHandler.java index f9e2558fab855..8b3fff747d63e 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderThingMonitorHandler.java +++ b/bundles/org.openhab.binding.zoneminder/src/main/java/org/openhab/binding/zoneminder/internal/handler/ZoneMinderThingMonitorHandler.java @@ -561,7 +561,6 @@ public void updateStatus(ThingStatus status) { super.updateStatus(status); updateState(ZoneMinderConstants.CHANNEL_ONLINE, ((status == ThingStatus.ONLINE) ? OnOffType.ON : OnOffType.OFF)); - } protected void recalculateChannelStates() { @@ -655,7 +654,6 @@ protected void recalculateChannelStates() { // Now we can conclude on the Alarmed and Recording channel state channelRecordingState = (recordingFunction && recordingDetailedState && channelEnabled); channelAlarmedState = (alarmedFunction && alarmedDetailedState && channelEnabled); - } @Override @@ -759,7 +757,6 @@ protected void onFetchData() { && (DataRefreshPriorityEnum.HIGH_PRIORITY == getRefreshPriority())) { stopPriorityRefresh(); } - } protected State getDetailedStatus() { @@ -777,7 +774,6 @@ protected State getDetailedStatus() { } return state; - } /* diff --git a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/binding/binding.xml index ad597abc3f2ee..bfb41faed36eb 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/binding/binding.xml @@ -1,8 +1,7 @@ - + ZoneMinder Binding This binding interfaces a ZoneMinder Server diff --git a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/config/monitor-channels.xml b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/config/monitor-channels.xml index 93eef7e18614e..9339531e96219 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/config/monitor-channels.xml +++ b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/config/monitor-channels.xml @@ -14,7 +14,7 @@ Timeout in seconds when activating alarm. Default is 60 seconds 60 - + Event text in ZoneMinder Triggered from openHAB diff --git a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/config/zoneminderserver.xml b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/config/zoneminderserver.xml index 12b35d276c8af..ba93625d62de1 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/config/zoneminderserver.xml +++ b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/config/zoneminderserver.xml @@ -1,10 +1,13 @@ - basic - + credentials @@ -62,15 +65,18 @@ 6802 true - + Seconds between each call to ZoneMinder Server API to refresh values in openHAB 10 true - + - Minutes between each call to ZoneMinder Server to refresh Server DiskUsage in ZoneMinder. Default value is '0' (Disabled) + Minutes between each call to ZoneMinder Server to refresh Server DiskUsage in ZoneMinder. Default value + is '0' (Disabled) 0 true diff --git a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/thing/monitor-thing.xml b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/thing/monitor-thing.xml index 34d2bb6dde6ee..4050d4d63fc1f 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/thing/monitor-thing.xml +++ b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/thing/monitor-thing.xml @@ -1,32 +1,33 @@ - - + Camera in ZoneMinder - - - - - - - - - - - + + + + + + + + + + + - + @@ -34,36 +35,38 @@ Switch Switch telling if the monitor is online - + Switch Showing the value of the checkbox 'enabled' in ZoneMinder for the monitor - + Switch Will force an alarm from openHAB in ZoneMinder - + Switch - set to 'ON' when one of the following is true: Motion detected, Signal lost, Force Alarm pressed, External Alarm. Else set to 'OFF' - + set to 'ON' when one of the following is true: Motion detected, Signal lost, Force Alarm pressed, + External Alarm. Else set to 'OFF' + Switch - set to 'ON' when either channel monitor-alarm set to 'ON', or montior function is 'Mocord' or 'Record'. Else set to 'OFF' - + set to 'ON' when either channel monitor-alarm set to 'ON', or montior function is 'Mocord' or 'Record'. + Else set to 'OFF' + diff --git a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/thing/server-bridge.xml b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/thing/server-bridge.xml index 92290301849e8..bd6171d4880e1 100644 --- a/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/thing/server-bridge.xml +++ b/bundles/org.openhab.binding.zoneminder/src/main/resources/ESH-INF/thing/server-bridge.xml @@ -8,7 +8,7 @@ ZoneMinder Server - + diff --git a/bundles/org.openhab.binding.zway/pom.xml b/bundles/org.openhab.binding.zway/pom.xml index b9e09e4003534..2460befbed0bc 100644 --- a/bundles/org.openhab.binding.zway/pom.xml +++ b/bundles/org.openhab.binding.zway/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.binding.zway diff --git a/bundles/org.openhab.binding.zway/src/main/feature/feature.xml b/bundles/org.openhab.binding.zway/src/main/feature/feature.xml index f5920d1810213..31162401c07d9 100644 --- a/bundles/org.openhab.binding.zway/src/main/feature/feature.xml +++ b/bundles/org.openhab.binding.zway/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.apache.commons/commons-lang3/3.4 - mvn:org.openhab.addons.bundles/org.openhab.binding.zway/${project.version} - + + openhab-runtime-base + mvn:org.apache.commons/commons-lang3/3.4 + mvn:org.openhab.addons.bundles/org.openhab.binding.zway/${project.version} + diff --git a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/binding/binding.xml index 42f3f158c108c..5a2a70a6f621f 100644 --- a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/binding/binding.xml @@ -1,14 +1,13 @@ - + Z-Way Binding Currently only a continuous polling is available! ]]> diff --git a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/config/bridge-config.xml b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/config/bridge-config.xml index cdd9bd90fa321..5ea58b16b8a6b 100644 --- a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/config/bridge-config.xml +++ b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/config/bridge-config.xml @@ -1,13 +1,14 @@ - + https://openhab.org/schemas/config-description-1.0.0.xsd"> - The configuration of the Z-Way server. Except for the username and password all the information detected during the discovery. + The configuration of the Z-Way server. Except for the username and password all the information detected + during the discovery. @@ -18,7 +19,8 @@ network-address - The IP address or hostname of the Z-Way server. If Z-Way and openHAB are running on the same machine, the default value can be used. + The IP address or hostname of the Z-Way server. If Z-Way and openHAB are running on the same machine, + the default value can be used. localhost @@ -50,7 +52,8 @@ Password to access the Z-Way server. - + Refresh device states and registration from Z-Way server. Seconds diff --git a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/bridge.xml index fc70e830ea00a..ab06fce57c74a 100644 --- a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,25 +1,26 @@ - - + - + - - - - + + + + - + diff --git a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/channels.xml b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/channels.xml index 6ee4605bc6bce..6984312857319 100644 --- a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/channels.xml @@ -1,5 +1,6 @@ - @@ -7,126 +8,126 @@ Number Temperature - + Number Light - + Number Humidity - + Number Pressure - + Number Light - + Number CarbonDioxide - + Number Energy - + Number Energy - + Number Energy - + Switch Smoke - + Switch Gas - + Switch Water - + Switch Alarm - + Contact Contact - + Switch Motion - + Switch PowerOutlet - + Dimmer ColorLight - + Rollershutter Blinds - + @@ -135,14 +136,14 @@ Number Battery - + Switch Door - + @@ -150,14 +151,14 @@ This channel represents a universal channel if no further device information is available. Switch - + Number This channel represents a universal channel if no further device information is available. - + @@ -165,14 +166,14 @@ This channel represents a universal channel if no further device information is available. Switch - + Dimmer This channel represents a universal channel if no further device information is available. - + @@ -185,16 +186,17 @@ Switch - The channel allows the control or display of a thermostat (mode). A thermostat can have up to three states (modes): off, heating and cooling. The state of heating and cooling is alternately set at the state on. + The channel allows the control or display of a thermostat (mode). A thermostat can have up to three + states (modes): off, heating and cooling. The state of heating and cooling is alternately set at the state on. Temperature - + Number Temperature - + @@ -202,22 +204,26 @@ This channel represents a universal channel if no further device information is available. Switch - + Number - This channel represents a two-digit value. The first digit is the button/scene number and the second digit points to action/keyAttribute (have a look at http://z-wave.sigmadesigns.com/wp-content/uploads/2016/08/SDS12657-12-Z-Wave-Command-Class-Specification-A-M.pdf, p. 153). - + This channel represents a two-digit value. The first digit is the button/scene number and the second + digit points to action/keyAttribute (have a look at + http://z-wave.sigmadesigns.com/wp-content/uploads/2016/08/SDS12657-12-Z-Wave-Command-Class-Specification-A-M.pdf, p. + 153). + Number - The channel allows the control or display of a thermostat (mode) from command class. The modes differ from device to device. + The channel allows the control or display of a thermostat (mode) from command class. The modes differ + from device to device. Temperature - + @@ -238,7 +244,7 @@ Change inclusion type for further inclusions. Switch - + @@ -246,7 +252,7 @@ Start inclusion mode (after a timeout the inclusion will be automatically finished). Switch - + @@ -254,7 +260,7 @@ Start exclusion mode (after a timeout the exclusion will be automatically finished). Switch - + diff --git a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/device.xml b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/device.xml index 13ef84a8d529b..d9eb867d35d5d 100644 --- a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/device.xml +++ b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/device.xml @@ -1,18 +1,19 @@ - - + diff --git a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/virtual_device.xml b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/virtual_device.xml index a8662a98297d9..50539871d178e 100644 --- a/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/virtual_device.xml +++ b/bundles/org.openhab.binding.zway/src/main/resources/ESH-INF/thing/virtual_device.xml @@ -1,11 +1,12 @@ - - + diff --git a/bundles/org.openhab.extensionservice.marketplace.automation/pom.xml b/bundles/org.openhab.extensionservice.marketplace.automation/pom.xml index 6f4337ee731d3..e0c6f5c41a649 100644 --- a/bundles/org.openhab.extensionservice.marketplace.automation/pom.xml +++ b/bundles/org.openhab.extensionservice.marketplace.automation/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.extensionservice.marketplace.automation diff --git a/bundles/org.openhab.extensionservice.marketplace.automation/src/main/feature/feature.xml b/bundles/org.openhab.extensionservice.marketplace.automation/src/main/feature/feature.xml index 2cf08539c005b..e6e4f3f31e1bf 100644 --- a/bundles/org.openhab.extensionservice.marketplace.automation/src/main/feature/feature.xml +++ b/bundles/org.openhab.extensionservice.marketplace.automation/src/main/feature/feature.xml @@ -1,6 +1,6 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features diff --git a/bundles/org.openhab.extensionservice.marketplace.automation/src/main/java/org/openhab/extensionservice/marketplace/automation/internal/AutomationExtensionHandler.java b/bundles/org.openhab.extensionservice.marketplace.automation/src/main/java/org/openhab/extensionservice/marketplace/automation/internal/AutomationExtensionHandler.java index eb8df7a3b37e0..cfc48eb7c64c5 100644 --- a/bundles/org.openhab.extensionservice.marketplace.automation/src/main/java/org/openhab/extensionservice/marketplace/automation/internal/AutomationExtensionHandler.java +++ b/bundles/org.openhab.extensionservice.marketplace.automation/src/main/java/org/openhab/extensionservice/marketplace/automation/internal/AutomationExtensionHandler.java @@ -87,5 +87,4 @@ private String getTemplate(String urlString) throws IOException { URL url = new URL(urlString); return IOUtils.toString(url); } - } diff --git a/bundles/org.openhab.extensionservice.marketplace.automation/src/main/java/org/openhab/extensionservice/marketplace/automation/internal/MarketplaceRuleTemplateProvider.java b/bundles/org.openhab.extensionservice.marketplace.automation/src/main/java/org/openhab/extensionservice/marketplace/automation/internal/MarketplaceRuleTemplateProvider.java index 3dd51b3b62e90..5cae8dad5d882 100644 --- a/bundles/org.openhab.extensionservice.marketplace.automation/src/main/java/org/openhab/extensionservice/marketplace/automation/internal/MarketplaceRuleTemplateProvider.java +++ b/bundles/org.openhab.extensionservice.marketplace.automation/src/main/java/org/openhab/extensionservice/marketplace/automation/internal/MarketplaceRuleTemplateProvider.java @@ -100,5 +100,4 @@ public void addTemplateAsJSON(String uid, String json) throws ParsingException { logger.error("Cannot close input stream.", e); } } - } diff --git a/bundles/org.openhab.extensionservice.marketplace/pom.xml b/bundles/org.openhab.extensionservice.marketplace/pom.xml index 5baa70c9e781b..85be7dad37ac3 100644 --- a/bundles/org.openhab.extensionservice.marketplace/pom.xml +++ b/bundles/org.openhab.extensionservice.marketplace/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.extensionservice.marketplace diff --git a/bundles/org.openhab.extensionservice.marketplace/src/main/feature/feature.xml b/bundles/org.openhab.extensionservice.marketplace/src/main/feature/feature.xml index 4d288d9946889..4780541126701 100644 --- a/bundles/org.openhab.extensionservice.marketplace/src/main/feature/feature.xml +++ b/bundles/org.openhab.extensionservice.marketplace/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.extensionservice.marketplace/${project.version} - - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.extensionservice.marketplace/${project.version} + + diff --git a/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/MarketplaceExtension.java b/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/MarketplaceExtension.java index 3e36fca4a2a98..1d7754ec38569 100644 --- a/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/MarketplaceExtension.java +++ b/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/MarketplaceExtension.java @@ -66,5 +66,4 @@ public String getDownloadUrl() { public String getPackageFormat() { return packageFormat; } - } diff --git a/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/BundleExtensionHandler.java b/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/BundleExtensionHandler.java index 921239d09942a..fc418f4375dd7 100644 --- a/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/BundleExtensionHandler.java +++ b/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/BundleExtensionHandler.java @@ -27,7 +27,6 @@ import org.openhab.extensionservice.marketplace.MarketplaceExtension; import org.openhab.extensionservice.marketplace.MarketplaceExtensionHandler; import org.openhab.extensionservice.marketplace.MarketplaceHandlerException; -import org.openhab.extensionservice.marketplace.internal.BundleExtensionHandler; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; @@ -38,7 +37,8 @@ import org.slf4j.LoggerFactory; /** - * A {@link MarketplaceExtensionHandler} implementation, which handles extensions as jar files (specifically, OSGi bundles) and installs + * A {@link MarketplaceExtensionHandler} implementation, which handles extensions as jar files (specifically, OSGi + * bundles) and installs * them through the standard OSGi bundle installation mechanism. * The information, which installed bundle corresponds to which extension is written to a file in the bundle's data * store. It is therefore wiped together with the bundles upon an OSGi "clean". @@ -56,9 +56,8 @@ public class BundleExtensionHandler implements MarketplaceExtensionHandler { private static final String BUNDLE_FILE = "installedBundlesMap.csv"; // extension types supported by this handler - private static final List SUPPORTED_EXT_TYPES = Arrays.asList( - MarketplaceExtension.EXT_TYPE_BINDING, - MarketplaceExtension.EXT_TYPE_VOICE); + private static final List SUPPORTED_EXT_TYPES = Arrays.asList(MarketplaceExtension.EXT_TYPE_BINDING, + MarketplaceExtension.EXT_TYPE_VOICE); private final Logger logger = LoggerFactory.getLogger(BundleExtensionHandler.class); @@ -81,7 +80,8 @@ protected void deactivate() { @Override public boolean supports(MarketplaceExtension ext) { // we support only certain extension types, and only as pure OSGi bundles - return SUPPORTED_EXT_TYPES.contains(ext.getType()) && ext.getPackageFormat().equals(MarketplaceExtension.EXT_FORMAT_BUNDLE); + return SUPPORTED_EXT_TYPES.contains(ext.getType()) + && ext.getPackageFormat().equals(MarketplaceExtension.EXT_FORMAT_BUNDLE); } @Override @@ -156,7 +156,7 @@ private Map loadInstalledBundlesFile(File dataFile) { map.put(parts[0], Long.valueOf(parts[1])); } catch (NumberFormatException e) { logger.debug("Cannot parse '{}' as a number in file {} - ignoring it.", parts[1], - dataFile.getName()); + dataFile.getName()); } } else { logger.debug("Invalid line in file {} - ignoring it:\n{}", dataFile.getName(), line); @@ -184,5 +184,4 @@ private synchronized void persistInstalledBundlesMap(Map map) { logger.debug("System does not support bundle data files -> not persisting installed bundle info"); } } - } diff --git a/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/MarketplaceExtensionService.java b/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/MarketplaceExtensionService.java index 76cb718f3b457..df98670d0da30 100644 --- a/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/MarketplaceExtensionService.java +++ b/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/MarketplaceExtensionService.java @@ -375,5 +375,4 @@ private String extractExensionId(URI uri) { private Optional getExtensionNode(String id) { return proxy.getNodes().stream().filter(node -> node != null && node.id.equals(id)).findFirst(); } - } diff --git a/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/MarketplaceXMLReader.java b/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/MarketplaceXMLReader.java index ce818ab000190..41aaa0656a77f 100644 --- a/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/MarketplaceXMLReader.java +++ b/bundles/org.openhab.extensionservice.marketplace/src/main/java/org/openhab/extensionservice/marketplace/internal/MarketplaceXMLReader.java @@ -50,5 +50,4 @@ public void registerAliases(@NonNullByDefault({}) XStream xstream) { // ignore what we do not know xstream.ignoreUnknownElements(); } - } diff --git a/bundles/org.openhab.extensionservice.marketplace/src/test/java/org/openhab/extensionservice/marketplace/internal/MarketplaceExtensionServiceTest.java b/bundles/org.openhab.extensionservice.marketplace/src/test/java/org/openhab/extensionservice/marketplace/internal/MarketplaceExtensionServiceTest.java index ce79b915f7535..72f9541a79f75 100644 --- a/bundles/org.openhab.extensionservice.marketplace/src/test/java/org/openhab/extensionservice/marketplace/internal/MarketplaceExtensionServiceTest.java +++ b/bundles/org.openhab.extensionservice.marketplace/src/test/java/org/openhab/extensionservice/marketplace/internal/MarketplaceExtensionServiceTest.java @@ -132,5 +132,4 @@ private Node createVoiceNode() { node.packagetypes = "voice"; return node; } - } diff --git a/bundles/org.openhab.io.homekit/README.md b/bundles/org.openhab.io.homekit/README.md index 290aacf28c9c4..a8273c7eb0d85 100644 --- a/bundles/org.openhab.io.homekit/README.md +++ b/bundles/org.openhab.io.homekit/README.md @@ -42,60 +42,376 @@ org.openhab.homekit:maximumTemperature=100 ### Overview of all settings -| Setting | Description | Default value | -|-------------------------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--------------- | -| networkInterface | IP address or domain name under which the HomeKit bridge can be reached. If no value is configured, the add-on uses the first network adapter address. | (none) | -| port | Port under which the HomeKit bridge can be reached. | 9123 | -| pin | Pin code used for pairing with iOS devices. Apparently, pin codes are provided by Apple and represent specific device types, so they cannot be chosen freely. The pin code 031-45-154 is used in sample applications and known to work. | 031-45-154 | -| useFahrenheitTemperature | Set to true to use Fahrenheit degrees, or false to use Celsius degrees. | false | -| thermostatTargetModeCool | Word used for activating the cooling mode of the device (if applicable). | CoolOn | -| thermostatTargetModeHeat | Word used for activating the heating mode of the device (if applicable). | HeatOn | -| thermostatTargetModeAuto | Word used for activating the automatic mode of the device (if applicable). | Auto | -| thermostatTargetModeOff | Word used to set the thermostat mode of the device to off (if applicable). | Off | -| minimumTemperature | Lower bound of possible temperatures, used in the user interface of the iOS device to display the allowed temperature range. Note that this setting applies to all devices in HomeKit. | -100 | -| maximumTemperature | Upper bound of possible temperatures, used in the user interface of the iOS device to display the allowed temperature range. Note that this setting applies to all devices in HomeKit. | 100 | -| name | Name under which this HomeKit bridge is announced on the network. This is also the name displayed on the iOS device when searching for available bridges. | openHAB | +| Setting | Description | Default value | +|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------| +| networkInterface | IP address or domain name under which the HomeKit bridge can be reached. If no value is configured, the add-on uses the first network adapter address. | (none) | +| port | Port under which the HomeKit bridge can be reached. | 9123 | +| pin | Pin code used for pairing with iOS devices. Apparently, pin codes are provided by Apple and represent specific device types, so they cannot be chosen freely. The pin code 031-45-154 is used in sample applications and known to work. | 031-45-154 | +| startDelay | HomeKit start delay in seconds in case the number of accessories is lower than last time. This helps to avoid resetting home app in case not all items have been initialised properly before HomeKit integration start. | 30 | +| useFahrenheitTemperature | Set to true to use Fahrenheit degrees, or false to use Celsius degrees. | false | +| thermostatTargetModeCool | Word used for activating the cooling mode of the device (if applicable). | CoolOn | +| thermostatTargetModeHeat | Word used for activating the heating mode of the device (if applicable). | HeatOn | +| thermostatTargetModeAuto | Word used for activating the automatic mode of the device (if applicable). | Auto | +| thermostatTargetModeOff | Word used to set the thermostat mode of the device to off (if applicable). | Off | +| minimumTemperature | Lower bound of possible temperatures, used in the user interface of the iOS device to display the allowed temperature range. Note that this setting applies to all devices in HomeKit. | -100 | +| maximumTemperature | Upper bound of possible temperatures, used in the user interface of the iOS device to display the allowed temperature range. Note that this setting applies to all devices in HomeKit. | 100 | +| name | Name under which this HomeKit bridge is announced on the network. This is also the name displayed on the iOS device when searching for available bridges. | openHAB | ## Item Configuration After setting this global configuration, you will need to tag your [openHAB items](https://www.openhab.org/docs/configuration/items.html) for HomeKit in order to map them to an ontology. -For our purposes, you may consider HomeKit accessories to be of two forms: simple and complex. - -A simple accessory will be mapped to a single openHAB item (i.e. a Lightbulb is mapped to a Switch, Dimmer, or Color item). -A complex accessory will be made up of multiple openHAB items (i.e. a Thermostat is composed of Heating and Cooling thresholds, a mode, and current temperature). -Complex accessories require a tag on a Group indicating the accessory type, as well as tags on the items it composes. - -A full list of supported accessory types can be found in the table below. - -| Tag | Child tag | Supported items | Description | -|-------------------- |-------------------------------- |----------------------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Lighting | | Switch, Dimmer, Color | A lightbulb, switchable, dimmable or rgb | -| Switchable | | Switch, Dimmer, Color | An accessory that can be turned off and on. While similar to a lightbulb, this will be presented differently in the Siri grammar and iOS apps | -| ContactSensor | | Contact | An accessory with on/off state that can be viewed in HomeKit but not changed such as a contact sensor for a door or window | -| CurrentTemperature | | Number | An accessory that provides a single read-only temperature value. The units default to celsius but can be overridden globally using the useFahrenheitTemperature global property | -| CurrentHumidity | | Number | An accessory that provides a single read-only value indicating the relative humidity. | -| Thermostat | | Group | A thermostat requires all child tags defined below | -| | CurrentTemperature | Number | The current temperature, same as above | -| | homekit:TargetHeatingCoolingMode | String | Indicates the desired mode of the device: OFF, AUTO, HEAT, COOL. The string's value must match those defined in the thermostat*Mode properties. This is a HomeKit-specific term and therefore the tags needs to be prefixed with "homekit:" | -| | homekit:CurrentHeatingCoolingMode | String | Indicates the current mode of the device: OFF, AUTO, HEAT, COOL. The string's value must match those defined in the thermostat*Mode properties. This is a HomeKit-specific term and therefore the tags needs to be prefixed with "homekit:" | -| | homekit:TargetTemperature | Number | A target temperature that will engage the thermostat's heating and cooling actions as necessary, depending on the heatingCoolingMode. This is a HomeKit-specific term and therefore the tags needs to be prefixed with "homekit:" | -| WindowCovering | | Rollershutter | A window covering | -| Lock | | Switch | A Lock Mechanism | - -**Please note:** `TargetTemperature` has been renamed to `homekit:TargetTemperature` and `homekit:HeatingCoolingMode` has been renamed to `homekit:TargetHeatingCoolingMode`. +For our purposes, you may consider HomeKit accessories to be of two types: simple and complex. + +A simple accessory will be mapped to a single openHAB item (i.e. Lightbulb is mapped to Switch, Dimmer, or Color item). +A complex accessory will be made up of multiple openHAB items (i.e. Thermostat is composed of mode, and current & target temperature). +Complex accessories require a tag on a Group Item indicating the accessory type, as well as tags on the items it composes. + +A HomeKit accessory has mandatory and optional characteristics (listed below in the table). +The mapping between OpenHAB items and HomeKit accessory and characteristics is done by means of tagging. +You can tag OpenHAB items using: + +- [tags](https://www.openhab.org/docs/configuration/items.html#tags) (deprecated) +- [metadata](https://www.openhab.org/docs/concepts/items.html#item-metadata) + +e.g. + +```xtend +Switch leaksensor_tag "Leak Sensor with Tag" [ "LeakSensor" ] +Switch leaksensor_metadata "Leak Sensor" {homekit="LeakSensor"} +``` + +The HomeKit integration currently supports both options. You can mix both options in the same configuration file. +If an OpenHAB item has both, tags and metadata, then HomeKit integration will use only metadata and ignore tags. +In general, the `tag` way is considered legacy and may be removed in future releases. + +You can link one OpenHAB item to one or more HomeKit accessory, e.g. + +```xtend +Switch occupancy_and_motion_sensor "Occupancy and Motion Sensor Tag" {homekit="OccupancySensor,MotionSensor"} +``` + +The tag can be: + +- full qualified: i.e. with accessory type and characteristic, e.g. "LeakSensor.LeakDetectedState" +- shorthand version: with only either accessory type or characteristic, .e.g. "LeakSensor", "LeakDetectedState". + + +if shorthand version has only accessory type, then HomeKit integration will automatically link *all* mandatory characteristics of this accessory type to the OpenHab item. +e.g. window covering has 3 mandatory characteristics +and following are identical definitions of window covering + +```xtend +Rollershutter window_covering "Window Rollershutter" {homekit="WindowCovering"} +Rollershutter window_covering "Window Rollershutter" {homekit="WindowCovering, WindowCovering.CurrentPosition, WindowCovering.TargetPosition, WindowCovering.PositionState"} +``` + +If the shorthand version has only a characteristic then it must be a part of a group which has a HomeKit accessory type. + +Complex accessories are defined using group item. The group item must indicated the HomeKit accessory type, e.g. +using tags (in shorthand notation) + +```xtend +Group gLegacy_leaksensor "Legacy Leak sensor Group" [ "LeakSensor" ] +Switch legacy_leaksensor "Legacy Leak sensor" (gLegacy_Leaksensor) [ "LeakSensor" ] +Switch legacy_leaksensor_battery "Legacy Leak sensor battery status" (gLegacy_Leaksensor) [ "homekit:BatteryLowStatus" ] +``` + +using metadata + +```xtend +Group gLeakSensor "Leak Sensor Group" {homekit="LeakSensor"} +Switch leaksensor "Leak Sensor" (gLeakSensor) {homekit="LeakSensor.LeakDetectedState"} +Switch leaksensor_battery "Leak Sensor Battery" (gLeakSensor) {homekit="LeakSensor.BatteryLowStatus"} +``` + +A full list of supported accessory types can be found in the table *below*. + +| Accessory Tag | Mandatory Characteristics | Optional Characteristics | Supported OH items | Description | +|:---------------------|:----------------------------|:-----------------------------|:-------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| LeakSensor | | | | Leak Sensor | +| | LeakDetectedState | | SwitchItem, Contact Item | Leak sensor state (ON=Leak Detected, OFF=no leak | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch,Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| MotionSensor | | | | Motion Sensor | +| | MotionDetectedState | | SwitchItem, Contact Item | Motion sensor state (ON=motion detected, OFF=no motion | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| OccupancySensor | | | | Occupancy Sensor | +| | OccupancyDetectedState | | SwitchItem, Contact Item | Occupancy sensor state (ON=occupied, OFF=not occupied | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| ContactSensor | | | | Contact Sensor,An accessory with on/off state that can be viewed in HomeKit but not changed such as a contact sensor for a door or window | +| | ContactSensorState | | SwitchItem, Contact Item | Contact sensor state (ON=open, OFF=closed) | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| SmokeSensor | | | | Smoke Sensor | +| | SmokeDetectedState | | SwitchItem, Contact Item | Smoke sensor state (ON=smoke detected, OFF=no smoke) | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| HumiditySensor | | | | Relative Humidity Sensor providing read-only values | +| | RelativeHumidity | | Number | relative humidity in % between 0 and 100. additional configuration homekitMultiplicator = . | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| TemperatureSensor | | | | Temperature sensor | +| | CurrentTemperature | | Number | current temperature | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| CarbonDioxideSensor | | | | Carbon Dioxide Sensor | +| | CarbonDioxideDetectedState | | Switch, Contact | carbon dioxide sensor state (ON- abnormal level of carbon dioxide detected, OFF - level is normal) | +| | | CarbonDioxideLevel | Number | Carbon dioxide level in ppm, max 100000 | +| | | CarbonDioxidePeakLevel | Number | highest detected level (ppm) of carbon dioxide detected by a sensor, max 100000 | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| CarbonMonoxideSensor | | | | Carbon monoxide Sensor | +| | CarbonMonoxideDetectedState | | Switch, Contact | Carbon monoxide sensor state (ON- abnormal level of carbon monoxide detected, OFF - level is normal) | +| | | CarbonMonoxideLevel | Number | Carbon monoxide level in ppm, max 100 | +| | | CarbonMonoxidePeakLevel | Number | highest detected level (ppm) of carbon monoxide detected by a sensor, max 100 | +| | | Name | String | Name of the sensor | +| | | ActiveStatus | Switch, Contact | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| | | BatteryLowStatus | Switch, Contact | accessory battery status. A value of "ON"/"OPEN" indicate that the battery level of the accessory is low. Value should return to "OFF"/"CLOSED" when the battery charges to a level thats above the low threshold. | +| WindowCovering | | | | Window covering / blinds. One Rollershutter item covers all mandatory characteristics. see examples below. | +| | CurrentPosition | | Rollershutter | Current position of window covering | +| | TargetPosition | | Rollershutter | Target position of window covering | +| | PositionState | | Rollershutter | current only "STOPPED" is supported. | +| | | Name | String | Name of the windows covering | +| | | HoldPosition | Switch | Window covering should stop at its current position. A value of ON must hold the state of the accessory. A value of OFF should be ignored. | +| | | ObstructionStatus | Switch, Contact | Current status of obstruction sensor. ON-obstruction detected, OFF - no obstruction | +| | | CurrentHorizontalTiltAngle | Number | current angle of horizontal slats for accessories windows. values -90 to 90. A value of 0 indicates that the slats are rotated to a fully open position. A value of -90 indicates that the slats are rotated all the way in a direction where the user-facing edge is higher than the window-facing edge. | +| | | TargetHorizontalTiltAngle | Number | target angle of horizontal slats | +| | | CurrentVerticalTiltAngle | Number | current angle of vertical slats | +| | | TargetVerticalTiltAngle | Number | target angle of vertical slats | +| Switchable | | | | An accessory that can be turned off and on. While similar to a lightbulb, this will be presented differently in the Siri grammar and iOS apps | +| | OnState | | Switch | State of the switch - ON/OFF | +| | | Name | String | Name of the switch | +| Outlet | | | | An accessory that can be turned off and on. While similar to a lightbulb, this will be presented differently in the Siri grammar and iOS apps | +| | OnState | | Switch | State of the outlet - ON/OFF | +| | InUseStatus | | Switch | indicated whether current flowing through the outlet | +| | | Name | String | Name of the switch | +| Lighting | | | | A lightbulb, can have further optional parameters for brightness, hue, etc | +| | OnState | | SwitchItem | State of the light - ON/OFF | +| | | Name | String | Name of the light | +| | | Hue | Dimmer, Color | Hue | +| | | Saturation | Dimmer, Color | Saturation in % (1-100) | +| | | Brightness | Dimmer, Color | Brightness in % (1-100) | +| | | ColorTemperature | Number | Color temperature which is represented in reciprocal megaKelvin, values - 50 to 400. should not be used in combination with hue, saturation and brightness | +| Fan | | | | Fan | +| | ActiveStatus | | Switch | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | | CurrentFanState | Number | current fan state. values: 0=INACTIVE, 1=IDLE, 2=BLOWING AIR | +| | | TargetFanState | Number | target fan state. values: 0=MANUAL, 1=AUTO | +| | | RotationDirection | Number,SwitchItem | rotation direction. values: 0/OFF=CLOCKWISE, 1/ON=COUNTER CLOCKWISE | +| | | RotationSpeed | Number | fan rotation speed in % (1-100) | +| | | SwingMode | Number,SwitchItem | swing mode. values: 0/OFF=SWING DISABLED, 1/ON=SWING ENABLED | +| | | LockControl | Number,SwitchItem | status of physical control lock. values: 0/OFF=CONTROL LOCK DISABLED, 1/ON=CONTROL LOCK ENABLED | +| Thermostat | | | | A thermostat requires all mandatory characteristics defined below | +| | CurrentTemperature | | Number | current temperature | +| | TargetTemperature | | Number | target temperature | +| | CurrentHeatingCoolingMode | | String | Current heating cooling mode (OFF, AUTO, HEAT, COOL). for mapping see homekit settings above. | +| | TargetHeatingCoolingMode | | String | Target heating cooling mode (OFF, AUTO, HEAT, COOL). for mapping see homekit settings above. | +| Lock | | | | A Lock Mechanism | +| | LockCurrentState | | Switch | current states of lock mechanism (OFF=SECURED, ON=UNSECURED) | +| | LockTargetState | | Switch | target states of lock mechanism (OFF=SECURED, ON=UNSECURED) | +| | | Name | String | Name of the lock | +| Valve | | | | Valve. additional configuration: homekitValveType = ["Generic", "Irrigation", "Shower", "Faucet"] | +| | ActiveStatus | | Switch | accessory current working status. A value of "ON"/"OPEN" indicate that the accessory is active and is functioning without any errors. | +| | InUseStatus | | Switch | indicated whether fluid flowing through the valve. A value of "ON"/"OPEN" indicate that fluid is flowing. | +| | | Duration | Number | defines how long a valve should be set to ʼIn Useʼ in second. You can define the default duration via configuration homekitDefaultDuration = | +| | | RemainingDuration | Number | describes the remaining duration on the accessory. the remaining duration increases/decreases from the accessoryʼs usual countdown. i.e. changes from 90 to 80 in a second. | +| | | Name | String | Name of the lock | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| SecuritySystem | | | | Security system. | +| | CurrentSecuritySystemState | | String | Current state of the security system. STAY_ARM / AWAY_ARM / NIGHT_ARM / DISARMED / TRIGGERED | +| | TargetSecuritySystemState | | String | Requested state of the security system. STAY_ARM / AWAY_ARM / NIGHT_ARM / DISARM. While the requested state is not DISARM, and the current state is DISARMED, HomeKit will display "Arming...", for example during an exit delay. | +| | | Name | String | Name of the security system | +| | | FaultStatus | Switch, Contact | accessory fault status. "ON"/"OPEN" value indicates that the accessory has experienced a fault that may be interfering with its intended functionality. A value of "OFF"/"CLOSED" indicates that there is no fault. | +| | | TamperedStatus | Switch, Contact | accessory tampered status. A status of "ON"/"OPEN" indicates that the accessory has been tampered with. Value should return to "OFF"/"CLOSED" when the accessory has been reset to a non-tampered state. | +| GarageDoorOpener | | | | A garage door opener. | +| | ObstructionStatus | | Switch | Current status of obstruction sensor. ON-obstruction detected, OFF - no obstruction | +| | CurrentDoorState | | String | Current door state. Possible values: OPEN, OPENING, CLOSED, CLOSING, STOPPED | +| | TargetDoorState | | Switch, String | Target door state. ON/"OPEN" = open door, OFF/"CLOSED" = closed door | +| | | Name | String | Name of the garage door | +| | | LockCurrentState | Switch | current states of lock mechanism (OFF=SECURED, ON=UNSECURED) | +| | | LockTargetState | Switch | target states of lock mechanism (OFF=SECURED, ON=UNSECURED) | + +### Legacy tags + +Following tags are still supported but could be removed in the future releases. Please consider replacing them with the new style. + +| Old (tag style) | New (metadata style) | +|:---------------------------------|:------------------------------------------------| +| homekit:HeatingCoolingMode | CurrentHeatingCoolingMode | +| homekit:TargetHeatingCoolingMode | TargetHeatingCoolingMode | +| homekit:TargetTemperature | TargetTemperature | +| homekit:BatteryLowStatus | BatteryLowStatus | +| homekit:BatteryLevel | mapping to BatteryLowStatus | +| CurrentHumidity | RelativeHumidity | +| Blinds | WindowCovering | +| DimmableLighting | Lighting with characteristic Brightness | +| ColorfulLighting | Lighting with characteristic Brightness and Hue | + + +### Examples See the sample below for example items: +#### Using "tag" + +```xtend +Color legacy_color_light_single "Legacy Color Light Single" [ "Lighting" ] +Color legacy_color_light_dimmable "Legacy Color Light Dimmable" [ "DimmableLighting" ] +Color legacy_color_light_hue "Legacy Color Light Hue" [ "ColorfulLighting" ] + +Rollershutter legacy_window_covering "Legacy Window Rollershutter" [ "WindowCovering" ] +Switch legacy_switch_single "Legacy Switch single" [ "Switchable" ] +Switch legacy_contactsensor_single "Legacy Contact Sensor single" [ "ContactSensor" ] +Switch legacy_leaksensor_single "Legacy Leak Sensor single" [ "LeakSensor" ] +Switch legacy_leaksensor_single2 "Legacy Leak Sensor single 2" [ "LeakSensor", "LeakSensor.LeakDetectedState" ] +Switch legacy_motionsensor_single "Legacy Motion Sensor" [ "MotionSensor" ] +Switch legacy_occupancy_single "Legacy Occupanncy Sensor" [ "OccupancySensor" ] +Switch legacy_smoke_single "Legacy Smoke Sensor" [ "SmokeSensor" ] +Number legacy_humidity_single "Legacy Humidity Sensor" [ "CurrentHumidity" ] + +Switch legacy_lock "Legacy Lock single" [ "Lock" ] + +Switch legacy_valve_single "Legacy Valve Single" [ "Valve" ] + +Group gLegacy_Valve "Legacy Valve Group" [ "Valve" ] +Switch legacy_valve_active "Legacy Valve active" (gLegacy_Valve) [ "Active" ] +Number legacy_valve_duration "Legacy Valve duration" (gLegacy_Valve) [ "Duration" ] +Number legacy_valve_remaining_duration "Legacy Valve remaining duration" (gLegacy_Valve) [ "RemainingDuration" ] + +Group gLegacy_Thermo "Legacy Thermostat" [ "Thermostat" ] +Number legacy_thermostat_current_temp "L Therm. Cur. Temp. [%.1f C]" (gLegacy_Thermo) [ "CurrentTemperature" ] +Number legacy_thermostat_target_temp "L Therm. Target Temp.[%.1f C]" (gLegacy_Thermo) [ "homekit:TargetTemperature" ] +String legacy_thermostat_current_mode "Legacy Thermostat Current Mode" (gLegacy_Thermo) [ "homekit:CurrentHeatingCoolingMode" ] +String legacy_thermostat_target_mode "Thermostat Target Mode" (gLegacy_Thermo) [ "homekit:TargetHeatingCoolingMode" ] + +Group gLegacy_Leaksensor "Legacy Leak Sensor Group" [ "LeakSensor" ] +Switch legacy_leaksensor "Legacy Leak Sensor" (gLegacy_Leaksensor) [ "LeakSensor" ] +Switch legacy_leaksensor_bat "Legacy Leak sensor battery status" (gLegacy_Leaksensor) [ "homekit:BatteryLowStatus" ] +Switch legacy_leaksensor_fault "Legacy Leak sensor fault" (gLegacy_Leaksensor) [ "FaultStatus" ] + +Group gLegacy_Security "Legacy Security System Group" [ "SecuritySystem" ] +String legacy_SecurityCurrentState "Security Current State" (gLegacy_Security) [ "CurrentSecuritySystemState" ] +String legacy_SecurityTargetState "Security Target State" (gLegacy_Security) [ "TargetSecuritySystemState" ] +``` + +#### Using "metadata" + +```xtend +Color color_light_single "Color Light Single" {homekit="Lighting, Lighting.Hue, Lighting.Brightness, Lighting.Saturation"} +Rollershutter window_covering "Window Rollershutter" {homekit="WindowCovering"} +Rollershutter window_covering_long "Window Rollershutter long" {homekit="WindowCovering.CurrentPosition, WindowCovering.TargetPosition, WindowCovering.PositionState"} + +Switch leaksensor_single "Leak Sensor single" {homekit="LeakSensor"} +Switch lock "Lock single" {homekit="Lock"} +Switch valve_single "Valve single" {homekit="Valve" [homekitValveType="Shower"]} + +Group gValve "Valve Group" {homekit="Valve" [homekitValveType="Irrigation"]} +Switch valve_active "Valve active" (gValve) {homekit="Valve.ActiveStatus, Valve.InUseStatus"} +Number valve_duration "Valve duration" (gValve) {homekit="Valve.Duration"} +Number valve_remaining_duration "Valve remaining duration" (gValve) {homekit="Valve.RemainingDuration"} + +Group gThermostat "Thermostat" {homekit="Thermostat"} +Number thermostat_current_temp "Thermostat Current Temp [%.1f C]" (gThermostat) {homekit="Thermostat.CurrentTemperature"} +Number thermostat_target_temp "Thermostat Target Temp[%.1f C]" (gThermostat) {homekit="Thermostat.TargetTemperature"} +String thermostat_current_mode "Thermostat Current Mode" (gThermostat) {homekit="Thermostat.CurrentHeatingCoolingMode"} +String thermostat_target_mode "Thermostat Target Mode" (gThermostat) {homekit="Thermostat.TargetHeatingCoolingMode"} + +Group gLeakSensor "Leak Sensor Group" {homekit="LeakSensor"} +Switch leaksensor "Leak Sensor" (gLeakSensor) {homekit="LeakDetectedState"} +String leaksensor_name "Leak Sensor Name" (gLeakSensor) {homekit="Name"} +Switch leaksensor_bat "Leak Sensor Battery" (gLeakSensor) {homekit="BatteryLowStatus"} +Switch leaksensor_active "Leak Sensor Active" (gLeakSensor) {homekit="ActiveStatus"} +Switch leaksensor_fault "Leak Sensor Fault" (gLeakSensor) {homekit="FaultStatus"} +Switch leaksensor_tampered "Leak Sensor Tampered" (gLeakSensor) {homekit="TamperedStatus"} + +Group gMotionSensor "Motion Sensor Group" {homekit="MotionSensor"} +Switch motionsensor "Motion Sensor" (gMotionSensor) {homekit="MotionSensor.MotionDetectedState"} +Switch motionsensor_bat "Motion Sensor Battery" (gMotionSensor) {homekit="MotionSensor.BatteryLowStatus"} +Switch motionsensor_active "Motion Sensor Active" (gMotionSensor) {homekit="MotionSensor.ActiveStatus"} +Switch motionsensor_fault "Motion Sensor Fault" (gMotionSensor) {homekit="MotionSensor.FaultStatus"} +Switch motionsensor_tampered "Motion Sensor Tampered" (gMotionSensor) {homekit="MotionSensor.TamperedStatus"} + +Group gOccupancySensor "Occupancy Sensor Group" {homekit="OccupancySensor"} +Switch occupancysensor "Occupancy Sensor" (gOccupancySensor) {homekit="OccupancyDetectedState"} +Switch occupancysensor_bat "Occupancy Sensor Battery" (gOccupancySensor) {homekit="BatteryLowStatus"} +Switch occupancysensor_active "Occupancy Sensor Active" (gOccupancySensor) {homekit="OccupancySensor.ActiveStatus"} +Switch occupancysensor_fault "Occupancy Sensor Fault" (gOccupancySensor) {homekit="OccupancySensor.FaultStatus"} +Switch occupancysensor_tampered "Occupancy Sensor Tampered" (gOccupancySensor) {homekit="OccupancySensor.TamperedStatus"} + +Group gContactSensor "Contact Sensor Group" {homekit="ContactSensor"} +Contact contactsensor "Contact Sensor" (gContactSensor) {homekit="ContactSensor.ContactSensorState"} +Switch contactsensor_bat "Contact Sensor Battery" (gContactSensor) {homekit="ContactSensor.BatteryLowStatus"} +Switch contactsensor_active "Contact Sensor Active" (gContactSensor) {homekit="ContactSensor.ActiveStatus"} +Switch contactsensor_fault "Contact Sensor Fault" (gContactSensor) {homekit="ContactSensor.FaultStatus"} +Switch contactsensor_tampered "Contact Sensor Tampered" (gContactSensor) {homekit="ContactSensor.TamperedStatus"} + +Group gSecuritySystem "Security System Group" {homekit="SecuritySystem"} +String security_current_state "Security Current State" (gSecuritySystem) {homekit="SecuritySystem.CurrentSecuritySystemState"} +String security_target_state "Security Target State" (gSecuritySystem) {homekit="SecuritySystem.TargetSecuritySystemState"} ``` -Switch KitchenLights "Kitchen Lights" (gKitchen) [ "Lighting" ] -Dimmer BedroomLights "Bedroom Lights" (gBedroom) [ "Lighting" ] -Number BedroomTemperature "Bedroom Temperature" (gBedroom) [ "CurrentTemperature" ] -Group gDownstairsThermostat "Downstairs Thermostat" (gFF) [ "Thermostat" ] -Number DownstairsThermostatCurrentTemp "Downstairs Thermostat Current Temperature" (gDownstairsThermostat) [ "CurrentTemperature" ] -Number DownstairsThermostatTargetTemperature "Downstairs Thermostat Target Temperature" (gDownstairsThermostat) [ "homekit:TargetTemperature" ] -String DownstairsThermostatHeatingCoolingMode "Downstairs Thermostat Heating/Cooling Mode" (gDownstairsThermostat) [ "homekit:TargetHeatingCoolingMode" ] + + +## Usage of valve timer + +The HomeKit valve accessory supports following 2 optional characteristics: + +- duration: this describes how long the valve should set "InUse" once it is activated. The duration changes will apply to the next operation. If valve is already active then duration changes have no effect. + +- remaining duration: this describes the remaining duration on the valve. Notifications on this characteristic must only + be used if the remaining duration increases/decreases from the accessoryʼs usual countdown of remaining duration. + +Upon valve activation in home app, home app starts to count down from the "duration" to "0" without contacting the server. Home app also does not trigger any acion if it remaining duration get 0. +It is up to valve to have an own timer and stop valve once the timer is over. +Some valves have such timer, e.g. pretty common for sprinklers. +In case the valve has no timer capability, OpenHAB can take care on this - start an internal timer and send "Off" command to the valve once the timer is over. + +configuration for these two cases looks as follow: + +- valve with timer: + +```xtend +Group gValve "Valve Group" {homekit="Valve" [homekitValveType="Irrigation"]} +Switch valve_active "Valve active" (gValve) {homekit = "Valve.ActiveStatus, Valve.InUseStatus"} +Number valve_duration "Valve duration" (gValve) {homekit = "Valve.Duration"} +Number valve_remaining_duration "Valve remaining duration" (gValve) {homekit = "Valve.RemainingDuration"} +``` + +- valve without timer (no item for remaining duration required) + +```xtend +Group gValve "Valve Group" {homekit="Valve" [homekitValveType="Irrigation", homekitTimer="true]} +Switch valve_active "Valve active" (gValve) {homekit = "Valve.ActiveStatus, Valve.InUseStatus"} +Number valve_duration "Valve duration" (gValve) {homekit = "Valve.Duration" [homekitDefaultDuration = 1800]} ``` + ## Common Problems **openHAB HomeKit hub shows up when I manually scan for devices, but Home app reports "can't connect to device"** @@ -126,6 +442,13 @@ If you encounter any issues with the add-on and need support, it may be importan In order to get logs from the underlying library used to implement the HomeKit protocol, enable trace logging using the following commands at [the console](https://www.openhab.org/docs/administration/console.html): ``` -openhab> log:set TRACE com.beowulfe.hap -openhab> log:tail com.beowulfe.hap +openhab> log:set TRACE io.github.hapjava +openhab> log:tail io.github.hapjava ``` + +## Console commands + +`smarthome:homekit list` - list all HomeKit accessories currently advertised to the HomeKit clients. + +`smarthome:homekit show ` - print additional details of the accessories which partially match provided ID or name. + \ No newline at end of file diff --git a/bundles/org.openhab.io.homekit/pom.xml b/bundles/org.openhab.io.homekit/pom.xml index e114c24e44e00..d1737ad85c96e 100644 --- a/bundles/org.openhab.io.homekit/pom.xml +++ b/bundles/org.openhab.io.homekit/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.homekit @@ -14,14 +16,14 @@ javax.json,javax.json-api,netty-common,netty-buffer,netty-transport,netty-handler,netty-codec,netty-codec-http,netty-resolver - 4.1.42.Final + 4.1.42.Final io.github.hap-java hap - 1.2.0.OH + 2.0.0.OH compile @@ -103,5 +105,4 @@ compile - diff --git a/bundles/org.openhab.io.homekit/src/main/feature/feature.xml b/bundles/org.openhab.io.homekit/src/main/feature/feature.xml index 2f658a7eb71d0..3db3fc36901c8 100644 --- a/bundles/org.openhab.io.homekit/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.homekit/src/main/feature/feature.xml @@ -1,13 +1,13 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mdns - openhab.tp-netty - mvn:org.glassfish/javax.json/1.0.4 - mvn:javax.json/javax.json-api/1.0 - mvn:org.openhab.addons.bundles/org.openhab.io.homekit/${project.version} - + + openhab-runtime-base + openhab-transport-mdns + openhab.tp-netty + mvn:org.glassfish/javax.json/1.0.4 + mvn:javax.json/javax.json-api/1.0 + mvn:org.openhab.addons.bundles/org.openhab.io.homekit/${project.version} + diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/Homekit.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/Homekit.java index b18205fc44a9a..fd2f4f2af1749 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/Homekit.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/Homekit.java @@ -13,12 +13,18 @@ package org.openhab.io.homekit; import java.io.IOException; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import io.github.hapjava.accessories.HomekitAccessory; /** * HomeKit integration API * * @author Andy Lintner - Initial contribution */ +@NonNullByDefault public interface Homekit { /** @@ -37,4 +43,9 @@ public interface Homekit { * @param allow boolean indicating whether or not to allow unauthenticated requests */ void allowUnauthenticatedRequests(boolean allow); + + /** + * returns list of HomeKit accessories registered at bridge. + */ + List getAccessories(); } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/Debouncer.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/Debouncer.java index 9f1e7a34184e7..ee4a39ad8d9e7 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/Debouncer.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/Debouncer.java @@ -86,7 +86,7 @@ private void tryActionOrPostpone() { if (delaySurpassed) { if (pending.compareAndSet(true, false)) { int foldedCalls = calls.getAndSet(0); - logger.debug("Debouncer action {} invoked after delay {} ({} calls)", name, delayMs, foldedCalls); + logger.trace("Debouncer action {} invoked after delay {} ({} calls)", name, delayMs, foldedCalls); try { action.run(); } catch (Exception e) { diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryRegistry.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryRegistry.java index 67617b2eecc19..e242a63bcd3ad 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryRegistry.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryRegistry.java @@ -12,19 +12,16 @@ */ package org.openhab.io.homekit.internal; +import java.io.IOException; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; import org.eclipse.jdt.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitAccessory; -import io.github.hapjava.HomekitRoot; +import io.github.hapjava.accessories.HomekitAccessory; +import io.github.hapjava.server.impl.HomekitRoot; /** * Stores the created HomekitAccessories. GroupedAccessories are also held here @@ -36,14 +33,35 @@ class HomekitAccessoryRegistry { private @Nullable HomekitRoot bridge; private final Map createdAccessories = new HashMap<>(); - private final Set createdIds = new HashSet<>(); - + private int configurationRevision = 1; private final Logger logger = LoggerFactory.getLogger(HomekitAccessoryRegistry.class); + public void setConfigurationRevision(int revision) { + configurationRevision = revision; + } + + public int getConfigurationRevision() { + return configurationRevision; + } + + public int makeNewConfigurationRevision() { + configurationRevision = (configurationRevision + 1) % 65535; + final HomekitRoot bridge = this.bridge; + try { + if (bridge != null) { + bridge.setConfigurationIndex(configurationRevision); + } + } catch (IOException e) { + logger.warn("Could not update configuration revision number", e); + } + return configurationRevision; + } + public synchronized void remove(String itemName) { if (createdAccessories.containsKey(itemName)) { HomekitAccessory accessory = createdAccessories.remove(itemName); - logger.debug("Removed accessory {} for taggedItem {}", accessory.getId(), itemName); + logger.trace("Removed accessory {} for taggedItem {}", accessory, itemName); + final HomekitRoot bridge = this.bridge; if (bridge != null) { bridge.removeAccessory(accessory); } else { @@ -53,38 +71,37 @@ public synchronized void remove(String itemName) { } public synchronized void clear() { - Iterator> iter = createdAccessories.entrySet().iterator(); - while (iter.hasNext()) { - Entry entry = iter.next(); - if (bridge != null) { - bridge.removeAccessory(entry.getValue()); - } else { - logger.warn("trying to clear {} but bridge is null", entry); - } - iter.remove(); + final HomekitRoot bridge = this.bridge; + if (bridge != null) { + createdAccessories.values().forEach(bridge::removeAccessory); + } else { + logger.warn("trying to clear accessories but bridge is null"); } - createdIds.clear(); } public synchronized void setBridge(HomekitRoot bridge) { this.bridge = bridge; - createdAccessories.values().forEach(accessory -> bridge.addAccessory(accessory)); + createdAccessories.values().forEach(bridge::addAccessory); } public synchronized void unsetBridge() { final HomekitRoot oldBridge = bridge; if (oldBridge != null) { - createdAccessories.values().forEach(accessory -> oldBridge.removeAccessory(accessory)); + createdAccessories.values().forEach(oldBridge::removeAccessory); } bridge = null; } public synchronized void addRootAccessory(String itemName, HomekitAccessory accessory) { createdAccessories.put(itemName, accessory); - createdIds.add(accessory.getId()); + final HomekitRoot bridge = this.bridge; if (bridge != null) { bridge.addAccessory(accessory); } - logger.debug("Added accessory {}", accessory.getId()); + logger.trace("Added accessory {}", accessory.getId()); + } + + public Map getAllAccessories() { + return this.createdAccessories; } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryType.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryType.java index 218a7d96349fc..67143a8e661f0 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryType.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryType.java @@ -14,12 +14,7 @@ import java.util.HashMap; import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import org.eclipse.smarthome.core.items.Item; -import org.eclipse.smarthome.core.library.items.ColorItem; -import org.eclipse.smarthome.core.library.items.DimmerItem; +import java.util.Optional; /** * Enum of the possible device types. The defined tag string can be used @@ -28,13 +23,11 @@ * @author Andy Lintner - Initial contribution */ public enum HomekitAccessoryType { - DIMMABLE_LIGHTBULB("DimmableLighting"), - HUMIDITY_SENSOR("CurrentHumidity"), + HUMIDITY_SENSOR("HumiditySensor"), LIGHTBULB("Lighting"), SWITCH("Switchable"), - TEMPERATURE_SENSOR("CurrentTemperature"), + TEMPERATURE_SENSOR("TemperatureSensor"), THERMOSTAT("Thermostat"), - COLORFUL_LIGHTBULB("ColorfulLighting"), CONTACT_SENSOR("ContactSensor"), VALVE("Valve"), LEAK_SENSOR("LeakSensor"), @@ -43,9 +36,22 @@ public enum HomekitAccessoryType { WINDOW_COVERING("WindowCovering"), SMOKE_SENSOR("SmokeSensor"), CARBON_MONOXIDE_SENSOR("CarbonMonoxideSensor"), + CARBON_DIOXIDE_SENSOR("CarbonDioxideSensor"), + FAN("Fan"), + LOCK("Lock"), + SECURITY_SYSTEM("SecuritySystem"), + OUTLET("Outlet"), + SPEAKER("Speaker"), + GARAGE_DOOR_OPENER("GarageDoorOpener"), + DUMMY("Dummy"), @Deprecated() BLINDS("Blinds"), - LOCK("Lock"); + @Deprecated() + OLD_DIMMABLE_LIGHTBULB("DimmableLighting"), + @Deprecated() + OLD_HUMIDITY_SENSOR("CurrentHumidity"), + @Deprecated() + OLD_COLORFUL_LIGHTBULB("ColorfulLighting"); private static final Map TAG_MAP = new HashMap<>(); @@ -69,28 +75,9 @@ public String getTag() { * get accessoryType from String * * @param tag the tag string - * @return accessoryType or null if not found - */ - public static HomekitAccessoryType valueOfTag(String tag) { - return TAG_MAP.get(tag); - } - - /** - * get accessoryType for a given Item - * - * @param item the item - * @return accessoryType or null if not found + * @return accessoryType or Optional.empty if no accessory type for the tag was found */ - public static HomekitAccessoryType fromItem(Item item) { - Set tags = item.getTags(); - HomekitAccessoryType accessoryType = tags.stream().map(tag -> TAG_MAP.get(tag)).filter(Objects::nonNull) - .findFirst().orElse(null); - if (item instanceof ColorItem && accessoryType == LIGHTBULB) { - return COLORFUL_LIGHTBULB; - } else if (item instanceof DimmerItem && accessoryType == LIGHTBULB) { - return DIMMABLE_LIGHTBULB; - } else { - return accessoryType; - } + public static Optional valueOfTag(String tag) { + return Optional.ofNullable(TAG_MAP.get(tag)); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryUpdater.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryUpdater.java index 98ecc87d6858b..b3a259f04a295 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryUpdater.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAccessoryUpdater.java @@ -22,7 +22,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; /** * Subscribes and unsubscribes from Item changes to enable notification to HomeKit @@ -55,7 +55,7 @@ public void subscribe(GenericItem item, String key, HomekitCharacteristicChangeC logger.debug("Received duplicate subscription for {} / {}", item, key); unsubscribe(item, key); } - logger.debug("Adding subscription for {} / {}", item, key); + logger.trace("Adding subscription for {} / {}", item, key); Subscription subscription = (changedItem, oldState, newState) -> callback.changed(); item.addStateChangeListener(subscription); return subscription; @@ -71,7 +71,7 @@ public void unsubscribe(GenericItem item, String key) { return; } subscriptionsByName.computeIfPresent(new ItemKey(item, key), (k, v) -> { - logger.debug("Removing existing subscription for {} / {}", item, key); + logger.trace("Removing existing subscription for {} / {}", item, key); item.removeStateChangeListener(v); return null; }); diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAuthInfoImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAuthInfoImpl.java index 15e5c9d9191a8..ea7a6afbce1e2 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAuthInfoImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitAuthInfoImpl.java @@ -23,8 +23,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitAuthInfo; -import io.github.hapjava.HomekitServer; +import io.github.hapjava.server.HomekitAuthInfo; +import io.github.hapjava.server.impl.HomekitServer; /** * Provides a mechanism to store authenticated HomeKit client details inside the @@ -126,5 +126,4 @@ private void initializeStorage() throws InvalidAlgorithmParameterException { storage.put("privateKey", Base64.getEncoder().encodeToString(HomekitServer.generateKey())); } } - } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitChangeListener.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitChangeListener.java index 6cc1ec744024e..d55626b36e77a 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitChangeListener.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitChangeListener.java @@ -17,21 +17,28 @@ import java.util.Collection; import java.util.HashSet; import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.concurrent.ScheduledExecutorService; import org.eclipse.smarthome.core.common.ThreadPoolManager; +import org.eclipse.smarthome.core.items.GroupItem; import org.eclipse.smarthome.core.items.Item; import org.eclipse.smarthome.core.items.ItemNotFoundException; import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.items.ItemRegistryChangeListener; +import org.eclipse.smarthome.core.items.MetadataRegistry; +import org.eclipse.smarthome.core.storage.Storage; +import org.eclipse.smarthome.core.storage.StorageService; import org.openhab.io.homekit.internal.accessories.HomekitAccessoryFactory; -import org.openhab.io.homekit.internal.accessories.IncompleteAccessoryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitRoot; +import io.github.hapjava.accessories.HomekitAccessory; +import io.github.hapjava.server.impl.HomekitRoot; /** * Listens for changes to the item registry. When changes are detected, check @@ -41,10 +48,15 @@ */ public class HomekitChangeListener implements ItemRegistryChangeListener { private final Logger logger = LoggerFactory.getLogger(HomekitChangeListener.class); + private final static String REVISION_CONFIG = "revision"; + private final static String ACCESSORY_COUNT = "accessory_count"; private final ItemRegistry itemRegistry; private final HomekitAccessoryRegistry accessoryRegistry = new HomekitAccessoryRegistry(); + private final MetadataRegistry metadataRegistry; + private final Storage storage; private HomekitAccessoryUpdater updater = new HomekitAccessoryUpdater(); private HomekitSettings settings; + private int lastAccessoryCount; private Set pendingUpdates = new HashSet<>(); @@ -61,17 +73,36 @@ public class HomekitChangeListener implements ItemRegistryChangeListener { */ private final Debouncer applyUpdatesDebouncer; - HomekitChangeListener(ItemRegistry itemRegistry, HomekitSettings settings) { + HomekitChangeListener(ItemRegistry itemRegistry, HomekitSettings settings, MetadataRegistry metadataRegistry, + final StorageService storageService) { this.itemRegistry = itemRegistry; this.settings = settings; + this.metadataRegistry = metadataRegistry; + storage = storageService.getStorage("homekit"); this.applyUpdatesDebouncer = new Debouncer("update-homekit-devices", scheduler, Duration.ofMillis(1000), Clock.systemUTC(), this::applyUpdates); itemRegistry.addRegistryChangeListener(this); - itemRegistry.getAll().stream().map(item -> new HomekitTaggedItem(item, itemRegistry)) - .filter(taggedItem -> taggedItem.isAccessory()) - .filter(taggedItem -> !taggedItem.isMemberOfAccessoryGroup()) - .forEach(rootTaggedItem -> createRootAccessory(rootTaggedItem)); + itemRegistry.getItems().stream().forEach(this::createRootAccessories); + initialiseRevision(); + logger.info("Created {} HomeKit items.", accessoryRegistry.getAllAccessories().size()); + } + + private void initialiseRevision() { + int revision; + try { + revision = Integer.valueOf(storage.get(REVISION_CONFIG)); + } catch (java.lang.NumberFormatException e) { + revision = 1; + storage.put(REVISION_CONFIG, "" + revision); + } + try { + lastAccessoryCount = Integer.valueOf(storage.get(ACCESSORY_COUNT)); + } catch (java.lang.NumberFormatException e) { + lastAccessoryCount = 0; + storage.put(ACCESSORY_COUNT, "" + accessoryRegistry.getAllAccessories().size()); + } + accessoryRegistry.setConfigurationRevision(revision); } @Override @@ -91,12 +122,13 @@ public void allItemsChanged(Collection oldItemNames) { * @param item The item that has been changed or removed. */ private synchronized void markDirty(Item item) { + logger.trace("Mark dirty item {}", item.getLabel()); pendingUpdates.add(item.getName()); /* * If findMyAccessoryGroups fails because the accessory group has already been deleted, then we can count on a * later update telling us that the accessory group was removed. */ - for (Item accessoryGroup : HomekitTaggedItem.findMyAccessoryGroups(item, itemRegistry)) { + for (Item accessoryGroup : HomekitAccessoryFactory.getAccessoryGroups(item, itemRegistry, metadataRegistry)) { pendingUpdates.add(accessoryGroup.getName()); } @@ -116,16 +148,25 @@ private Optional getItemOptional(String name) { } } + public void makeNewConfigurationRevision() { + storage.put(REVISION_CONFIG, "" + accessoryRegistry.makeNewConfigurationRevision()); + lastAccessoryCount = accessoryRegistry.getAllAccessories().size(); + storage.put(ACCESSORY_COUNT, "" + lastAccessoryCount); + } + private synchronized void applyUpdates() { + logger.trace("apply updates"); Iterator iter = pendingUpdates.iterator(); while (iter.hasNext()) { String name = iter.next(); accessoryRegistry.remove(name); - - getItemOptional(name).map(i -> new HomekitTaggedItem(i, itemRegistry)) - .filter(i -> i.isAccessory() && !i.isMemberOfAccessoryGroup()) - .ifPresent(rootItem -> createRootAccessory(rootItem)); + logger.trace(" add items {}", name); + getItemOptional(name).ifPresent(this::createRootAccessories); + } + if (!pendingUpdates.isEmpty()) { + makeNewConfigurationRevision(); + pendingUpdates.clear(); } } @@ -135,6 +176,10 @@ public void updated(Item oldElement, Item element) { markDirty(element); } + public int getLastAccessoryCount() { + return lastAccessoryCount; + } + public synchronized void clearAccessories() { accessoryRegistry.clear(); } @@ -159,18 +204,40 @@ public void stop() { this.itemRegistry.removeRegistryChangeListener(this); } + public Map getAccessories() { + return this.accessoryRegistry.getAllAccessories(); + } + + public int getConfigurationRevision() { + return this.accessoryRegistry.getConfigurationRevision(); + } + + /** + * creates one or more HomeKit items for given openhab item. + * one openhab item can linked to several HomeKit accessories or characteristics. + * + * @param item + */ + private void createRootAccessories(Item item) { + logger.trace("create root accessory {}", item.getLabel()); + final List> accessoryTypes = HomekitAccessoryFactory + .getAccessoryTypes(item, metadataRegistry); + final List groups = HomekitAccessoryFactory.getAccessoryGroups(item, itemRegistry, metadataRegistry); + logger.trace("Item {} has groups {}", item.getName(), groups); + if (!accessoryTypes.isEmpty() && groups.isEmpty()) { // it has homekit accessory type and is not part of bigger + // homekit group item + logger.trace("Item {} is a HomeKit accessory of types {}", item.getName(), accessoryTypes); + accessoryTypes.stream().forEach(rootAccessory -> createRootAccessory(new HomekitTaggedItem(item, + rootAccessory.getKey(), HomekitAccessoryFactory.getItemConfiguration(item, metadataRegistry)))); + } + } + private void createRootAccessory(HomekitTaggedItem taggedItem) { try { - if (taggedItem.isMemberOfAccessoryGroup()) { - logger.warn("Bug! Cannot add {} as a root accessory if it is a member of a group! ", - taggedItem.getItem().getUID()); - return; - } - logger.debug("Adding HomeKit device {}", taggedItem.getItem().getUID()); + logger.trace("Adding HomeKit device {}", taggedItem.getItem().getUID()); accessoryRegistry.addRootAccessory(taggedItem.getName(), - HomekitAccessoryFactory.create(taggedItem, itemRegistry, updater, settings)); - logger.debug("Added HomeKit device {}", taggedItem.getItem().getUID()); - } catch (HomekitException | IncompleteAccessoryException e) { + HomekitAccessoryFactory.create(taggedItem, metadataRegistry, updater, settings)); + } catch (HomekitException e) { logger.warn("Could not add device {}: {}", taggedItem.getItem().getUID(), e.getMessage()); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCharacteristicType.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCharacteristicType.java index 7a683c35523d1..520e3c0b08381 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCharacteristicType.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCharacteristicType.java @@ -14,9 +14,7 @@ import java.util.HashMap; import java.util.Map; -import java.util.Objects; - -import org.eclipse.smarthome.core.items.Item; +import java.util.Optional; /** * Characteristics are used by complex accessories that can't be represented by @@ -28,15 +26,88 @@ public enum HomekitCharacteristicType { /* * It is illegal to have a characteristic type also be a device type */ - BATTERY_LEVEL("homekit:BatteryLevel"), - TARGET_TEMPERATURE("homekit:TargetTemperature"), + EMPTY("Empty"), // used in case only accessory type but no characteristic provided + NAME("Name"), + BATTERY_LOW_STATUS("BatteryLowStatus"), + ACTIVE_STATUS("ActiveStatus"), + ISCONFIGURED("IsConfigured"), + SERVICELABELIDX("ServiceLabelIndex"), + INUSE_STATUS("InUseStatus"), + FAULT_STATUS("FaultStatus"), + TAMPERED_STATUS("TamperedStatus"), + OBSTRUCTION_STATUS("ObstructionStatus"), + ON_STATE("OnState"), + CONTACT_SENSOR_STATE("ContactSensorState"), + + MOTION_DETECTED_STATE("MotionDetectedState"), + OCCUPANCY_DETECTED_STATE("OccupancyDetectedState"), + SMOKE_DETECTED_STATE("SmokeDetectedState"), + + CARBON_MONOXIDE_DETECTED_STATE("CarbonMonoxideDetectedState"), + CARBON_MONOXIDE_LEVEL("CarbonMonoxideLevel"), + CARBON_MONOXIDE_PEAK_LEVEL("CarbonMonoxidePeakLevel"), + + CARBON_DIOXIDE_DETECTED_STATE("CarbonDioxideDetectedState"), + CARBON_DIOXIDE_LEVEL("CarbonDioxideLevel"), + CARBON_DIOXIDE_PEAK_LEVEL("CarbonDioxidePeakLevel"), + + RELATIVE_HUMIDITY("RelativeHumidity"), + LEAK_DETECTED_STATE("LeakDetectedState"), + HOLD_POSITION("HoldPosition"), + + TARGET_POSITION("TargetPosition"), + CURRENT_POSITION("CurrentPosition"), + POSITION_STATE("PositionState"), + CURRENT_HORIZONTAL_TILT_ANGLE("CurrentHorizontalTiltAngle"), + CURRENT_VERTICAL_TILT_ANGLE("CurrentVerticalTiltAngle"), + TARGET_HORIZONTAL_TILT_ANGLE("TargetHorizontalTiltAngle"), + TARGET_VERTICAL_TILT_ANGLE("TargetVerticalTiltAngle"), + + HUE("Hue"), + BRIGHTNESS("Brightness"), + SATURATION("Saturation"), + COLOR_TEMPERATURE("ColorTemperature"), + + CURRENT_FAN_STATE("CurrentFanState"), + TARGET_FAN_STATE("TargetFanState"), + ROTATION_DIRECTION("RotationDirection"), + ROTATION_SPEED("RotationSpeed"), + SWING_MODE("SwingMode"), + LOCK_CONTROL("LockControl"), + + CURRENT_TEMPERATURE("CurrentTemperature"), + TARGET_HEATING_COOLING_STATE("TargetHeatingCoolingMode"), + CURRENT_HEATING_COOLING_STATE("CurrentHeatingCoolingMode"), + TARGET_TEMPERATURE("TargetTemperature"), + TEMPERATURE_UNIT("TemperatureUnit"), + + LOCK_CURRENT_STATE("LockCurrentState"), + LOCK_TARGET_STATE("LockTargetState"), + + DURATION("Duration"), + REMAINING_DURATION("RemainingDuration"), + + SECURITY_SYSTEM_CURRENT_STATE("CurrentSecuritySystemState"), + SECURITY_SYSTEM_TARGET_STATE("TargetSecuritySystemState"), + + VOLUME("Volume"), + MUTE("Mute"), + + CURRENT_DOOR_STATE("CurrentDoorState"), + TARGET_DOOR_STATE("TargetDoorState"), + + @Deprecated() + OLD_BATTERY_LEVEL("homekit:BatteryLevel"), + @Deprecated() + OLD_BATTERY_LOW_STATUS("homekit:BatteryLowStatus"), + @Deprecated() + VERY_OLD_TARGET_HEATING_COOLING_MODE("homekit:HeatingCoolingMode"), + @Deprecated() + OLD_TARGET_HEATING_COOLING_MODE("homekit:TargetHeatingCoolingMode"), @Deprecated() - OLD_TARGET_TEMPERATURE("TargetTemperature"), - BATTERY_LOW_STATUS("homekit:BatteryLowStatus"), + OLD_CURRENT_HEATING_COOLING_STATE("homekit:CurrentHeatingCoolingMode"), @Deprecated() - OLD_TARGET_HEATING_COOLING_MODE("homekit:HeatingCoolingMode"), - TARGET_HEATING_COOLING_MODE("homekit:TargetHeatingCoolingMode"), - CURRENT_HEATING_COOLING_STATE("homekit:CurrentHeatingCoolingMode"); + OLD_TARGET_TEMPERATURE("homekit:TargetTemperature"); private static final Map TAG_MAP = new HashMap<>(); @@ -62,17 +133,7 @@ public String getTag() { * @param tag the tag string * @return characteristicType or null if not found */ - public static HomekitCharacteristicType valueOfTag(String tag) { - return TAG_MAP.get(tag); - } - - /** - * get characteristicType for a given Item - * - * @param item the item - * @return characteristicType or null if not found - */ - public static HomekitCharacteristicType fromItem(Item item) { - return item.getTags().stream().map(tag -> TAG_MAP.get(tag)).filter(Objects::nonNull).findFirst().orElse(null); + public static Optional valueOfTag(String tag) { + return Optional.ofNullable(TAG_MAP.get(tag)); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCommandExtension.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCommandExtension.java index c9fe4c6ff918e..ee54da0c5a2ca 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCommandExtension.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitCommandExtension.java @@ -14,6 +14,7 @@ import java.util.Arrays; import java.util.List; +import java.util.concurrent.ExecutionException; import org.eclipse.smarthome.core.storage.StorageService; import org.eclipse.smarthome.io.console.Console; @@ -33,7 +34,13 @@ @Component(service = ConsoleCommandExtension.class) public class HomekitCommandExtension extends AbstractConsoleCommandExtension { private static final String SUBCMD_CLEAR_PAIRINGS = "clearPairings"; + private static final String SUBCMD_LIST_ACCESSORIES = "list"; + private static final String SUBCMD_PRINT_ACCESSORY = "show"; private static final String SUBCMD_ALLOW_UNAUTHENTICATED = "allowUnauthenticated"; + @Deprecated + private static final String LEGACY_SUBCMD_LIST_ACCESSORIES = "listAccessories"; + @Deprecated + private static final String LEGACY_SUBCMD_PRINT_ACCESSORY = "printAccessory"; private final Logger logger = LoggerFactory.getLogger(HomekitCommandExtension.class); private StorageService storageService; @@ -60,21 +67,44 @@ public void execute(String[] args, Console console) { console.println("true/false is required as an argument"); } break; - + case SUBCMD_LIST_ACCESSORIES: + case LEGACY_SUBCMD_LIST_ACCESSORIES: + listAccessories(console); + if (subCommand.equalsIgnoreCase(LEGACY_SUBCMD_LIST_ACCESSORIES)) { + console.println(""); + console.println("Hey, you can use the shorter command 'homekit list'"); + } + break; + case SUBCMD_PRINT_ACCESSORY: + case LEGACY_SUBCMD_PRINT_ACCESSORY: + if (args.length > 1) { + printAccessory(args[1], console); + } else { + console.println("accessory id or name is required as an argument"); + } + if (subCommand.equalsIgnoreCase(LEGACY_SUBCMD_PRINT_ACCESSORY)) { + console.println(""); + console.println("Hey, you can use the shorter command 'homekit show '"); + } + break; default: console.println("Unknown command '" + subCommand + "'"); printUsage(console); break; } + } else { + printUsage(console); } } @Override public List getUsages() { - return Arrays.asList( - new String[] { buildCommandUsage(SUBCMD_CLEAR_PAIRINGS, "removes all pairings with HomeKit clients"), - buildCommandUsage(SUBCMD_ALLOW_UNAUTHENTICATED + " ", - "enables or disables unauthenticated access to facilitate debugging") }); + return Arrays.asList(buildCommandUsage(SUBCMD_LIST_ACCESSORIES, "list all HomeKit accessories"), + buildCommandUsage(SUBCMD_PRINT_ACCESSORY + " ", + "print additional details of the accessories which partially match provided ID or name."), + buildCommandUsage(SUBCMD_CLEAR_PAIRINGS, "removes all pairings with HomeKit clients."), + buildCommandUsage(SUBCMD_ALLOW_UNAUTHENTICATED + " ", + "enables or disables unauthenticated access to facilitate debugging")); } @Reference @@ -110,4 +140,35 @@ private void allowUnauthenticatedHomekitRequests(boolean allow, Console console) console.println((allow ? "Enabled " : "Disabled ") + "unauthenticated HomeKit access"); } + private void listAccessories(Console console) { + homekit.getAccessories().stream().forEach(v -> { + try { + console.println(v.getId() + " " + v.getName().get()); + } catch (InterruptedException | ExecutionException e) { + logger.warn("Cannot list accessories", e); + } + }); + } + + private void printAccessory(String id, Console console) { + homekit.getAccessories().forEach(v -> { + try { + if (("" + v.getId()).contains(id) || ((v.getName().get() != null) + && (v.getName().get().toUpperCase().contains(id.toUpperCase())))) { + console.println(v.getId() + " " + v.getName().get()); + console.println("Services:"); + v.getServices().forEach(s -> { + console.println(" Service Type: " + s.getType()); + console.println(" Characteristics: "); + s.getCharacteristics().forEach(c -> { + console.println(" : " + c.getClass()); + }); + }); + console.println(""); + } + } catch (InterruptedException | ExecutionException e) { + logger.warn("Cannot print accessory", e); + } + }); + } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitDeviceType.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitDeviceType.java deleted file mode 100644 index 6d337a10f9b2f..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitDeviceType.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal; - -import java.util.HashMap; -import java.util.Map; - -/** - * Enum of the possible device types. The defined tag string can be used - * as a tag on an item to enable it for Homekit. - * - * @author Andy Lintner - Initial contribution - */ -public enum HomekitDeviceType { - DIMMABLE_LIGHTBULB("DimmableLighting"), - HUMIDITY_SENSOR("CurrentHumidity"), - LIGHTBULB("Lighting"), - SWITCH("Switchable"), - TEMPERATURE_SENSOR("CurrentTemperature"), - THERMOSTAT("Thermostat"), - COLORFUL_LIGHTBULB("ColorfulLighting"), - CONTACT_SENSOR("ContactSensor"); - - private static final Map TAG_MAP = new HashMap<>(); - - static { - for (HomekitDeviceType type : HomekitDeviceType.values()) { - TAG_MAP.put(type.tag, type); - } - } - - private final String tag; - - private HomekitDeviceType(String tag) { - this.tag = tag; - } - - public static HomekitDeviceType valueOfTag(String tag) { - return TAG_MAP.get(tag); - } -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitImpl.java index 5cfdb9b0de041..0c345685c3cab 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitImpl.java @@ -16,13 +16,19 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.security.InvalidAlgorithmParameterException; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.config.core.ConfigurableService; import org.eclipse.smarthome.config.core.Configuration; +import org.eclipse.smarthome.core.common.ThreadPoolManager; import org.eclipse.smarthome.core.items.ItemRegistry; +import org.eclipse.smarthome.core.items.MetadataRegistry; import org.eclipse.smarthome.core.net.NetworkAddressService; import org.eclipse.smarthome.core.storage.StorageService; import org.openhab.io.homekit.Homekit; @@ -36,8 +42,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitRoot; -import io.github.hapjava.HomekitServer; +import io.github.hapjava.accessories.HomekitAccessory; +import io.github.hapjava.server.impl.HomekitRoot; +import io.github.hapjava.server.impl.HomekitServer; /** * Provides access to openHAB items via the HomeKit API @@ -51,6 +58,7 @@ ConfigurableService.SERVICE_PROPERTY_LABEL + "=HomeKit Integration", "port:Integer=9123" }) @NonNullByDefault public class HomekitImpl implements Homekit { + private final Logger logger = LoggerFactory.getLogger(HomekitImpl.class); private final StorageService storageService; private final NetworkAddressService networkAddressService; @@ -61,14 +69,17 @@ public class HomekitImpl implements Homekit { private @Nullable HomekitServer homekitServer; private @Nullable HomekitRoot bridge; + private final ScheduledExecutorService scheduler = ThreadPoolManager + .getScheduledPool(ThreadPoolManager.THREAD_POOL_NAME_COMMON); + @Activate public HomekitImpl(@Reference StorageService storageService, @Reference ItemRegistry itemRegistry, - @Reference NetworkAddressService networkAddressService, Map config) - throws IOException, InvalidAlgorithmParameterException { + @Reference NetworkAddressService networkAddressService, Map config, + @Reference MetadataRegistry metadataRegistry) throws IOException, InvalidAlgorithmParameterException { this.storageService = storageService; this.networkAddressService = networkAddressService; this.settings = processConfig(config); - this.changeListener = new HomekitChangeListener(itemRegistry, settings); + this.changeListener = new HomekitChangeListener(itemRegistry, settings, metadataRegistry, storageService); startHomekitServer(); } @@ -97,7 +108,7 @@ protected synchronized void modified(Map config) { startBridge(); } } catch (IOException | InvalidAlgorithmParameterException e) { - logger.debug("Could not initialize HomeKit connector: {}", e.getMessage()); + logger.warn("Could not initialize HomeKit connector: {}", e.getMessage()); return; } } @@ -112,13 +123,32 @@ private void stopBridge() { } private void startBridge() throws InvalidAlgorithmParameterException, IOException { + final HomekitServer homekitServer = this.homekitServer; if (homekitServer != null && bridge == null) { final HomekitRoot bridge = homekitServer.createBridge(new HomekitAuthInfoImpl(storageService, settings.pin), - settings.name, HomekitSettings.MANUFACTURER, - FrameworkUtil.getBundle(getClass()).getVersion().toString(), HomekitSettings.SERIAL_NUMBER); + settings.name, HomekitSettings.MANUFACTURER, HomekitSettings.MODEL, HomekitSettings.SERIAL_NUMBER, + FrameworkUtil.getBundle(getClass()).getVersion().toString(), HomekitSettings.HARDWARE_REVISION); changeListener.setBridge(bridge); - bridge.start(); this.bridge = bridge; + bridge.setConfigurationIndex(changeListener.getConfigurationRevision()); + + final int lastAccessoryCount = changeListener.getLastAccessoryCount(); + int currentAccessoryCount = changeListener.getAccessories().size(); + if (currentAccessoryCount < lastAccessoryCount) { + logger.debug( + "It looks like not all items were initialized yet. Old configuration had {} accessories, the current one has only {} accessories. Delay HomeKit bridge start for {} seconds.", + lastAccessoryCount, currentAccessoryCount, settings.startDelay); + scheduler.schedule(() -> { + if (currentAccessoryCount < lastAccessoryCount) { + // the number of items is still different, maybe it is desired. + // make new configuration revision. + changeListener.makeNewConfigurationRevision(); + } + bridge.start(); + }, settings.startDelay, TimeUnit.SECONDS); + } else { // start bridge immediately. + bridge.start(); + } } else { logger.warn( "trying to start bridge but HomeKit server is not initialized or bridge is already initialized"); @@ -155,6 +185,7 @@ protected void deactivate() { @Override public void refreshAuthInfo() throws IOException { + final HomekitRoot bridge = this.bridge; if (bridge != null) { bridge.refreshAuthInfo(); } @@ -162,8 +193,14 @@ public void refreshAuthInfo() throws IOException { @Override public void allowUnauthenticatedRequests(boolean allow) { + final HomekitRoot bridge = this.bridge; if (bridge != null) { bridge.allowUnauthenticatedRequests(allow); } } + + @Override + public List getAccessories() { + return new ArrayList(this.changeListener.getAccessories().values()); + } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitSettings.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitSettings.java index 583435aae3c77..a0eddbb580c85 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitSettings.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitSettings.java @@ -18,12 +18,15 @@ * @author Andy Lintner - Initial contribution */ public class HomekitSettings { - public static final String MANUFACTURER = "openHAB"; + public static final String MANUFACTURER = "openHAB Community"; public static final String SERIAL_NUMBER = "none"; + public static final String MODEL = "openHAB"; + public static final String HARDWARE_REVISION = "2.5"; public String name = "openHAB"; public int port = 9123; public String pin = "031-45-154"; + public int startDelay = 30; public boolean useFahrenheitTemperature = false; public double minimumTemperature = -100; public double maximumTemperature = 100; @@ -31,9 +34,16 @@ public class HomekitSettings { public String thermostatTargetModeCool = "CoolOn"; public String thermostatTargetModeAuto = "Auto"; public String thermostatTargetModeOff = "Off"; - public String thermostatCurrentModeHeating = "Heating"; - public String thermostatCurrentModeCooling = "Cooling"; + public String thermostatCurrentModeHeating = "HeatOn"; + public String thermostatCurrentModeCooling = "CoolOn"; public String thermostatCurrentModeOff = "Off"; + public String doorCurrentStateOpen = "OPEN"; + public String doorCurrentStateOpening = "OPENING"; + public String doorCurrentStateClosed = "CLOSED"; + public String doorCurrentStateClosing = "CLOSING"; + public String doorCurrentStateStopped = "STOPPED"; + public String doorTargetStateClosed = "CLOSED"; + public String doorTargetStateOpen = "OPEN"; public String networkInterface; @Deprecated @@ -140,5 +150,4 @@ public boolean equals(Object obj) { } return true; } - } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitTaggedItem.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitTaggedItem.java index 2c93def53cf2f..1d66243ab5a94 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitTaggedItem.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/HomekitTaggedItem.java @@ -12,16 +12,15 @@ */ package org.openhab.io.homekit.internal; -import java.util.List; +import static org.openhab.io.homekit.internal.HomekitAccessoryType.DUMMY; + import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.apache.commons.lang.builder.HashCodeBuilder; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.items.GroupItem; import org.eclipse.smarthome.core.items.Item; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,75 +29,48 @@ * * @author Andy Lintner - Initial contribution */ +@NonNullByDefault public class HomekitTaggedItem { - class BadItemConfigurationException extends Exception { - private static final long serialVersionUID = 2199765638404197193L; - - public BadItemConfigurationException(String reason) { - super(reason); - } - } + private final Logger logger = LoggerFactory.getLogger(HomekitTaggedItem.class); private static final Map CREATED_ACCESSORY_IDS = new ConcurrentHashMap<>(); - /** * The type of HomekitDevice we've decided this was. If the item is question is the member of a group which is a * HomekitDevice, then this is null. */ - private HomekitAccessoryType homekitAccessoryType; - private HomekitCharacteristicType homekitCharacteristicType; private final Item item; - private Logger logger = LoggerFactory.getLogger(HomekitTaggedItem.class); + private final HomekitAccessoryType homekitAccessoryType; + private @Nullable HomekitCharacteristicType homekitCharacteristicType; + private @Nullable Map configuration; + private @Nullable GroupItem parentGroupItem; private final int id; - private GroupItem parentGroupItem; - public HomekitTaggedItem(Item item, ItemRegistry itemRegistry) { + public HomekitTaggedItem(Item item, HomekitAccessoryType homekitAccessoryType, + @Nullable Map configuration) { this.item = item; - - try { - homekitAccessoryType = HomekitAccessoryType.fromItem(item); - homekitCharacteristicType = HomekitCharacteristicType.fromItem(item); - if (homekitAccessoryType != null && homekitCharacteristicType != null) { - throw new BadItemConfigurationException( - "Items cannot be tagged as both a characteristic and an accessory type"); - } - List matchingGroupItems = findMyAccessoryGroups(item, itemRegistry); - - switch (matchingGroupItems.size()) { - case 0: // Does not belong to a accessory group - if (homekitCharacteristicType != null) { - throw new BadItemConfigurationException( - "Item is tagged as a characteristic, but does not belong to a root accessory group"); - } - - parentGroupItem = null; - break; - case 1: // Belongs to exactly one accessory group - if (item instanceof GroupItem) { - throw new BadItemConfigurationException("Nested Accessory Groups are not supported"); - } - - parentGroupItem = matchingGroupItems.get(0); - break; - default: // Belongs to more than one accessory group - throw new BadItemConfigurationException( - "Item belongs to multiple Groups which are tagged as Homekit devices."); - } - } catch (BadItemConfigurationException e) { - logger.warn("Item {} was misconfigured: {}. Excluding item from HomeKit.", item.getName(), e.getMessage()); - homekitAccessoryType = null; - homekitCharacteristicType = null; - parentGroupItem = null; - } - if (homekitAccessoryType != null) { + this.parentGroupItem = null; + this.configuration = configuration; + this.homekitAccessoryType = homekitAccessoryType; + this.homekitCharacteristicType = HomekitCharacteristicType.EMPTY; + if (homekitAccessoryType != DUMMY) { this.id = calculateId(item); } else { this.id = 0; } } - public boolean isTagged() { - return (homekitAccessoryType != null && id != 0) || homekitCharacteristicType != null; + public HomekitTaggedItem(Item item, HomekitAccessoryType homekitAccessoryType, + @Nullable HomekitCharacteristicType homekitCharacteristicType, + @Nullable Map configuration) { + this(item, homekitAccessoryType, configuration); + this.homekitCharacteristicType = homekitCharacteristicType; + } + + public HomekitTaggedItem(Item item, HomekitAccessoryType homekitAccessoryType, + @Nullable HomekitCharacteristicType homekitCharacteristicType, @Nullable GroupItem parentGroup, + @Nullable Map configuration) { + this(item, homekitAccessoryType, homekitCharacteristicType, configuration); + this.parentGroupItem = parentGroup; } public boolean isGroup() { @@ -109,17 +81,21 @@ public HomekitAccessoryType getAccessoryType() { return homekitAccessoryType; } - public HomekitCharacteristicType getCharacteristicType() { + public @Nullable HomekitCharacteristicType getCharacteristicType() { return homekitCharacteristicType; } + public @Nullable Map getConfiguration() { + return configuration; + } + /** * Returns whether or not this item refers to an item that fully specifies a HomeKit accessory. Mutually * exclusive * to isCharacteristic(). Primary devices must belong to a root accessory group. */ public boolean isAccessory() { - return homekitAccessoryType != null; + return homekitAccessoryType != DUMMY; } /** @@ -128,7 +104,7 @@ public boolean isAccessory() { * root deviceGroup. */ public boolean isCharacteristic() { - return homekitCharacteristicType != null; + return homekitCharacteristicType != null && homekitCharacteristicType != HomekitCharacteristicType.EMPTY; } public Item getItem() { @@ -147,7 +123,7 @@ public String getName() { * Returns the RootDevice GroupItem to which this item belongs. * Returns null if not in a group. */ - public GroupItem getRootDeviceGroupItem() { + public @Nullable GroupItem getRootDeviceGroupItem() { return parentGroupItem; } @@ -161,7 +137,8 @@ public boolean isMemberOfAccessoryGroup() { } private int calculateId(Item item) { - int id = new HashCodeBuilder().append(item.getName()).hashCode(); + // magic number 629 is the legacy from apache HashCodeBuilder (17*37) + int id = 629 + item.getName().hashCode(); if (id < 0) { id += Integer.MAX_VALUE; } @@ -181,16 +158,8 @@ private int calculateId(Item item) { return id; } - public static List findMyAccessoryGroups(Item item, ItemRegistry itemRegistry) { - return item.getGroupNames().stream().flatMap(name -> { - Item groupItem = itemRegistry.get(name); - if ((groupItem != null) && (groupItem instanceof GroupItem)) { - return Stream.of((GroupItem) groupItem); - } else { - return Stream.empty(); - } - }).filter(groupItem -> { - return groupItem.getTags().stream().filter(gt -> HomekitAccessoryType.valueOfTag(gt) != null).count() > 0; - }).collect(Collectors.toList()); + public String toString() { + return "Item:" + item + " HomeKit type:" + homekitAccessoryType + " HomeKit characteristic:" + + homekitCharacteristicType; } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java index 705f78e2df98b..00d1be3791977 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitAccessoryImpl.java @@ -12,75 +12,91 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.math.BigDecimal; +import java.math.RoundingMode; + +import javax.measure.Quantity; +import javax.measure.Unit; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.GroupItem; import org.eclipse.smarthome.core.items.Item; -import org.eclipse.smarthome.core.items.ItemRegistry; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.library.unit.SIUnits; +import org.eclipse.smarthome.core.library.unit.ImperialUnits; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitAccessory; +import io.github.hapjava.accessories.HomekitAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.Service; /** - * Abstract class for HomekitAccessory implementations, this provides the + * Abstract class for Homekit Accessory implementations, this provides the * accessory metadata using information from the underlying Item. * * @author Andy Lintner - Initial contribution */ -abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory { - - private final int accessoryId; - private final String itemName; - private final String itemLabel; - private final ItemRegistry itemRegistry; +abstract class AbstractHomekitAccessoryImpl implements HomekitAccessory { + private final Logger logger = LoggerFactory.getLogger(AbstractHomekitAccessoryImpl.class); + private final List characteristics; + private final HomekitTaggedItem accessory; private final HomekitAccessoryUpdater updater; + private final HomekitSettings settings; + private final List services; - protected Logger logger = LoggerFactory.getLogger(AbstractHomekitAccessoryImpl.class); - - @SuppressWarnings("null") - public AbstractHomekitAccessoryImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, Class expectedItemClass) { - this.accessoryId = taggedItem.getId(); - this.itemName = taggedItem.getItem().getName(); - this.itemLabel = taggedItem.getItem().getLabel(); - this.itemRegistry = itemRegistry; + public AbstractHomekitAccessoryImpl(HomekitTaggedItem accessory, List characteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + this.characteristics = characteristics; + this.accessory = accessory; this.updater = updater; - Item baseItem = taggedItem.getItem(); - if (baseItem instanceof GroupItem && ((GroupItem) baseItem).getBaseItem() != null) { - baseItem = ((GroupItem) baseItem).getBaseItem(); - } - if (expectedItemClass != taggedItem.getItem().getClass() - && !expectedItemClass.isAssignableFrom(baseItem.getClass())) { - logger.warn("Item {} is of type {} instead of the expected {}", taggedItem.getItem().getName(), - baseItem.getClass().getName(), expectedItemClass.getName()); - } + this.services = new ArrayList<>(); + this.settings = settings; + } + + protected Optional getCharacteristic(HomekitCharacteristicType type) { + return characteristics.stream().filter(c -> c.getCharacteristicType() == type).findAny(); } @Override public int getId() { - return accessoryId; + return accessory.getId(); + } + + @Override + public CompletableFuture getName() { + return CompletableFuture.completedFuture(accessory.getItem().getLabel()); } @Override - public String getLabel() { - return itemLabel; + public CompletableFuture getManufacturer() { + return CompletableFuture.completedFuture("none"); } @Override - public String getManufacturer() { - return "none"; + public CompletableFuture getModel() { + return CompletableFuture.completedFuture("none"); } @Override - public String getModel() { - return "none"; + public CompletableFuture getSerialNumber() { + return CompletableFuture.completedFuture("none"); } @Override - public String getSerialNumber() { - return "none"; + public CompletableFuture getFirmwareRevision() { + return CompletableFuture.completedFuture("none"); } @Override @@ -88,19 +104,97 @@ public void identify() { // We're not going to support this for now } - protected ItemRegistry getItemRegistry() { - return itemRegistry; + public HomekitTaggedItem getRootAccessory() { + return accessory; } - protected String getItemName() { - return itemName; + public Collection getServices() { + return this.services; } protected HomekitAccessoryUpdater getUpdater() { return updater; } - protected GenericItem getItem() { - return (GenericItem) getItemRegistry().get(getItemName()); + protected HomekitSettings getSettings() { + return settings; + } + + protected void subscribe(HomekitCharacteristicType characteristicType, + HomekitCharacteristicChangeCallback callback) { + final Optional characteristic = getCharacteristic(characteristicType); + if (characteristic.isPresent()) { + getUpdater().subscribe((GenericItem) characteristic.get().getItem(), characteristicType.getTag(), callback); + } else { + logger.warn("Missing mandatory characteristic {}", characteristicType); + } + } + + protected void unsubscribe(HomekitCharacteristicType characteristicType) { + final Optional characteristic = getCharacteristic(characteristicType); + if (characteristic.isPresent()) { + getUpdater().unsubscribe((GenericItem) characteristic.get().getItem(), characteristicType.getTag()); + } else { + logger.warn("Missing mandatory characteristic {}", characteristicType); + } + } + + protected @Nullable T getStateAs(HomekitCharacteristicType characteristic, Class type) { + final Optional taggedItem = getCharacteristic(characteristic); + if (taggedItem.isPresent()) { + final State state = taggedItem.get().getItem().getStateAs(type); + if (state != null) { + return (T) state.as(type); + } + } + logger.warn("State for characteristic {} at accessory {} cannot be retrieved.", characteristic, + accessory.getId()); + return null; + } + + @SuppressWarnings("unchecked") + protected @Nullable T getItem(HomekitCharacteristicType characteristic, Class type) { + final Optional taggedItem = getCharacteristic(characteristic); + if (taggedItem.isPresent()) { + if (type.isInstance(taggedItem.get().getItem())) + return (T) taggedItem.get().getItem(); + else + logger.warn("Unsupported item type for characteristic {} at accessory {}. Expected {}, got {}", + characteristic, accessory.getItem().getLabel(), type, taggedItem.get().getItem().getClass()); + } else { + logger.warn("Mandatory characteristic {} not found at accessory {}. ", characteristic, + accessory.getItem().getLabel()); + + } + return null; + } + + @SuppressWarnings("unchecked") + protected T getAccessoryConfiguration(String key, @NonNull T defaultValue) { + final @Nullable Map configuration = accessory.getConfiguration(); + if (configuration != null) { + Object value = configuration.get(key); + if (value != null && value.getClass().equals(defaultValue.getClass())) { + return (T) value; + } + } + return defaultValue; + } + + protected void addCharacteristic(HomekitTaggedItem characteristic) { + characteristics.add(characteristic); + } + + private > double convertAndRound(double value, Unit from, Unit to) { + double rawValue = from == to ? value : from.getConverterTo(to).convert(value); + return new BigDecimal(rawValue).setScale(1, RoundingMode.HALF_UP).doubleValue(); + } + + protected double convertToCelsius(double degrees){ + return convertAndRound(degrees, getSettings().useFahrenheitTemperature ? ImperialUnits.FAHRENHEIT : SIUnits.CELSIUS, SIUnits.CELSIUS); + } + + protected double convertFromCelsius(double degrees){ + return convertAndRound(degrees, getSettings().useFahrenheitTemperature ? SIUnits.CELSIUS : ImperialUnits.FAHRENHEIT, ImperialUnits.FAHRENHEIT); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitLightbulbImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitLightbulbImpl.java deleted file mode 100644 index e6cd8958699ad..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractHomekitLightbulbImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.accessories; - -import java.util.concurrent.CompletableFuture; - -import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.GroupItem; -import org.eclipse.smarthome.core.items.ItemRegistry; -import org.eclipse.smarthome.core.library.items.SwitchItem; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; -import org.openhab.io.homekit.internal.HomekitTaggedItem; - -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.Lightbulb; - -/** - * Abstract class implementing a HomeKit Lightbulb using a SwitchItem - * - * @author Andy Lintner - Initial contribution - */ -abstract class AbstractHomekitLightbulbImpl extends AbstractHomekitAccessoryImpl - implements Lightbulb { - - public AbstractHomekitLightbulbImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, Class expectedItemClass) { - super(taggedItem, itemRegistry, updater, expectedItemClass); - } - - @Override - public CompletableFuture getLightbulbPowerState() { - OnOffType state = getItem().getStateAs(OnOffType.class); - return CompletableFuture.completedFuture(state == OnOffType.ON); - } - - @Override - public CompletableFuture setLightbulbPowerState(boolean value) throws Exception { - GenericItem item = getItem(); - if (item instanceof SwitchItem) { - ((SwitchItem) item).send(value ? OnOffType.ON : OnOffType.OFF); - } else if (item instanceof GroupItem) { - ((GroupItem) item).send(value ? OnOffType.ON : OnOffType.OFF); - } - return CompletableFuture.completedFuture(null); - } - - @Override - public void subscribeLightbulbPowerState(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); - } - - @Override - public void unsubscribeLightbulbPowerState() { - getUpdater().unsubscribe(getItem()); - } - -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractTemperatureHomekitAccessoryImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractTemperatureHomekitAccessoryImpl.java deleted file mode 100644 index 32d667e095e96..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/AbstractTemperatureHomekitAccessoryImpl.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.accessories; - -import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.ItemRegistry; -import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; -import org.openhab.io.homekit.internal.HomekitSettings; -import org.openhab.io.homekit.internal.HomekitTaggedItem; - -import io.github.hapjava.accessories.TemperatureSensor; -import io.github.hapjava.accessories.properties.TemperatureUnit; - -/** - * - * @author Andy Lintner - Initial contribution - */ -abstract class AbstractTemperatureHomekitAccessoryImpl extends AbstractHomekitAccessoryImpl - implements TemperatureSensor { - - private final HomekitSettings settings; - - public AbstractTemperatureHomekitAccessoryImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, HomekitSettings settings, Class expectedItemClass) { - super(taggedItem, itemRegistry, updater, expectedItemClass); - this.settings = settings; - } - - @Override - public TemperatureUnit getTemperatureUnit() { - return settings.useFahrenheitTemperature ? TemperatureUnit.FAHRENHEIT : TemperatureUnit.CELSIUS; - } - - @Override - public double getMaximumTemperature() { - return settings.maximumTemperature; - } - - @Override - public double getMinimumTemperature() { - return settings.minimumTemperature; - } - - protected double convertToCelsius(double degrees) { - if (settings.useFahrenheitTemperature) { - return Math.round((5d / 9d) * (degrees - 32d) * 1000d) / 1000d; - } else { - return degrees; - } - } - - protected double convertFromCelsius(double degrees) { - if (settings.useFahrenheitTemperature) { - return Math.round((((9d / 5d) * degrees) + 32d) * 10d) / 10d; - } else { - return degrees; - } - } -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/BooleanItemReader.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/BooleanItemReader.java index 7a1edae5928fd..3c64b7b832659 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/BooleanItemReader.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/BooleanItemReader.java @@ -12,17 +12,20 @@ */ package org.openhab.io.homekit.internal.accessories; +import org.eclipse.smarthome.core.items.GroupItem; import org.eclipse.smarthome.core.items.Item; import org.eclipse.smarthome.core.library.items.ContactItem; +import org.eclipse.smarthome.core.library.items.StringItem; import org.eclipse.smarthome.core.library.items.SwitchItem; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.StringType; import org.eclipse.smarthome.core.types.State; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Wraps either a SwitchItem or a ContactItem, interpretting the open / closed states accordingly. + * Wraps either a SwitchItem or a ContactItem, interpreting the open / closed states accordingly. * * @author Tim Harper - Initial contribution * @@ -44,8 +47,8 @@ public class BooleanItemReader { this.item = item; this.trueOnOffValue = trueOnOffValue; this.trueOpenClosedValue = trueOpenClosedValue; - if (!(item instanceof SwitchItem) && !(item instanceof ContactItem)) { - logger.warn("Item {} is a {} instead of the expected SwitchItem or ContactItem", item.getName(), + if (!(item instanceof SwitchItem) && !(item instanceof ContactItem) && !(item instanceof StringItem)) { + logger.warn("Item {} is a {} instead of the expected SwitchItem, ContactItem or StringItem", item.getName(), item.getClass().getName()); } } @@ -56,8 +59,18 @@ Boolean getValue() { return state.equals(trueOnOffValue); } else if (state instanceof OpenClosedType) { return state.equals(trueOpenClosedValue); + } else if (state instanceof StringType) { + return state.toString().equalsIgnoreCase("Open") || state.toString().equalsIgnoreCase("Opened"); } else { return null; } } + + void setValue(Boolean value) { + if (item instanceof SwitchItem) { + ((SwitchItem) item).send(OnOffType.from(value)); + } else if (item instanceof GroupItem) { + ((GroupItem) item).send(OnOffType.from(value)); + } + } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/GroupedAccessory.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/GroupedAccessory.java deleted file mode 100644 index 27f2ed7fa67ae..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/GroupedAccessory.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.accessories; - -import org.openhab.io.homekit.internal.HomekitTaggedItem; - -import io.github.hapjava.HomekitAccessory; - -/** - * An accessory that is too complex to be represented by a single item. A - * grouped accessory is made up of multiple items, each implementing a single - * characteristic of the accessory. - * - * @author Andy Lintner - Initial contribution - */ -public interface GroupedAccessory extends HomekitAccessory { - - public String getGroupName(); - - public void addCharacteristic(HomekitTaggedItem item); - - public boolean isComplete(); -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitAccessoryFactory.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitAccessoryFactory.java index 99bbf18eb7ac7..929b9ffa81ed7 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitAccessoryFactory.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitAccessoryFactory.java @@ -12,156 +12,421 @@ */ package org.openhab.io.homekit.internal.accessories; +import static org.openhab.io.homekit.internal.HomekitAccessoryType.*; +import static org.openhab.io.homekit.internal.HomekitCharacteristicType.*; + +import java.lang.reflect.InvocationTargetException; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.items.GenericItem; import org.eclipse.smarthome.core.items.GroupItem; import org.eclipse.smarthome.core.items.Item; import org.eclipse.smarthome.core.items.ItemRegistry; +import org.eclipse.smarthome.core.items.Metadata; +import org.eclipse.smarthome.core.items.MetadataKey; +import org.eclipse.smarthome.core.items.MetadataRegistry; +import org.eclipse.smarthome.core.library.items.ColorItem; +import org.eclipse.smarthome.core.library.items.DimmerItem; import org.openhab.io.homekit.internal.HomekitAccessoryType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; import org.openhab.io.homekit.internal.HomekitCharacteristicType; import org.openhab.io.homekit.internal.HomekitException; import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import org.openhab.io.homekit.internal.battery.BatteryStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitAccessory; +import io.github.hapjava.accessories.HomekitAccessory; +import io.github.hapjava.characteristics.Characteristic; +import io.github.hapjava.services.Service; /** * Creates a HomekitAccessory for a given HomekitTaggedItem. * * @author Andy Lintner - Initial contribution + * @author Eugen Freiter - refactoring for optional characteristics */ +@NonNullByDefault +@SuppressWarnings("deprecation") public class HomekitAccessoryFactory { - private static final Logger LOGGER = LoggerFactory.getLogger(HomekitAccessoryFactory.class); - - @SuppressWarnings("deprecation") - public static HomekitAccessory create(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, HomekitSettings settings) - throws HomekitException, IncompleteAccessoryException { - LOGGER.debug("Constructing {} of accessoryType {}", taggedItem.getName(), taggedItem.getAccessoryType()); - - Map characteristicItems = getCharacteristicItems(taggedItem); - - switch (taggedItem.getAccessoryType()) { - case LEAK_SENSOR: - HomekitTaggedItem leakSensorAccessory = getPrimaryAccessory(taggedItem, - HomekitAccessoryType.LEAK_SENSOR, itemRegistry).orElseThrow( - () -> new HomekitException("Leak accessory group should have a leak sensor in it")); - - return new HomekitLeakSensorImpl(leakSensorAccessory, itemRegistry, updater, - BatteryStatus.getFromCharacteristics(characteristicItems)); - case VALVE: - return new HomekitValveImpl(taggedItem, itemRegistry, updater); - case MOTION_SENSOR: - HomekitTaggedItem motionSensorAccessory = getPrimaryAccessory(taggedItem, - HomekitAccessoryType.MOTION_SENSOR, itemRegistry) - .orElseThrow(() -> new HomekitException( - "Motion sensor accessory group should have a motion sensor item in it")); - return new HomekitMotionSensorImpl(motionSensorAccessory, itemRegistry, updater, - BatteryStatus.getFromCharacteristics(characteristicItems)); - case OCCUPANCY_SENSOR: - HomekitTaggedItem occupancySensorAccessory = getPrimaryAccessory(taggedItem, - HomekitAccessoryType.OCCUPANCY_SENSOR, itemRegistry) - .orElseThrow(() -> new HomekitException( - "Occupancy sensor accessory group should have a occupancy sensor item in it")); - return new HomekitOccupancySensorImpl(occupancySensorAccessory, itemRegistry, updater, - BatteryStatus.getFromCharacteristics(characteristicItems)); - case CONTACT_SENSOR: - HomekitTaggedItem contactSensorAccessory = getPrimaryAccessory(taggedItem, - HomekitAccessoryType.CONTACT_SENSOR, itemRegistry) - .orElseThrow(() -> new HomekitException( - "Contact sensor accessory group should have a occupancy sensor item in it")); - return new HomekitContactSensorImpl(contactSensorAccessory, itemRegistry, updater, - BatteryStatus.getFromCharacteristics(characteristicItems)); - case LIGHTBULB: - return new HomekitLightbulbImpl(taggedItem, itemRegistry, updater); - case DIMMABLE_LIGHTBULB: - return new HomekitDimmableLightbulbImpl(taggedItem, itemRegistry, updater); - case COLORFUL_LIGHTBULB: - return new HomekitColorfulLightbulbImpl(taggedItem, itemRegistry, updater); - case THERMOSTAT: - HomekitTaggedItem temperatureAccessory = getPrimaryAccessory(taggedItem, - HomekitAccessoryType.TEMPERATURE_SENSOR, itemRegistry).orElseThrow( - () -> new HomekitException("Thermostats need a CurrentTemperature accessory")); - return new HomekitThermostatImpl(taggedItem, itemRegistry, updater, settings, - temperatureAccessory.getItem(), getCharacteristicItems(taggedItem)); - case SWITCH: - return new HomekitSwitchImpl(taggedItem, itemRegistry, updater); - case TEMPERATURE_SENSOR: - return new HomekitTemperatureSensorImpl(taggedItem, itemRegistry, updater, settings); - case HUMIDITY_SENSOR: - return new HomekitHumiditySensorImpl(taggedItem, itemRegistry, updater); - case BLINDS: - case WINDOW_COVERING: - return new HomekitWindowCoveringImpl(taggedItem, itemRegistry, updater); - case SMOKE_SENSOR: - HomekitTaggedItem smokeSensorAccessory = getPrimaryAccessory(taggedItem, - HomekitAccessoryType.SMOKE_SENSOR, itemRegistry).orElseThrow( - () -> new HomekitException("Smoke accessory group should have a smoke sensor in it")); - return new HomekitSmokeSensorImpl(smokeSensorAccessory, itemRegistry, updater, - BatteryStatus.getFromCharacteristics(characteristicItems)); - case CARBON_MONOXIDE_SENSOR: - HomekitTaggedItem carbonMonoxideSensorAccessory = getPrimaryAccessory(taggedItem, - HomekitAccessoryType.CARBON_MONOXIDE_SENSOR, itemRegistry) - .orElseThrow(() -> new HomekitException( - "Carbon monoxide accessory group should have a carbon monoxide sensor in it")); - return new HomekitSmokeSensorImpl(carbonMonoxideSensorAccessory, itemRegistry, updater, - BatteryStatus.getFromCharacteristics(characteristicItems)); - case LOCK: - return new HomekitLockImpl(taggedItem, itemRegistry, updater); + private static final Logger logger = LoggerFactory.getLogger(HomekitAccessoryFactory.class); + public final static String METADATA_KEY = "homekit"; // prefix for HomeKit meta information in items.xml + + /** List of mandatory attributes for each accessory type. **/ + private final static Map MANDATORY_CHARACTERISTICS = new HashMap() { + { + put(LEAK_SENSOR, new HomekitCharacteristicType[] { LEAK_DETECTED_STATE }); + put(MOTION_SENSOR, new HomekitCharacteristicType[] { MOTION_DETECTED_STATE }); + put(OCCUPANCY_SENSOR, new HomekitCharacteristicType[] { OCCUPANCY_DETECTED_STATE }); + put(CONTACT_SENSOR, new HomekitCharacteristicType[] { CONTACT_SENSOR_STATE }); + put(SMOKE_SENSOR, new HomekitCharacteristicType[] { SMOKE_DETECTED_STATE }); + put(HUMIDITY_SENSOR, new HomekitCharacteristicType[] { RELATIVE_HUMIDITY }); + put(SWITCH, new HomekitCharacteristicType[] { ON_STATE }); + put(CARBON_DIOXIDE_SENSOR, new HomekitCharacteristicType[] { CARBON_DIOXIDE_DETECTED_STATE }); + put(CARBON_MONOXIDE_SENSOR, new HomekitCharacteristicType[] { CARBON_MONOXIDE_DETECTED_STATE }); + put(WINDOW_COVERING, new HomekitCharacteristicType[] { TARGET_POSITION, CURRENT_POSITION, POSITION_STATE }); + put(LIGHTBULB, new HomekitCharacteristicType[] { ON_STATE }); + put(FAN, new HomekitCharacteristicType[] { ACTIVE_STATUS }); + put(TEMPERATURE_SENSOR, new HomekitCharacteristicType[] { CURRENT_TEMPERATURE }); + put(THERMOSTAT, new HomekitCharacteristicType[] { CURRENT_HEATING_COOLING_STATE, + TARGET_HEATING_COOLING_STATE, CURRENT_TEMPERATURE, TARGET_TEMPERATURE }); + put(LOCK, new HomekitCharacteristicType[] { LOCK_CURRENT_STATE, LOCK_TARGET_STATE }); + put(VALVE, new HomekitCharacteristicType[] { ACTIVE_STATUS, INUSE_STATUS }); + put(SECURITY_SYSTEM, + new HomekitCharacteristicType[] { SECURITY_SYSTEM_CURRENT_STATE, SECURITY_SYSTEM_TARGET_STATE }); + put(OUTLET, new HomekitCharacteristicType[] { ON_STATE, INUSE_STATUS }); + put(SPEAKER, new HomekitCharacteristicType[] { MUTE }); + put(GARAGE_DOOR_OPENER, + new HomekitCharacteristicType[] { CURRENT_DOOR_STATE, TARGET_DOOR_STATE, OBSTRUCTION_STATUS }); + + // LEGACY + put(BLINDS, new HomekitCharacteristicType[] { TARGET_POSITION, CURRENT_POSITION, POSITION_STATE }); + put(OLD_HUMIDITY_SENSOR, new HomekitCharacteristicType[] { RELATIVE_HUMIDITY }); + put(OLD_DIMMABLE_LIGHTBULB, new HomekitCharacteristicType[] { ON_STATE }); + put(OLD_COLORFUL_LIGHTBULB, new HomekitCharacteristicType[] { ON_STATE }); + } + }; + + /** List of service implementation for each accessory type. **/ + private final static Map> SERVICE_IMPL_MAP = new HashMap>() { + { + put(LEAK_SENSOR, HomekitLeakSensorImpl.class); + put(MOTION_SENSOR, HomekitMotionSensorImpl.class); + put(OCCUPANCY_SENSOR, HomekitOccupancySensorImpl.class); + put(CONTACT_SENSOR, HomekitContactSensorImpl.class); + put(SMOKE_SENSOR, HomekitSmokeSensorImpl.class); + put(HUMIDITY_SENSOR, HomekitHumiditySensorImpl.class); + put(SWITCH, HomekitSwitchImpl.class); + put(CARBON_DIOXIDE_SENSOR, HomekitCarbonDioxideSensorImpl.class); + put(CARBON_MONOXIDE_SENSOR, HomekitCarbonMonoxideSensorImpl.class); + put(WINDOW_COVERING, HomekitWindowCoveringImpl.class); + put(LIGHTBULB, HomekitLightbulbImpl.class); + put(FAN, HomekitFanImpl.class); + put(TEMPERATURE_SENSOR, HomekitTemperatureSensorImpl.class); + put(THERMOSTAT, HomekitThermostatImpl.class); + put(LOCK, HomekitLockImpl.class); + put(VALVE, HomekitValveImpl.class); + put(SECURITY_SYSTEM, HomekitSecuritySystemImpl.class); + put(OUTLET, HomekitOutletImpl.class); + put(SPEAKER, HomekitSpeakerImpl.class); + put(GARAGE_DOOR_OPENER, HomekitGarageDoorOpenerImpl.class); + put(BLINDS, HomekitWindowCoveringImpl.class); + put(OLD_HUMIDITY_SENSOR, HomekitHumiditySensorImpl.class); + put(OLD_DIMMABLE_LIGHTBULB, HomekitLightbulbImpl.class); + put(OLD_COLORFUL_LIGHTBULB, HomekitLightbulbImpl.class); + } + }; + + /** mapping of legacy attributes to new attributes. **/ + private final static Map LEGACY_CHARACTERISTICS_MAPPING = new HashMap() { + { + put(OLD_CURRENT_HEATING_COOLING_STATE, CURRENT_HEATING_COOLING_STATE); + put(OLD_TARGET_HEATING_COOLING_MODE, TARGET_HEATING_COOLING_STATE); + put(OLD_TARGET_TEMPERATURE, TARGET_TEMPERATURE); + put(OLD_BATTERY_LOW_STATUS, BATTERY_LOW_STATUS); + put(VERY_OLD_TARGET_HEATING_COOLING_MODE, CURRENT_HEATING_COOLING_STATE); } + }; + + /** list of optional implicit optional characteristics. mainly used for legacy accessory type */ + private final static Map IMPLICIT_OPTIONAL_CHARACTERISTICS = new HashMap() { + { + put(OLD_DIMMABLE_LIGHTBULB, new HomekitCharacteristicType[] { BRIGHTNESS }); + put(OLD_COLORFUL_LIGHTBULB, new HomekitCharacteristicType[] { HUE, SATURATION, BRIGHTNESS }); - throw new HomekitException("Unknown HomeKit type: " + taggedItem.getAccessoryType()); + } + }; + + /** + * creates HomeKit accessory for a openhab item. + * + * @param taggedItem openhab item tagged as HomeKit item + * @param metadataRegistry openhab metadata registry required to get item meta information + * @param updater OH HomeKit update class that ensure the status sync between OH item and corresponding HomeKit + * characteristic. + * @param settings OH settings + * @return HomeKit accessory + * @throws HomekitException exception in case HomeKit accessory could not be created, e.g. due missing mandatory + * characteristic + */ + @SuppressWarnings("null") + public static HomekitAccessory create(HomekitTaggedItem taggedItem, MetadataRegistry metadataRegistry, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws HomekitException { + final HomekitAccessoryType accessoryType = taggedItem.getAccessoryType(); + logger.trace("Constructing {} of accessoryType {}", taggedItem.getName(), accessoryType); + final List requiredCharacteristics = getMandatoryCharacteristics(taggedItem, + metadataRegistry); + final HomekitCharacteristicType[] mandatoryCharacteristics = MANDATORY_CHARACTERISTICS.get(accessoryType); + if ((mandatoryCharacteristics != null) && (requiredCharacteristics.size() < mandatoryCharacteristics.length)) { + logger.warn("Accessory of type {} must have following characteristics {}. Found only {}", accessoryType, + mandatoryCharacteristics, requiredCharacteristics); + throw new HomekitException("Missing mandatory characteristics"); + } + AbstractHomekitAccessoryImpl accessoryImpl; + + try { + @Nullable + final Class accessoryImplClass = SERVICE_IMPL_MAP + .get(accessoryType); + if (accessoryImplClass != null) { + accessoryImpl = accessoryImplClass + .getConstructor(HomekitTaggedItem.class, List.class, HomekitAccessoryUpdater.class, + HomekitSettings.class) + .newInstance(taggedItem, requiredCharacteristics, updater, settings); + addOptionalCharacteristics(accessoryImpl, metadataRegistry); + return accessoryImpl; + } else { + logger.warn("Unsupported HomeKit type: {}", accessoryType); + throw new HomekitException("Unsupported HomeKit type: " + accessoryType); + } + } catch (NoSuchMethodException | IllegalAccessException | InstantiationException + | InvocationTargetException e) { + logger.warn("Cannot instantiate accessory implementation for accessory {}", accessoryType, e); + throw new HomekitException("Cannot instantiate accessory implementation for accessory " + accessoryType); + } + } + + /** + * return HomeKit accessory types for a OH item based on meta data + * + * @param item OH item + * @param metadataRegistry meta data registry + * @return list of HomeKit accessory types and characteristics. + */ + public static List> getAccessoryTypes(Item item, + MetadataRegistry metadataRegistry) { + final List> accessories = new ArrayList<>(); + Metadata metadata = metadataRegistry.get(new MetadataKey(METADATA_KEY, item.getUID())); + boolean legacyMode = metadata == null; + String[] tags = !legacyMode ? metadata.getValue().split(",") : item.getTags().toArray(new String[0]); // fallback + + logger.trace("item {} meta data {} tags {} ", item.getName(), metadata, tags); + for (String tag : tags) { + final String[] meta = tag.split("\\."); + Optional accessoryType = HomekitAccessoryType.valueOfTag(meta[0].trim()); + if (accessoryType.isPresent()) { // it accessory, check for characteristic + HomekitAccessoryType type = accessoryType.get(); + if ((legacyMode) && (type.equals(LIGHTBULB))) { // support old smart logic to convert Lighting to + // DimmableLighting or ColorfulLighting depending on + // item type + if (item instanceof ColorItem) { + type = OLD_COLORFUL_LIGHTBULB; + } else if (item instanceof DimmerItem) { + type = OLD_DIMMABLE_LIGHTBULB; + } + } + if (meta.length > 1) { + // it has characteristic as well + accessories.add(new SimpleEntry<>(type, + HomekitCharacteristicType.valueOfTag(meta[1].trim()).orElse(EMPTY))); + } else {// it has no characteristic + accessories.add(new SimpleEntry<>(type, EMPTY)); + } + } else { // it is no accessory, so, maybe it is a characteristic + HomekitCharacteristicType.valueOfTag(meta[0].trim()) + .ifPresent(c -> accessories.add(new SimpleEntry<>(DUMMY, c))); + } + } + return accessories; + } + + public static @Nullable Map getItemConfiguration(Item item, MetadataRegistry metadataRegistry) { + Metadata metadata = metadataRegistry.get(new MetadataKey(METADATA_KEY, item.getUID())); + return metadata != null ? metadata.getConfiguration() : null; + } + + /** + * return list of HomeKit relevant groups linked to an accessory + * + * @param item OH item + * @param itemRegistry item registry + * @param metadataRegistry metadata registry + * @return list of relevant group items + */ + public static List getAccessoryGroups(Item item, ItemRegistry itemRegistry, + MetadataRegistry metadataRegistry) { + return item.getGroupNames().stream().flatMap(name -> { + Item groupItem = itemRegistry.get(name); + if (groupItem instanceof GroupItem) { + return Stream.of((GroupItem) groupItem); + } else { + return Stream.empty(); + } + }).filter(groupItem -> !getAccessoryTypes(groupItem, metadataRegistry).isEmpty()).collect(Collectors.toList()); } /** - * Given an accessory group, return the item in the group tagged as an accessory. - * - * @param taggedItem The group item containing our item, or, the accessory item. - * @param accessoryType The accessory type for which we're looking - * @return + * collect all mandatory characteristics for a given tagged item, e.g. collect all mandatory HomeKit items from a + * GroupItem + * + * @param taggedItem HomeKit tagged item + * @param metadataRegistry meta data registry + * @return list of mandatory */ - private static Optional getPrimaryAccessory(HomekitTaggedItem taggedItem, - HomekitAccessoryType accessoryType, ItemRegistry itemRegistry) { - LOGGER.debug("{}: isGroup? {}, isMember? {}", taggedItem.getName(), taggedItem.isGroup(), - taggedItem.isMemberOfAccessoryGroup()); + private static List getMandatoryCharacteristics(HomekitTaggedItem taggedItem, + MetadataRegistry metadataRegistry) { + logger.trace("get mandatory characteristics for item {}: isGroup? {}, isMember? {}", taggedItem.getName(), + taggedItem.isGroup(), taggedItem.isMemberOfAccessoryGroup()); + List collectedCharacteristics = new ArrayList<>(); if (taggedItem.isGroup()) { - GroupItem groupItem = (GroupItem) taggedItem.getItem(); - return groupItem.getMembers().stream().filter(item -> item.hasTag(accessoryType.getTag())).findFirst() - .map(item -> new HomekitTaggedItem(item, itemRegistry)); - } else if (taggedItem.getAccessoryType() == accessoryType) { - return Optional.of(taggedItem); + for (Item item : ((GroupItem) taggedItem.getItem()).getAllMembers()) { + addMandatoryCharacteristics(taggedItem, collectedCharacteristics, item, metadataRegistry); + } } else { - return Optional.empty(); + addMandatoryCharacteristics(taggedItem, collectedCharacteristics, taggedItem.getItem(), metadataRegistry); + } + return collectedCharacteristics; + } + + /** + * add mandatory HomeKit items for a given main item to a list of characteristics + * + * @param mainItem main item + * @param characteristics list of characteristics + * @param item current item + * @param metadataRegistry meta date registry + */ + @SuppressWarnings("null") + private static void addMandatoryCharacteristics(HomekitTaggedItem mainItem, List characteristics, + Item item, MetadataRegistry metadataRegistry) { + HomekitCharacteristicType[] mandatoryCharacteristics = MANDATORY_CHARACTERISTICS + .get(mainItem.getAccessoryType()); + for (Entry accessory : getAccessoryTypes(item, + metadataRegistry)) { + if (isRootAccessory(accessory) && (mandatoryCharacteristics != null)) { + Arrays.stream(mandatoryCharacteristics) + .forEach(c -> characteristics.add(new HomekitTaggedItem(item, accessory.getKey(), c, + mainItem.isGroup() ? (GroupItem) mainItem.getItem() : null, + HomekitAccessoryFactory.getItemConfiguration(item, metadataRegistry)))); + } else { + if (isMandatoryCharacteristic(mainItem.getAccessoryType(), legacyCheck(accessory.getValue()))) + characteristics + .add(new HomekitTaggedItem(item, accessory.getKey(), legacyCheck(accessory.getValue()), + mainItem.isGroup() ? (GroupItem) mainItem.getItem() : null, + HomekitAccessoryFactory.getItemConfiguration(item, metadataRegistry))); + } } } - private static Map getCharacteristicItems(HomekitTaggedItem taggedItem) { + /** + * add optional characteristic for given accessory. + * + * @param accessory accessory + * @param metadataRegistry metadata registry + */ + private static void addOptionalCharacteristics(AbstractHomekitAccessoryImpl accessory, + MetadataRegistry metadataRegistry) { + Map characteristics = getOptionalCharacteristics( + accessory.getRootAccessory(), metadataRegistry); + Service service = accessory.getPrimaryService(); + + characteristics.forEach((type, item) -> { + try { + logger.trace("adding optional characteristic: {} for item {}", type, item.getName()); + final HomekitTaggedItem optionalItem = new HomekitTaggedItem(item, + accessory.getRootAccessory().getAccessoryType(), type, + accessory.getRootAccessory().getRootDeviceGroupItem(), + getItemConfiguration(item, metadataRegistry)); + final Characteristic characteristic = HomekitCharacteristicFactory.createCharacteristic(optionalItem, + accessory.getUpdater()); + // find the corresponding add method at service and call it. + service.getClass().getMethod("addOptionalCharacteristic", characteristic.getClass()).invoke(service, + characteristic); + + accessory.addCharacteristic(optionalItem); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | HomekitException e) { + logger.warn("Not supported optional HomeKit characteristic. Service type {}, characteristic type {}", + service.getType(), type, e); + } + }); + } + + /** + * collect optional HomeKit characteristics for a OH item. + * + * @param taggedItem main OH item + * @param metadataRegistry OH metadata registry + * @return a map with characteristics and corresponding OH items + */ + @SuppressWarnings("null") + private static Map getOptionalCharacteristics(HomekitTaggedItem taggedItem, + MetadataRegistry metadataRegistry) { + logger.trace("get optional characteristics for item {}: isGroup? {}, isMember? {}", taggedItem.getName(), + taggedItem.isGroup(), taggedItem.isMemberOfAccessoryGroup()); + Map characteristicItems = new HashMap<>(); if (taggedItem.isGroup()) { GroupItem groupItem = (GroupItem) taggedItem.getItem(); - Map characteristicItems = new HashMap<>(); - groupItem.getMembers().forEach(item -> { - HomekitCharacteristicType type = HomekitCharacteristicType.fromItem(item); - if (type != null) { - if (characteristicItems.containsKey(type)) { - LOGGER.warn("incorrect configuration for {} detected: {} and {} are tagged as {}, skipping {}", - taggedItem.getItem().getUID(), characteristicItems.get(type).getUID(), item.getUID(), - type, item.getUID()); - } else { - characteristicItems.put(type, item); - } - } - }); - return Collections.unmodifiableMap(characteristicItems); + groupItem.getMembers().forEach(item -> getAccessoryTypes(item, metadataRegistry).stream() + .filter(c -> !isRootAccessory(c)) + .filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), legacyCheck(c.getValue()))) + .forEach(characteristic -> characteristicItems.put(legacyCheck(characteristic.getValue()), + (GenericItem) item))); } else { - // do nothing; only accessory groups have characteristic items - return Collections.emptyMap(); + getAccessoryTypes(taggedItem.getItem(), metadataRegistry).stream().filter(c -> !isRootAccessory(c)) + .filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), legacyCheck(c.getValue()))) + .forEach(characteristic -> characteristicItems.put(legacyCheck(characteristic.getValue()), + (GenericItem) taggedItem.getItem())); + final HomekitCharacteristicType[] implicitOptionalCharacteristics = IMPLICIT_OPTIONAL_CHARACTERISTICS + .get(taggedItem.getAccessoryType()); + if (implicitOptionalCharacteristics != null) { + Arrays.stream(implicitOptionalCharacteristics) + .filter(c -> !isMandatoryCharacteristic(taggedItem.getAccessoryType(), c)) + .forEach(characteristic -> characteristicItems.put(legacyCheck(characteristic), + (GenericItem) taggedItem.getItem())); + } } + logger.trace("characteristics for {} = {}", taggedItem.getName(), characteristicItems); + return Collections.unmodifiableMap(characteristicItems); + } + + /** + * return true is characteristic is a mandatory characteristic for the accessory. + * + * @param accessory accessory + * @param characteristic characteristic + * @return true if characteristic is mandatory, false if not mandatory + */ + @SuppressWarnings("null") + private static boolean isMandatoryCharacteristic(HomekitAccessoryType accessory, + HomekitCharacteristicType characteristic) { + return MANDATORY_CHARACTERISTICS.get(accessory) != null + && Arrays.asList(MANDATORY_CHARACTERISTICS.get(accessory)).contains(characteristic); + } + + /** + * check whether accessory is root accessory, i.e. without characteristic tag. + * + * @param accessory accessory + * @return true if accessory has not characteristic. + */ + @SuppressWarnings("null") + private static boolean isRootAccessory(Entry accessory) { + return ((accessory.getValue() == null) || (accessory.getValue() == EMPTY)); + } + + /** + * check whether it is legacy characteristic and return new name in such case. otherwise return the input parameter + * unchangec. + * + * @param characteristicType characteristic to check + * @return new characteristic type + */ + @SuppressWarnings("null") + private static HomekitCharacteristicType legacyCheck(final HomekitCharacteristicType characteristicType) { + if (LEGACY_CHARACTERISTICS_MAPPING.get(characteristicType) != null) + return LEGACY_CHARACTERISTICS_MAPPING.get(characteristicType); + return characteristicType; } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonDioxideSensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonDioxideSensorImpl.java new file mode 100644 index 0000000000000..751612da57cbb --- /dev/null +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonDioxideSensorImpl.java @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.io.homekit.internal.accessories; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.smarthome.core.items.GenericItem; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; +import org.openhab.io.homekit.internal.HomekitTaggedItem; + +import io.github.hapjava.accessories.CarbonDioxideSensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.carbondioxidesensor.CarbonDioxideDetectedEnum; +import io.github.hapjava.services.impl.CarbonDioxideSensorService; + +/** + * + * @author Cody Cutrer - Initial contribution + */ +public class HomekitCarbonDioxideSensorImpl extends AbstractHomekitAccessoryImpl + implements CarbonDioxideSensorAccessory { + + private final BooleanItemReader carbonDioxideDetectedReader; + + public HomekitCarbonDioxideSensorImpl(HomekitTaggedItem taggedItem, + List mandatoryCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings) + throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.carbonDioxideDetectedReader = new BooleanItemReader( + getItem(HomekitCharacteristicType.CARBON_DIOXIDE_DETECTED_STATE, GenericItem.class), OnOffType.ON, + OpenClosedType.OPEN); + getServices().add(new CarbonDioxideSensorService(this)); + } + + @Override + public CompletableFuture getCarbonDioxideDetectedState() { + Boolean state = this.carbonDioxideDetectedReader.getValue(); + if (state == null) { + return CompletableFuture.completedFuture(CarbonDioxideDetectedEnum.NORMAL); + } + return CompletableFuture + .completedFuture(state ? CarbonDioxideDetectedEnum.ABNORMAL : CarbonDioxideDetectedEnum.NORMAL); + } + + @Override + public void subscribeCarbonDioxideDetectedState(HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.CARBON_DIOXIDE_DETECTED_STATE, callback); + } + + @Override + public void unsubscribeCarbonDioxideDetectedState() { + unsubscribe(HomekitCharacteristicType.CARBON_DIOXIDE_DETECTED_STATE); + } +} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonMonoxideSensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonMonoxideSensorImpl.java index 4339383d25da4..e6b75d8f9dc37 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonMonoxideSensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCarbonMonoxideSensorImpl.java @@ -12,75 +12,58 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.OpenClosedType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import org.openhab.io.homekit.internal.battery.BatteryStatus; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.BatteryStatusAccessory; -import io.github.hapjava.accessories.CarbonMonoxideSensor; -import io.github.hapjava.accessories.properties.CarbonMonoxideDetectedState; +import io.github.hapjava.accessories.CarbonMonoxideSensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.carbonmonoxidesensor.CarbonMonoxideDetectedEnum; +import io.github.hapjava.services.impl.CarbonMonoxideSensorService; /** * * @author Cody Cutrer - Initial contribution */ -public class HomekitCarbonMonoxideSensorImpl extends AbstractHomekitAccessoryImpl - implements CarbonMonoxideSensor, BatteryStatusAccessory { +public class HomekitCarbonMonoxideSensorImpl extends AbstractHomekitAccessoryImpl + implements CarbonMonoxideSensorAccessory { - @NonNull - private BatteryStatus batteryStatus; + private final BooleanItemReader carbonMonoxideDetectedReader; - private BooleanItemReader carbonMonoxideDetectedReader; - - public HomekitCarbonMonoxideSensorImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, BatteryStatus batteryStatus) { - super(taggedItem, itemRegistry, updater, GenericItem.class); - - this.carbonMonoxideDetectedReader = new BooleanItemReader(taggedItem.getItem(), OnOffType.ON, + public HomekitCarbonMonoxideSensorImpl(HomekitTaggedItem taggedItem, + List mandatoryCharacteristics, HomekitAccessoryUpdater updater, HomekitSettings settings) + throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.carbonMonoxideDetectedReader = new BooleanItemReader( + getItem(HomekitCharacteristicType.CARBON_MONOXIDE_DETECTED_STATE, GenericItem.class), OnOffType.ON, OpenClosedType.OPEN); - this.batteryStatus = batteryStatus; + getServices().add(new CarbonMonoxideSensorService(this)); } @Override - public CompletableFuture getCarbonMonoxideDetectedState() { + public CompletableFuture getCarbonMonoxideDetectedState() { Boolean state = this.carbonMonoxideDetectedReader.getValue(); if (state == null) { return CompletableFuture.completedFuture(null); } return CompletableFuture - .completedFuture(state ? CarbonMonoxideDetectedState.ABNORMAL : CarbonMonoxideDetectedState.NORMAL); + .completedFuture(state ? CarbonMonoxideDetectedEnum.ABNORMAL : CarbonMonoxideDetectedEnum.NORMAL); } @Override public void subscribeCarbonMonoxideDetectedState(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.CARBON_MONOXIDE_DETECTED_STATE, callback); } @Override public void unsubscribeCarbonMonoxideDetectedState() { - getUpdater().unsubscribe(getItem()); - } - - @Override - public CompletableFuture getLowBatteryState() { - return CompletableFuture.completedFuture(batteryStatus.isLow()); - } - - @Override - public void subscribeLowBatteryState(HomekitCharacteristicChangeCallback callback) { - batteryStatus.subscribe(getUpdater(), callback); - } - - @Override - public void unsubscribeLowBatteryState() { - batteryStatus.unsubscribe(getUpdater()); + unsubscribe(HomekitCharacteristicType.CARBON_MONOXIDE_DETECTED_STATE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCharacteristicFactory.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCharacteristicFactory.java new file mode 100644 index 0000000000000..0334aa898d35b --- /dev/null +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitCharacteristicFactory.java @@ -0,0 +1,521 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.io.homekit.internal.accessories; + +import static org.openhab.io.homekit.internal.HomekitCharacteristicType.*; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.items.GenericItem; +import org.eclipse.smarthome.core.items.Item; +import org.eclipse.smarthome.core.library.items.ColorItem; +import org.eclipse.smarthome.core.library.items.DimmerItem; +import org.eclipse.smarthome.core.library.items.NumberItem; +import org.eclipse.smarthome.core.library.items.SwitchItem; +import org.eclipse.smarthome.core.library.types.DecimalType; +import org.eclipse.smarthome.core.library.types.HSBType; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.PercentType; +import org.eclipse.smarthome.core.types.State; +import org.eclipse.smarthome.core.types.UnDefType; +import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitException; +import org.openhab.io.homekit.internal.HomekitTaggedItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.hapjava.characteristics.Characteristic; +import io.github.hapjava.characteristics.CharacteristicEnum; +import io.github.hapjava.characteristics.ExceptionalConsumer; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.audio.VolumeCharacteristic; +import io.github.hapjava.characteristics.impl.battery.StatusLowBatteryCharacteristic; +import io.github.hapjava.characteristics.impl.battery.StatusLowBatteryEnum; +import io.github.hapjava.characteristics.impl.carbondioxidesensor.CarbonDioxideLevelCharacteristic; +import io.github.hapjava.characteristics.impl.carbondioxidesensor.CarbonDioxidePeakLevelCharacteristic; +import io.github.hapjava.characteristics.impl.carbonmonoxidesensor.CarbonMonoxideLevelCharacteristic; +import io.github.hapjava.characteristics.impl.carbonmonoxidesensor.CarbonMonoxidePeakLevelCharacteristic; +import io.github.hapjava.characteristics.impl.common.NameCharacteristic; +import io.github.hapjava.characteristics.impl.common.ObstructionDetectedCharacteristic; +import io.github.hapjava.characteristics.impl.common.StatusActiveCharacteristic; +import io.github.hapjava.characteristics.impl.common.StatusFaultCharacteristic; +import io.github.hapjava.characteristics.impl.common.StatusFaultEnum; +import io.github.hapjava.characteristics.impl.common.StatusTamperedCharacteristic; +import io.github.hapjava.characteristics.impl.common.StatusTamperedEnum; +import io.github.hapjava.characteristics.impl.fan.*; +import io.github.hapjava.characteristics.impl.lightbulb.BrightnessCharacteristic; +import io.github.hapjava.characteristics.impl.lightbulb.ColorTemperatureCharacteristic; +import io.github.hapjava.characteristics.impl.lightbulb.HueCharacteristic; +import io.github.hapjava.characteristics.impl.lightbulb.SaturationCharacteristic; +import io.github.hapjava.characteristics.impl.valve.RemainingDurationCharacteristic; +import io.github.hapjava.characteristics.impl.valve.SetDurationCharacteristic; +import io.github.hapjava.characteristics.impl.windowcovering.CurrentHorizontalTiltAngleCharacteristic; +import io.github.hapjava.characteristics.impl.windowcovering.CurrentVerticalTiltAngleCharacteristic; +import io.github.hapjava.characteristics.impl.windowcovering.HoldPositionCharacteristic; +import io.github.hapjava.characteristics.impl.windowcovering.TargetHorizontalTiltAngleCharacteristic; +import io.github.hapjava.characteristics.impl.windowcovering.TargetVerticalTiltAngleCharacteristic; + +/** + * Creates a optional characteristics . + * + * @author Eugen Freiter - Initial contribution + */ +@NonNullByDefault +@SuppressWarnings("deprecation") +public class HomekitCharacteristicFactory { + private static final Logger logger = LoggerFactory.getLogger(HomekitCharacteristicFactory.class); + + // List of optional characteristics and corresponding method to create them. + private final static Map> optional = new HashMap>() { + { + put(NAME, HomekitCharacteristicFactory::createNameCharacteristic); + put(BATTERY_LOW_STATUS, HomekitCharacteristicFactory::createStatusLowBatteryCharacteristic); + put(FAULT_STATUS, HomekitCharacteristicFactory::createStatusFaultCharacteristic); + put(TAMPERED_STATUS, HomekitCharacteristicFactory::createStatusTamperedCharacteristic); + put(ACTIVE_STATUS, HomekitCharacteristicFactory::createStatusActiveCharacteristic); + put(CARBON_MONOXIDE_LEVEL, HomekitCharacteristicFactory::createCarbonMonoxideLevelCharacteristic); + put(CARBON_MONOXIDE_PEAK_LEVEL, HomekitCharacteristicFactory::createCarbonMonoxidePeakLevelCharacteristic); + put(CARBON_DIOXIDE_LEVEL, HomekitCharacteristicFactory::createCarbonDioxideLevelCharacteristic); + put(CARBON_DIOXIDE_PEAK_LEVEL, HomekitCharacteristicFactory::createCarbonDioxidePeakLevelCharacteristic); + put(HOLD_POSITION, HomekitCharacteristicFactory::createHoldPositionCharacteristic); + put(OBSTRUCTION_STATUS, HomekitCharacteristicFactory::createObstructionDetectedCharacteristic); + put(CURRENT_HORIZONTAL_TILT_ANGLE, + HomekitCharacteristicFactory::createCurrentHorizontalTiltAngleCharacteristic); + put(CURRENT_VERTICAL_TILT_ANGLE, + HomekitCharacteristicFactory::createCurrentVerticalTiltAngleCharacteristic); + put(TARGET_HORIZONTAL_TILT_ANGLE, + HomekitCharacteristicFactory::createTargetHorizontalTiltAngleCharacteristic); + put(TARGET_VERTICAL_TILT_ANGLE, HomekitCharacteristicFactory::createTargetVerticalTiltAngleCharacteristic); + put(HUE, HomekitCharacteristicFactory::createHueCharacteristic); + put(BRIGHTNESS, HomekitCharacteristicFactory::createBrightnessCharacteristic); + put(SATURATION, HomekitCharacteristicFactory::createSaturationCharacteristic); + put(COLOR_TEMPERATURE, HomekitCharacteristicFactory::createColorTemperatureCharacteristic); + put(CURRENT_FAN_STATE, HomekitCharacteristicFactory::createCurrentFanStateCharacteristic); + put(TARGET_FAN_STATE, HomekitCharacteristicFactory::createTargetFanStateCharacteristic); + put(ROTATION_DIRECTION, HomekitCharacteristicFactory::createRotationDirectionCharacteristic); + put(ROTATION_SPEED, HomekitCharacteristicFactory::createRotationSpeedCharacteristic); + put(SWING_MODE, HomekitCharacteristicFactory::createSwingModeCharacteristic); + put(LOCK_CONTROL, HomekitCharacteristicFactory::createLockPhysicalControlsCharacteristic); + put(DURATION, HomekitCharacteristicFactory::createDurationCharacteristic); + put(VOLUME, HomekitCharacteristicFactory::createVolumeCharacteristic); + + put(REMAINING_DURATION, HomekitCharacteristicFactory::createRemainingDurationCharacteristic); + // LEGACY + put(OLD_BATTERY_LOW_STATUS, HomekitCharacteristicFactory::createStatusLowBatteryCharacteristic); + } + }; + + /** + * create optional HomeKit characteristic + * + * @param item corresponding OH item + * @param updater update to keep OH item and HomeKit characteristic in sync + * @return HomeKit characteristic + */ + public static Characteristic createCharacteristic(final HomekitTaggedItem item, HomekitAccessoryUpdater updater) + throws HomekitException { + final @Nullable HomekitCharacteristicType type = item.getCharacteristicType(); + logger.trace("createCharacteristic, type {} item {}", type, item); + if (optional.containsKey(type)) { + return optional.get(type).apply(item, updater); + } + logger.warn("Unsupported optional characteristic. Accessory type {}, characteristic type {}", + item.getAccessoryType(), type); + throw new HomekitException("Unsupported optional characteristic. Characteristic type \"" + type + "\""); + } + + // METHODS TO CREATE SINGLE CHARACTERISTIC FROM OH ITEM + + // supporting methods + @SuppressWarnings("null") + private static CompletableFuture getEnumFromItem(final HomekitTaggedItem item, + T offEnum, T onEnum, T defaultEnum) { + final State state = item.getItem().getState(); + if (state instanceof OnOffType) { + return CompletableFuture.completedFuture(state.equals(OnOffType.OFF) ? offEnum : onEnum); + } else if (state instanceof OpenClosedType) { + return CompletableFuture.completedFuture(state.equals(OpenClosedType.CLOSED) ? offEnum : onEnum); + } else if (state instanceof DecimalType) { + return CompletableFuture.completedFuture(state.as(DecimalType.class).intValue() == 0 ? offEnum : onEnum); + } else if (state instanceof UnDefType) { + return CompletableFuture.completedFuture(defaultEnum); + } + logger.warn( + "Item state {} is not supported. Only OnOffType,OpenClosedType and Decimal (0/1) are supported. Ignore item {}", + state, item.getName()); + return CompletableFuture.completedFuture(defaultEnum); + } + + private static void setValueFromEnum(final HomekitTaggedItem item, CharacteristicEnum value, + CharacteristicEnum offEnum, CharacteristicEnum onEnum) { + if (item.getItem() instanceof SwitchItem) { + if (value.equals(offEnum)) { + ((SwitchItem) item.getItem()).send(OnOffType.OFF); + } else if (value.equals(onEnum)) { + ((SwitchItem) item.getItem()).send(OnOffType.ON); + } else { + logger.warn("Enum value {} is not supported. Only following values are supported: {},{}", value, + offEnum, onEnum); + } + } else if (item.getItem() instanceof NumberItem) { + ((NumberItem) item.getItem()).send(new DecimalType(value.getCode())); + } else { + logger.warn("Item type {} is not supported. Only Switch and Number item types are supported.", + item.getItem().getType()); + } + } + + @SuppressWarnings("null") + private static int getIntFromItem(final HomekitTaggedItem item) { + int value = 0; + final State state = item.getItem().getState(); + if (state instanceof PercentType) { + value = state.as(PercentType.class).intValue(); + } else if (state instanceof DecimalType) { + value = state.as(DecimalType.class).intValue(); + } else if (state instanceof UnDefType) { + logger.debug("Item state {} is UNDEF {}.", state, item.getName()); + } else { + logger.warn( + "Item state {} is not supported for {}. Only PercentType and DecimalType (0/100) are supported.", + state, item.getName()); + } + return value; + } + + private static Supplier> getIntSupplier(final HomekitTaggedItem item) { + return () -> CompletableFuture.completedFuture(getIntFromItem(item)); + } + + private static ExceptionalConsumer setIntConsumer(final HomekitTaggedItem item) { + return (value) -> { + if (item.getItem() instanceof NumberItem) { + ((NumberItem) item.getItem()).send(new DecimalType(value)); + } else { + logger.warn("Item type {} is not supported for {}. Only Number type is supported.", + item.getItem().getType(), item.getName()); + } + }; + } + + private static Supplier> getDoubleSupplier(final HomekitTaggedItem item) { + return () -> { + final DecimalType value = item.getItem().getStateAs(DecimalType.class); + return CompletableFuture.completedFuture(value != null ? value.doubleValue() : 0.0); + }; + } + + protected static Consumer getSubscriber(final HomekitTaggedItem item, + final HomekitCharacteristicType key, final HomekitAccessoryUpdater updater) { + return (callback) -> updater.subscribe((GenericItem) item.getItem(), key.getTag(), callback); + } + + protected static Runnable getUnsubscriber(final HomekitTaggedItem item, final HomekitCharacteristicType key, + final HomekitAccessoryUpdater updater) { + return () -> updater.unsubscribe((GenericItem) item.getItem(), key.getTag()); + } + + // create method for characteristic + private static StatusLowBatteryCharacteristic createStatusLowBatteryCharacteristic(final HomekitTaggedItem item, + final HomekitAccessoryUpdater updater) { + return new StatusLowBatteryCharacteristic( + () -> getEnumFromItem(item, StatusLowBatteryEnum.NORMAL, StatusLowBatteryEnum.LOW, + StatusLowBatteryEnum.NORMAL), + getSubscriber(item, BATTERY_LOW_STATUS, updater), getUnsubscriber(item, BATTERY_LOW_STATUS, updater)); + } + + private static StatusFaultCharacteristic createStatusFaultCharacteristic(final HomekitTaggedItem item, + final HomekitAccessoryUpdater updater) { + return new StatusFaultCharacteristic( + () -> getEnumFromItem(item, StatusFaultEnum.NO_FAULT, StatusFaultEnum.GENERAL_FAULT, + StatusFaultEnum.NO_FAULT), + getSubscriber(item, FAULT_STATUS, updater), getUnsubscriber(item, FAULT_STATUS, updater)); + } + + private static StatusTamperedCharacteristic createStatusTamperedCharacteristic(final HomekitTaggedItem item, + final HomekitAccessoryUpdater updater) { + return new StatusTamperedCharacteristic( + () -> getEnumFromItem(item, StatusTamperedEnum.NOT_TAMPERED, StatusTamperedEnum.TAMPERED, + StatusTamperedEnum.NOT_TAMPERED), + getSubscriber(item, TAMPERED_STATUS, updater), getUnsubscriber(item, TAMPERED_STATUS, updater)); + } + + private static ObstructionDetectedCharacteristic createObstructionDetectedCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new ObstructionDetectedCharacteristic( + () -> CompletableFuture.completedFuture( + item.getItem().getState() == OnOffType.ON || item.getItem().getState() == OpenClosedType.OPEN), + getSubscriber(item, OBSTRUCTION_STATUS, updater), getUnsubscriber(item, OBSTRUCTION_STATUS, updater)); + } + + private static StatusActiveCharacteristic createStatusActiveCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new StatusActiveCharacteristic( + () -> CompletableFuture.completedFuture( + item.getItem().getState() == OnOffType.ON || item.getItem().getState() == OpenClosedType.OPEN), + getSubscriber(item, ACTIVE_STATUS, updater), getUnsubscriber(item, ACTIVE_STATUS, updater)); + } + + private static NameCharacteristic createNameCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new NameCharacteristic(() -> { + final State state = item.getItem().getState(); + return CompletableFuture.completedFuture(state instanceof UnDefType ? "" : state.toString()); + }); + } + + private static HoldPositionCharacteristic createHoldPositionCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new HoldPositionCharacteristic(OnOffType::from); + } + + private static CarbonMonoxideLevelCharacteristic createCarbonMonoxideLevelCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new CarbonMonoxideLevelCharacteristic(getDoubleSupplier(item), + getSubscriber(item, CARBON_DIOXIDE_LEVEL, updater), + getUnsubscriber(item, CARBON_DIOXIDE_LEVEL, updater)); + } + + private static CarbonMonoxidePeakLevelCharacteristic createCarbonMonoxidePeakLevelCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new CarbonMonoxidePeakLevelCharacteristic(getDoubleSupplier(item), + getSubscriber(item, CARBON_DIOXIDE_PEAK_LEVEL, updater), + getUnsubscriber(item, CARBON_DIOXIDE_PEAK_LEVEL, updater)); + } + + private static CarbonDioxideLevelCharacteristic createCarbonDioxideLevelCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new CarbonDioxideLevelCharacteristic(getDoubleSupplier(item), + getSubscriber(item, CARBON_MONOXIDE_LEVEL, updater), + getUnsubscriber(item, CARBON_MONOXIDE_LEVEL, updater)); + } + + private static CarbonDioxidePeakLevelCharacteristic createCarbonDioxidePeakLevelCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new CarbonDioxidePeakLevelCharacteristic(getDoubleSupplier(item), + getSubscriber(item, CARBON_MONOXIDE_PEAK_LEVEL, updater), + getUnsubscriber(item, CARBON_MONOXIDE_PEAK_LEVEL, updater)); + } + + private static CurrentHorizontalTiltAngleCharacteristic createCurrentHorizontalTiltAngleCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new CurrentHorizontalTiltAngleCharacteristic(getIntSupplier(item), + getSubscriber(item, CURRENT_HORIZONTAL_TILT_ANGLE, updater), + getUnsubscriber(item, CURRENT_HORIZONTAL_TILT_ANGLE, updater)); + } + + private static CurrentVerticalTiltAngleCharacteristic createCurrentVerticalTiltAngleCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new CurrentVerticalTiltAngleCharacteristic(getIntSupplier(item), + getSubscriber(item, CURRENT_VERTICAL_TILT_ANGLE, updater), + getUnsubscriber(item, CURRENT_VERTICAL_TILT_ANGLE, updater)); + } + + private static TargetHorizontalTiltAngleCharacteristic createTargetHorizontalTiltAngleCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new TargetHorizontalTiltAngleCharacteristic(getIntSupplier(item), setIntConsumer(item), + getSubscriber(item, TARGET_HORIZONTAL_TILT_ANGLE, updater), + getUnsubscriber(item, TARGET_HORIZONTAL_TILT_ANGLE, updater)); + } + + private static TargetVerticalTiltAngleCharacteristic createTargetVerticalTiltAngleCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new TargetVerticalTiltAngleCharacteristic(getIntSupplier(item), setIntConsumer(item), + getSubscriber(item, TARGET_HORIZONTAL_TILT_ANGLE, updater), + getUnsubscriber(item, TARGET_HORIZONTAL_TILT_ANGLE, updater)); + } + + private static HueCharacteristic createHueCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new HueCharacteristic(() -> { + Double value = 0.0; + State state = item.getItem().getState(); + if (state instanceof HSBType) { + value = ((HSBType) state).getHue().doubleValue(); + } + return CompletableFuture.completedFuture(value); + }, (hue) -> { + State state = item.getItem().getState(); + if (item.getItem() instanceof ColorItem) { + ((ColorItem) item.getItem()).send(new HSBType(new DecimalType(hue), ((HSBType) state).getSaturation(), + ((HSBType) state).getBrightness())); + } else { + logger.warn("Item type {} is not supported for {}. Only Color type is supported.", + item.getItem().getType(), item.getName()); + } + }, getSubscriber(item, HUE, updater), getUnsubscriber(item, HUE, updater)); + } + + private static BrightnessCharacteristic createBrightnessCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new BrightnessCharacteristic(() -> { + int value = 0; + final State state = item.getItem().getState(); + if (state instanceof HSBType) { + value = ((HSBType) state).getBrightness().intValue(); + } else if (state instanceof PercentType) { + value = ((PercentType) state).intValue(); + } + return CompletableFuture.completedFuture(value); + }, (brightness) -> { + final Item oItem = item.getItem(); + final State state = oItem.getState(); + if (oItem instanceof ColorItem) { + ((ColorItem) oItem).send(new HSBType(((HSBType) state).getHue(), ((HSBType) state).getSaturation(), + new PercentType(brightness))); + } else if (oItem instanceof DimmerItem) { + ((DimmerItem) oItem).send(new PercentType(brightness)); + } else { + logger.warn("Item type {} is not supported for {}. Only ColorItem and DimmerItem are supported.", + oItem.getType(), item.getName()); + } + }, getSubscriber(item, BRIGHTNESS, updater), getUnsubscriber(item, BRIGHTNESS, updater)); + } + + private static SaturationCharacteristic createSaturationCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new SaturationCharacteristic(() -> { + Double value = 0.0; + State state = item.getItem().getState(); + if (state instanceof HSBType) { + value = ((HSBType) state).getSaturation().doubleValue(); + } else if (state instanceof PercentType) { + value = ((PercentType) state).doubleValue(); + } + return CompletableFuture.completedFuture(value); + }, (saturation) -> { + final State state = item.getItem().getState(); + if (item.getItem() instanceof ColorItem) { + ((ColorItem) item.getItem()).send(new HSBType(((HSBType) state).getHue(), + new PercentType(saturation.intValue()), ((HSBType) state).getBrightness())); + } else { + logger.warn("Item type {} is not supported for {}. Only Color type is supported.", + item.getItem().getType(), item.getName()); + } + }, getSubscriber(item, SATURATION, updater), getUnsubscriber(item, SATURATION, updater)); + } + + private static ColorTemperatureCharacteristic createColorTemperatureCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new ColorTemperatureCharacteristic(getIntSupplier(item), setIntConsumer(item), + getSubscriber(item, COLOR_TEMPERATURE, updater), getUnsubscriber(item, COLOR_TEMPERATURE, updater)); + } + + private static CurrentFanStateCharacteristic createCurrentFanStateCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new CurrentFanStateCharacteristic(() -> { + final DecimalType value = item.getItem().getStateAs(DecimalType.class); + CurrentFanStateEnum currentFanStateEnum = value != null ? CurrentFanStateEnum.fromCode(value.intValue()) + : null; + if (currentFanStateEnum == null) { + currentFanStateEnum = CurrentFanStateEnum.INACTIVE; + } + return CompletableFuture.completedFuture(currentFanStateEnum); + }, getSubscriber(item, CURRENT_FAN_STATE, updater), getUnsubscriber(item, CURRENT_FAN_STATE, updater)); + } + + private static TargetFanStateCharacteristic createTargetFanStateCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new TargetFanStateCharacteristic(() -> { + final DecimalType value = item.getItem().getStateAs(DecimalType.class); + TargetFanStateEnum targetFanStateEnum = value != null ? TargetFanStateEnum.fromCode(value.intValue()) + : null; + if (targetFanStateEnum == null) { + targetFanStateEnum = TargetFanStateEnum.AUTO; + } + return CompletableFuture.completedFuture(targetFanStateEnum); + }, (targetState) -> { + if (item.getItem() instanceof NumberItem) { + ((NumberItem) item.getItem()).send(new DecimalType(targetState.getCode())); + } else { + logger.warn("Item type {} is not supported for {}. Only Number type is supported.", + item.getItem().getType(), item.getName()); + } + }, getSubscriber(item, TARGET_FAN_STATE, updater), getUnsubscriber(item, TARGET_FAN_STATE, updater)); + } + + private static RotationDirectionCharacteristic createRotationDirectionCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new RotationDirectionCharacteristic( + () -> getEnumFromItem(item, RotationDirectionEnum.CLOCKWISE, RotationDirectionEnum.COUNTER_CLOCKWISE, + RotationDirectionEnum.CLOCKWISE), + (value) -> setValueFromEnum(item, value, RotationDirectionEnum.CLOCKWISE, + RotationDirectionEnum.COUNTER_CLOCKWISE), + getSubscriber(item, ROTATION_DIRECTION, updater), getUnsubscriber(item, ROTATION_DIRECTION, updater)); + } + + private static SwingModeCharacteristic createSwingModeCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new SwingModeCharacteristic( + () -> getEnumFromItem(item, SwingModeEnum.SWING_DISABLED, SwingModeEnum.SWING_ENABLED, + SwingModeEnum.SWING_DISABLED), + (value) -> setValueFromEnum(item, value, SwingModeEnum.SWING_DISABLED, SwingModeEnum.SWING_ENABLED), + getSubscriber(item, SWING_MODE, updater), getUnsubscriber(item, SWING_MODE, updater)); + } + + private static LockPhysicalControlsCharacteristic createLockPhysicalControlsCharacteristic( + final HomekitTaggedItem item, HomekitAccessoryUpdater updater) { + return new LockPhysicalControlsCharacteristic( + () -> getEnumFromItem(item, LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED, + LockPhysicalControlsEnum.CONTROL_LOCK_ENABLED, LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED), + (value) -> setValueFromEnum(item, value, LockPhysicalControlsEnum.CONTROL_LOCK_DISABLED, + LockPhysicalControlsEnum.CONTROL_LOCK_ENABLED), + getSubscriber(item, LOCK_CONTROL, updater), getUnsubscriber(item, LOCK_CONTROL, updater)); + } + + private static RotationSpeedCharacteristic createRotationSpeedCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new RotationSpeedCharacteristic(getIntSupplier(item), setIntConsumer(item), + getSubscriber(item, ROTATION_SPEED, updater), getUnsubscriber(item, ROTATION_SPEED, updater)); + } + + private static SetDurationCharacteristic createDurationCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new SetDurationCharacteristic(() -> { + int value = getIntFromItem(item); + if (value == 0) { // check for default duration + final Object duration = item.getConfiguration().get(HomekitValveImpl.CONFIG_DEFAULT_DURATION); + if ((duration != null) && (duration instanceof BigDecimal)) { + value = ((BigDecimal) duration).intValue(); + if (item.getItem() instanceof NumberItem) { + ((NumberItem) item.getItem()).setState(new DecimalType(value)); + } + } + } + return CompletableFuture.completedFuture(value); + }, setIntConsumer(item), getSubscriber(item, DURATION, updater), getUnsubscriber(item, DURATION, updater)); + } + + private static RemainingDurationCharacteristic createRemainingDurationCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new RemainingDurationCharacteristic(getIntSupplier(item), + getSubscriber(item, REMAINING_DURATION, updater), getUnsubscriber(item, REMAINING_DURATION, updater)); + } + + private static VolumeCharacteristic createVolumeCharacteristic(final HomekitTaggedItem item, + HomekitAccessoryUpdater updater) { + return new VolumeCharacteristic(getIntSupplier(item), + (volume) -> ((NumberItem) item.getItem()).send(new DecimalType(volume)), + getSubscriber(item, DURATION, updater), getUnsubscriber(item, DURATION, updater)); + } +} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitColorfulLightbulbImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitColorfulLightbulbImpl.java deleted file mode 100644 index f2e135f12a70b..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitColorfulLightbulbImpl.java +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.accessories; - -import java.util.concurrent.CompletableFuture; - -import org.eclipse.smarthome.core.items.ItemRegistry; -import org.eclipse.smarthome.core.library.items.ColorItem; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.eclipse.smarthome.core.library.types.HSBType; -import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.types.State; -import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; -import org.openhab.io.homekit.internal.HomekitTaggedItem; - -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.ColorfulLightbulb; -import io.github.hapjava.accessories.DimmableLightbulb; - -/** - * Implements ColorfulLightBulb using an Item that provides a On/Off and color state - * - * @author Felix Rotthowe - Initial contribution - */ -class HomekitColorfulLightbulbImpl extends AbstractHomekitLightbulbImpl - implements ColorfulLightbulb, DimmableLightbulb { - - public HomekitColorfulLightbulbImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater) { - super(taggedItem, itemRegistry, updater, ColorItem.class); - } - - @Override - public CompletableFuture getHue() { - State state = getItem().getStateAs(HSBType.class); - if (state instanceof HSBType) { - HSBType hsb = (HSBType) state; - return CompletableFuture.completedFuture(hsb.getHue().doubleValue()); - } else { - return CompletableFuture.completedFuture(null); - } - } - - @Override - public CompletableFuture getSaturation() { - State state = getItem().getStateAs(HSBType.class); - if (state instanceof HSBType) { - HSBType hsb = (HSBType) state; - return CompletableFuture.completedFuture(hsb.getSaturation().doubleValue()); - } else { - return CompletableFuture.completedFuture(null); - } - } - - @Override - public CompletableFuture getBrightness() { - State state = getItem().getStateAs(PercentType.class); - if (state instanceof PercentType) { - PercentType brightness = (PercentType) state; - return CompletableFuture.completedFuture(brightness.intValue()); - } else { - return CompletableFuture.completedFuture(null); - } - } - - @Override - public CompletableFuture setHue(Double value) throws Exception { - final double hue = value == null ? 0.0 : value; - State state = getItem().getStateAs(HSBType.class); - if (state instanceof HSBType) { - HSBType hsb = (HSBType) state; - HSBType newState = new HSBType(new DecimalType(hue), hsb.getSaturation(), hsb.getBrightness()); - ((ColorItem) getItem()).send(newState); - return CompletableFuture.completedFuture(null); - } else { - // state is undefined (light is not connected) - return CompletableFuture.completedFuture(null); - } - } - - @Override - public CompletableFuture setSaturation(Double value) throws Exception { - final int saturation = value == null ? 0 : value.intValue(); - State state = getItem().getStateAs(HSBType.class); - if (state instanceof HSBType) { - HSBType hsb = (HSBType) state; - HSBType newState = new HSBType(hsb.getHue(), new PercentType(saturation), hsb.getBrightness()); - ((ColorItem) getItem()).send(newState); - return CompletableFuture.completedFuture(null); - } else { - // state is undefined (light is not connected) - return CompletableFuture.completedFuture(null); - } - } - - @Override - public CompletableFuture setBrightness(Integer value) throws Exception { - final int brightness = value == null ? 0 : value; - State state = getItem().getStateAs(HSBType.class); - if (state instanceof HSBType) { - HSBType hsb = (HSBType) state; - HSBType newState = new HSBType(hsb.getHue(), hsb.getSaturation(), new PercentType(brightness)); - ((ColorItem) getItem()).send(newState); - return CompletableFuture.completedFuture(null); - } else { - // state is undefined (light is not connected) - return CompletableFuture.completedFuture(null); - } - } - - @Override - public void subscribeHue(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), "hue", callback); - } - - @Override - public void subscribeSaturation(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), "saturation", callback); - } - - @Override - public void subscribeBrightness(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), "brightness", callback); - } - - @Override - public void unsubscribeHue() { - getUpdater().unsubscribe(getItem(), "hue"); - } - - @Override - public void unsubscribeSaturation() { - getUpdater().unsubscribe(getItem(), "saturation"); - } - - @Override - public void unsubscribeBrightness() { - getUpdater().unsubscribe(getItem(), "brightness"); - } -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitContactSensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitContactSensorImpl.java index fd6d38072564a..229a77caf5a1f 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitContactSensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitContactSensorImpl.java @@ -12,72 +12,52 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.OpenClosedType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import org.openhab.io.homekit.internal.battery.BatteryStatus; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.BatteryStatusAccessory; -import io.github.hapjava.accessories.ContactSensor; -import io.github.hapjava.accessories.properties.ContactState; +import io.github.hapjava.accessories.ContactSensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.contactsensor.ContactStateEnum; +import io.github.hapjava.services.impl.ContactSensorService; /** * - * @author Philipp Arndt - Initial contribution; Tim Harper - support for battery status + * @author Philipp Arndt - Initial contribution */ -public class HomekitContactSensorImpl extends AbstractHomekitAccessoryImpl - implements ContactSensor, BatteryStatusAccessory { - private BatteryStatus batteryStatus; - private BooleanItemReader contactSensedReader; - - public HomekitContactSensorImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, BatteryStatus batteryStatus) { - super(taggedItem, itemRegistry, updater, GenericItem.class); - this.contactSensedReader = new BooleanItemReader(taggedItem.getItem(), OnOffType.OFF, OpenClosedType.CLOSED); - this.batteryStatus = batteryStatus; +public class HomekitContactSensorImpl extends AbstractHomekitAccessoryImpl implements ContactSensorAccessory { + private final BooleanItemReader contactSensedReader; + + public HomekitContactSensorImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.contactSensedReader = new BooleanItemReader( + getItem(HomekitCharacteristicType.CONTACT_SENSOR_STATE, GenericItem.class), OnOffType.ON, + OpenClosedType.OPEN); + getServices().add(new ContactSensorService(this)); } @Override - public CompletableFuture getCurrentState() { - Boolean contactDetected = contactSensedReader.getValue(); - if (contactDetected == null) { - // BUG - HAP-java does not currently handle null well here, so we'll default to not detected. - return CompletableFuture.completedFuture(ContactState.NOT_DETECTED); - } else if (contactDetected) { - return CompletableFuture.completedFuture(ContactState.DETECTED); - } else { - return CompletableFuture.completedFuture(ContactState.NOT_DETECTED); - } + public CompletableFuture getCurrentState() { + Boolean isOpen = contactSensedReader.getValue(); + return CompletableFuture + .completedFuture((isOpen == Boolean.TRUE) ? ContactStateEnum.NOT_DETECTED : ContactStateEnum.DETECTED); } @Override public void subscribeContactState(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.CONTACT_SENSOR_STATE, callback); } @Override public void unsubscribeContactState() { - getUpdater().unsubscribe(getItem()); - } - - @Override - public CompletableFuture getLowBatteryState() { - return CompletableFuture.completedFuture(batteryStatus.isLow()); - } - - @Override - public void subscribeLowBatteryState(HomekitCharacteristicChangeCallback callback) { - batteryStatus.subscribe(getUpdater(), callback); - } - - @Override - public void unsubscribeLowBatteryState() { - batteryStatus.unsubscribe(getUpdater()); + unsubscribe(HomekitCharacteristicType.CONTACT_SENSOR_STATE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitDimmableLightbulbImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitDimmableLightbulbImpl.java deleted file mode 100644 index 97722ce1e1de0..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitDimmableLightbulbImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.accessories; - -import java.util.concurrent.CompletableFuture; - -import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.GroupItem; -import org.eclipse.smarthome.core.items.ItemRegistry; -import org.eclipse.smarthome.core.library.items.DimmerItem; -import org.eclipse.smarthome.core.library.types.PercentType; -import org.eclipse.smarthome.core.types.State; -import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; -import org.openhab.io.homekit.internal.HomekitTaggedItem; - -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.DimmableLightbulb; - -/** - * Implements DimmableLightBulb using an Item that provides a On/Off and Percent state. - * - * @author Andy Lintner - Initial contribution - */ -class HomekitDimmableLightbulbImpl extends AbstractHomekitLightbulbImpl implements DimmableLightbulb { - - public HomekitDimmableLightbulbImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater) { - super(taggedItem, itemRegistry, updater, DimmerItem.class); - } - - @Override - public CompletableFuture getBrightness() { - State state = getItem().getStateAs(PercentType.class); - if (state instanceof PercentType) { - PercentType brightness = (PercentType) state; - return CompletableFuture.completedFuture(brightness.intValue()); - } else { - return CompletableFuture.completedFuture(null); - } - } - - @Override - public CompletableFuture setBrightness(Integer value) throws Exception { - GenericItem item = getItem(); - if (item instanceof DimmerItem) { - ((DimmerItem) item).send(new PercentType(value)); - } else if (item instanceof GroupItem) { - ((GroupItem) item).send(new PercentType(value)); - } - return CompletableFuture.completedFuture(null); - } - - @Override - public void subscribeBrightness(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), "brightness", callback); - } - - @Override - public void unsubscribeBrightness() { - getUpdater().unsubscribe(getItem(), "brightness"); - } -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitFanImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitFanImpl.java new file mode 100644 index 0000000000000..985806852c217 --- /dev/null +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitFanImpl.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.io.homekit.internal.accessories; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.items.SwitchItem; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.types.State; +import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; +import org.openhab.io.homekit.internal.HomekitTaggedItem; + +import io.github.hapjava.accessories.FanAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.impl.FanService; + +/** + * Implements Fan using an Item that provides an On/Off state + * + * @author Eugen Freiter - Initial contribution + */ +class HomekitFanImpl extends AbstractHomekitAccessoryImpl implements FanAccessory { + public HomekitFanImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.getServices().add(new FanService(this)); + } + + @Override + public CompletableFuture isActive() { + final @Nullable State state = getStateAs(HomekitCharacteristicType.ACTIVE_STATUS, OnOffType.class); + return CompletableFuture.completedFuture(state == OnOffType.ON); + } + + @Override + public CompletableFuture setActive(final boolean state) throws Exception { + final @Nullable SwitchItem item = getItem(HomekitCharacteristicType.ACTIVE_STATUS, SwitchItem.class); + if (item != null) { + item.send(OnOffType.from(state)); + } + return CompletableFuture.completedFuture(null); + } + + @Override + public void subscribeActive(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.ACTIVE_STATUS, callback); + } + + @Override + public void unsubscribeActive() { + unsubscribe(HomekitCharacteristicType.ACTIVE_STATUS); + } +} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitGarageDoorOpenerImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitGarageDoorOpenerImpl.java new file mode 100644 index 0000000000000..bd3ee7d9d9195 --- /dev/null +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitGarageDoorOpenerImpl.java @@ -0,0 +1,192 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.io.homekit.internal.accessories; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.items.GenericItem; +import org.eclipse.smarthome.core.items.Item; +import org.eclipse.smarthome.core.library.items.StringItem; +import org.eclipse.smarthome.core.library.items.SwitchItem; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.library.types.StringType; +import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; +import org.openhab.io.homekit.internal.HomekitTaggedItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.hapjava.accessories.GarageDoorOpenerAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.garagedoor.CurrentDoorStateEnum; +import io.github.hapjava.characteristics.impl.garagedoor.TargetDoorStateEnum; +import io.github.hapjava.services.impl.GarageDoorOpenerService; + +/** + * Implements Garage Door Opener + * + * @author Eugen Freiter - Initial contribution + */ +public class HomekitGarageDoorOpenerImpl extends AbstractHomekitAccessoryImpl implements GarageDoorOpenerAccessory { + private Logger logger = LoggerFactory.getLogger(HomekitGarageDoorOpenerImpl.class); + + public HomekitGarageDoorOpenerImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.getServices().add(new GarageDoorOpenerService(this)); + } + + @Override + public CompletableFuture getCurrentDoorState() { + final Optional characteristic = getCharacteristic( + HomekitCharacteristicType.CURRENT_DOOR_STATE); + final HomekitSettings settings = getSettings(); + String stringValue = settings.doorCurrentStateClosed; + if (characteristic.isPresent()) { + stringValue = characteristic.get().getItem().getState().toString(); + } else { + logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.CURRENT_DOOR_STATE); + } + CurrentDoorStateEnum mode; + + if (stringValue.equalsIgnoreCase(settings.doorCurrentStateClosed)) { + mode = CurrentDoorStateEnum.CLOSED; + } else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateClosing)) { + mode = CurrentDoorStateEnum.CLOSING; + } else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateOpen)) { + mode = CurrentDoorStateEnum.OPEN; + } else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateOpening)) { + mode = CurrentDoorStateEnum.OPENING; + } else if (stringValue.equalsIgnoreCase(settings.doorCurrentStateStopped)) { + mode = CurrentDoorStateEnum.SOPPED; + } else if (stringValue.equals("UNDEF") || stringValue.equals("NULL")) { + logger.warn("Current door state not available. Relaying value of CLOSED to Homekit"); + mode = CurrentDoorStateEnum.CLOSED; + } else { + logger.warn("Unrecognized current door state: {}. Expected {}, {}, {}, {} or {} strings in value.", + stringValue, settings.doorCurrentStateClosed, settings.doorCurrentStateClosing, + settings.doorCurrentStateOpen, settings.doorCurrentStateOpening, settings.doorCurrentStateStopped); + mode = CurrentDoorStateEnum.CLOSED; + } + return CompletableFuture.completedFuture(mode); + } + + @Override + public CompletableFuture getTargetDoorState() { + final Optional characteristic = getCharacteristic( + HomekitCharacteristicType.TARGET_DOOR_STATE); + Item item; + + if (characteristic.isPresent()) { + item = characteristic.get().getItem(); + } else { + logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.TARGET_DOOR_STATE); + return CompletableFuture.completedFuture(TargetDoorStateEnum.CLOSED); + } + TargetDoorStateEnum mode; + + if (item instanceof SwitchItem) { + mode = item.getState() == OnOffType.ON ? TargetDoorStateEnum.OPEN : TargetDoorStateEnum.CLOSED; + } else if (item instanceof StringItem) { + final HomekitSettings settings = getSettings(); + final String stringValue = item.getState().toString(); + if (stringValue.equalsIgnoreCase(settings.doorTargetStateClosed)) { + mode = TargetDoorStateEnum.CLOSED; + } else if (stringValue.equalsIgnoreCase(settings.doorTargetStateOpen)) { + mode = TargetDoorStateEnum.OPEN; + ; + } else { + logger.warn( + "Unsupported value {} for {}. Only {} and {} supported. Check HomeKit settings if you want to change the mapping", + stringValue, item.getName(), settings.doorTargetStateClosed, settings.doorTargetStateOpen); + mode = TargetDoorStateEnum.CLOSED; + } + } else { + logger.warn("Unsupported item type {} for {}. Only Switch and String are supported", item.getType(), + item.getName()); + mode = TargetDoorStateEnum.CLOSED; + } + return CompletableFuture.completedFuture(mode); + } + + @Override + public CompletableFuture getObstructionDetected() { + final @Nullable Item item = getItem(HomekitCharacteristicType.OBSTRUCTION_STATUS, GenericItem.class); + if (item == null) { + logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.OBSTRUCTION_STATUS); + } + return CompletableFuture + .completedFuture(item.getState() == OnOffType.ON || item.getState() == OpenClosedType.OPEN); + } + + @Override + public CompletableFuture setTargetDoorState(final TargetDoorStateEnum targetDoorStateEnum) { + final Optional characteristic = getCharacteristic( + HomekitCharacteristicType.TARGET_DOOR_STATE); + Item item; + if (characteristic.isPresent()) { + item = characteristic.get().getItem(); + } else { + logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.TARGET_DOOR_STATE); + return CompletableFuture.completedFuture(null); + } + + if (item instanceof SwitchItem) { + ((SwitchItem) item).send(OnOffType.from(targetDoorStateEnum == TargetDoorStateEnum.OPEN)); + } else if (item instanceof StringItem) { + final HomekitSettings settings = getSettings(); + ((StringItem) item) + .send(new StringType(targetDoorStateEnum == TargetDoorStateEnum.OPEN ? settings.doorTargetStateOpen + : settings.doorTargetStateClosed)); + } else { + logger.warn("Unsupported item type {} for {}. Only Switch and String are supported", item.getType(), + item.getName()); + } + return CompletableFuture.completedFuture(null); + } + + @Override + public void subscribeCurrentDoorState(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.CURRENT_DOOR_STATE, callback); + } + + @Override + public void subscribeTargetDoorState(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.TARGET_DOOR_STATE, callback); + } + + @Override + public void subscribeObstructionDetected(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.OBSTRUCTION_STATUS, callback); + } + + @Override + public void unsubscribeCurrentDoorState() { + unsubscribe(HomekitCharacteristicType.CURRENT_DOOR_STATE); + } + + @Override + public void unsubscribeTargetDoorState() { + unsubscribe(HomekitCharacteristicType.TARGET_DOOR_STATE); + } + + @Override + public void unsubscribeObstructionDetected() { + unsubscribe(HomekitCharacteristicType.OBSTRUCTION_STATUS); + } +} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitHumiditySensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitHumiditySensorImpl.java index 388d07eb2a741..e7b1358788156 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitHumiditySensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitHumiditySensorImpl.java @@ -12,44 +12,52 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.math.BigDecimal; +import java.util.List; import java.util.concurrent.CompletableFuture; -import org.eclipse.smarthome.core.items.ItemRegistry; -import org.eclipse.smarthome.core.library.items.NumberItem; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DecimalType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.HumiditySensor; +import io.github.hapjava.accessories.HumiditySensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.impl.HumiditySensorService; /** * * @author Andy Lintner - Initial contribution */ -public class HomekitHumiditySensorImpl extends AbstractHomekitAccessoryImpl implements HumiditySensor { +public class HomekitHumiditySensorImpl extends AbstractHomekitAccessoryImpl implements HumiditySensorAccessory { + private final static String CONFIG_MULTIPLICATOR = "homekitMultiplicator"; - public HomekitHumiditySensorImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater) { - super(taggedItem, itemRegistry, updater, NumberItem.class); + public HomekitHumiditySensorImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + getServices().add(new HumiditySensorService(this)); } @Override public CompletableFuture getCurrentRelativeHumidity() { - DecimalType state = getItem().getStateAs(DecimalType.class); - if (state == null) { - return CompletableFuture.completedFuture(null); + @Nullable + DecimalType state = getStateAs(HomekitCharacteristicType.RELATIVE_HUMIDITY, DecimalType.class); + if (state != null) { + BigDecimal multiplicator = getAccessoryConfiguration(CONFIG_MULTIPLICATOR, BigDecimal.valueOf(1.0)); + return CompletableFuture.completedFuture((state.toBigDecimal().multiply(multiplicator)).doubleValue()); } - return CompletableFuture.completedFuture(state.doubleValue()); + return CompletableFuture.completedFuture(0.0); } @Override public void subscribeCurrentRelativeHumidity(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.RELATIVE_HUMIDITY, callback); } @Override public void unsubscribeCurrentRelativeHumidity() { - getUpdater().unsubscribe(getItem()); + unsubscribe(HomekitCharacteristicType.RELATIVE_HUMIDITY); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLeakSensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLeakSensorImpl.java index 8030fd840e64f..87da6d8aa2b12 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLeakSensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLeakSensorImpl.java @@ -12,68 +12,53 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.OpenClosedType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import org.openhab.io.homekit.internal.battery.BatteryStatus; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.BatteryStatusAccessory; -import io.github.hapjava.accessories.LeakSensor; +import io.github.hapjava.accessories.LeakSensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.leaksensor.LeakDetectedStateEnum; +import io.github.hapjava.services.impl.LeakSensorService; /** * * @author Tim Harper - Initial contribution */ -public class HomekitLeakSensorImpl extends AbstractHomekitAccessoryImpl - implements LeakSensor, BatteryStatusAccessory { +public class HomekitLeakSensorImpl extends AbstractHomekitAccessoryImpl implements LeakSensorAccessory { + private final BooleanItemReader leakDetectedReader; - @NonNull - private BatteryStatus batteryStatus; - - private BooleanItemReader leakDetectedReader; - - public HomekitLeakSensorImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, BatteryStatus batteryStatus) { - super(taggedItem, itemRegistry, updater, GenericItem.class); - - this.leakDetectedReader = new BooleanItemReader(taggedItem.getItem(), OnOffType.ON, OpenClosedType.OPEN); - this.batteryStatus = batteryStatus; + public HomekitLeakSensorImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.leakDetectedReader = new BooleanItemReader( + getItem(HomekitCharacteristicType.LEAK_DETECTED_STATE, GenericItem.class), OnOffType.ON, + OpenClosedType.OPEN); + getServices().add(new LeakSensorService(this)); } @Override - public CompletableFuture getLeakDetected() { - return CompletableFuture.completedFuture(this.leakDetectedReader.getValue()); + public CompletableFuture getLeakDetected() { + return CompletableFuture + .completedFuture((this.leakDetectedReader.getValue() != null && this.leakDetectedReader.getValue()) + ? LeakDetectedStateEnum.LEAK_DETECTED + : LeakDetectedStateEnum.LEAK_NOT_DETECTED); } @Override public void subscribeLeakDetected(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.LEAK_DETECTED_STATE, callback); } @Override public void unsubscribeLeakDetected() { - getUpdater().unsubscribe(getItem()); - } - - @Override - public CompletableFuture getLowBatteryState() { - return CompletableFuture.completedFuture(batteryStatus.isLow()); - } - - @Override - public void subscribeLowBatteryState(HomekitCharacteristicChangeCallback callback) { - batteryStatus.subscribe(getUpdater(), callback); - } - - @Override - public void unsubscribeLowBatteryState() { - batteryStatus.unsubscribe(getUpdater()); + unsubscribe(HomekitCharacteristicType.LEAK_DETECTED_STATE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLightbulbImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLightbulbImpl.java index 86a221e08037c..af5bc1872dd64 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLightbulbImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLightbulbImpl.java @@ -12,20 +12,59 @@ */ package org.openhab.io.homekit.internal.accessories; -import org.eclipse.smarthome.core.items.ItemRegistry; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.smarthome.core.items.GenericItem; +import org.eclipse.smarthome.core.items.GroupItem; import org.eclipse.smarthome.core.library.items.SwitchItem; +import org.eclipse.smarthome.core.library.types.OnOffType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; +import io.github.hapjava.accessories.LightbulbAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.impl.LightbulbService; + /** * Implements Lightbulb using an Item that provides an On/Off state * * @author Andy Lintner - Initial contribution */ -class HomekitLightbulbImpl extends AbstractHomekitLightbulbImpl { +class HomekitLightbulbImpl extends AbstractHomekitAccessoryImpl implements LightbulbAccessory { + + public HomekitLightbulbImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.getServices().add(new LightbulbService(this)); + } + + @Override + public CompletableFuture getLightbulbPowerState() { + OnOffType state = getStateAs(HomekitCharacteristicType.ON_STATE, OnOffType.class); + return CompletableFuture.completedFuture(state == OnOffType.ON); + } + + @Override + public CompletableFuture setLightbulbPowerState(boolean value) { + GenericItem item = getItem(HomekitCharacteristicType.ON_STATE, GenericItem.class); + if (item instanceof SwitchItem) { + ((SwitchItem) item).send(OnOffType.from(value)); + } else if (item instanceof GroupItem) { + ((GroupItem) item).send(OnOffType.from(value)); + } + return CompletableFuture.completedFuture(null); + } + + @Override + public void subscribeLightbulbPowerState(HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.ON_STATE, callback); + } - public HomekitLightbulbImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater) { - super(taggedItem, itemRegistry, updater, SwitchItem.class); + @Override + public void unsubscribeLightbulbPowerState() { + unsubscribe(HomekitCharacteristicType.ON_STATE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLockImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLockImpl.java index 36bfe5f042357..b0c8b9fbad8f5 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLockImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitLockImpl.java @@ -12,94 +12,103 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; -import org.eclipse.smarthome.core.items.ItemRegistry; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.items.Item; import org.eclipse.smarthome.core.library.items.SwitchItem; import org.eclipse.smarthome.core.library.types.OnOffType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.LockableLockMechanism; -import io.github.hapjava.accessories.properties.LockMechanismState; +import io.github.hapjava.accessories.LockMechanismAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.lock.LockCurrentStateEnum; +import io.github.hapjava.characteristics.impl.lock.LockTargetStateEnum; +import io.github.hapjava.services.impl.LockMechanismService; /** - * Implements the support of Lock accessories, mapping them to OpenHAB Switch type + * Implements the support of Lock accessories, mapping them to OpenHAB Switch type * - * @author blafois - Support for additional accessory type. + * @author blafois - Initial contribution. * */ -public class HomekitLockImpl extends AbstractHomekitAccessoryImpl implements LockableLockMechanism { +public class HomekitLockImpl extends AbstractHomekitAccessoryImpl implements LockMechanismAccessory { - public HomekitLockImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, HomekitAccessoryUpdater updater) { - super(taggedItem, itemRegistry, updater, SwitchItem.class); + public HomekitLockImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + getServices().add(new LockMechanismService(this)); } @Override - public CompletableFuture getCurrentMechanismState() { - OnOffType state = getItem().getStateAs(OnOffType.class); - - if (state == OnOffType.OFF) { - return CompletableFuture.completedFuture(LockMechanismState.SECURED); - } else if (state == OnOffType.ON) { - return CompletableFuture.completedFuture(LockMechanismState.UNSECURED); + public CompletableFuture getLockCurrentState() { + @Nullable + OnOffType state = getStateAs(HomekitCharacteristicType.LOCK_CURRENT_STATE, OnOffType.class); + if (state != null) { + return CompletableFuture.completedFuture( + state == OnOffType.OFF ? LockCurrentStateEnum.SECURED : LockCurrentStateEnum.UNSECURED); } - - return CompletableFuture.completedFuture(LockMechanismState.UNKNOWN); + return CompletableFuture.completedFuture(LockCurrentStateEnum.UNKNOWN); } @Override - public void subscribeCurrentMechanismState(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + public CompletableFuture getLockTargetState() { + @Nullable + OnOffType state = getStateAs(HomekitCharacteristicType.LOCK_TARGET_STATE, OnOffType.class); + if (state != null) { + return CompletableFuture.completedFuture( + state == OnOffType.OFF ? LockTargetStateEnum.SECURED : LockTargetStateEnum.UNSECURED); + } + return CompletableFuture.completedFuture(LockTargetStateEnum.UNSECURED); + // Apple HAP specification has onyl SECURED and UNSECURED values for lock target state. + // unknown does not supported for target state. } @Override - public void unsubscribeCurrentMechanismState() { - getUpdater().unsubscribe(getItem()); + public CompletableFuture setLockTargetState(final LockTargetStateEnum state) { + @Nullable + Item item = getItem(HomekitCharacteristicType.LOCK_TARGET_STATE, SwitchItem.class); + if (item != null) + switch (state) { + case SECURED: + // Close the door + if (item instanceof SwitchItem) { + ((SwitchItem) item).send(OnOffType.OFF); + } + break; + case UNSECURED: + // Open the door + if (item instanceof SwitchItem) { + ((SwitchItem) item).send(OnOffType.ON); + } + break; + default: + break; + } + return CompletableFuture.completedFuture(null); } @Override - public void setTargetMechanismState(LockMechanismState state) throws Exception { - switch (state) { - case SECURED: - // Close the door - if (getItem() instanceof SwitchItem) { - ((SwitchItem) getItem()).send(OnOffType.OFF); - } - break; - case UNSECURED: - // Open the door - if (getItem() instanceof SwitchItem) { - ((SwitchItem) getItem()).send(OnOffType.ON); - } - break; - default: - break; - } + public void subscribeLockCurrentState(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.LOCK_CURRENT_STATE, callback); } @Override - public CompletableFuture getTargetMechanismState() { - OnOffType state = getItem().getStateAs(OnOffType.class); - - if (state == OnOffType.OFF) { - return CompletableFuture.completedFuture(LockMechanismState.SECURED); - } else if (state == OnOffType.ON) { - return CompletableFuture.completedFuture(LockMechanismState.UNSECURED); - } - - return CompletableFuture.completedFuture(LockMechanismState.UNKNOWN); + public void unsubscribeLockCurrentState() { + unsubscribe(HomekitCharacteristicType.LOCK_CURRENT_STATE); } @Override - public void subscribeTargetMechanismState(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + public void subscribeLockTargetState(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.LOCK_TARGET_STATE, callback); } @Override - public void unsubscribeTargetMechanismState() { - getUpdater().unsubscribe(getItem()); + public void unsubscribeLockTargetState() { + unsubscribe(HomekitCharacteristicType.LOCK_TARGET_STATE); } - } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitMotionSensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitMotionSensorImpl.java index 61f2d3cf7186c..1aaa7b599bb7e 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitMotionSensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitMotionSensorImpl.java @@ -12,63 +12,51 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.OpenClosedType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import org.openhab.io.homekit.internal.battery.BatteryStatus; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.BatteryStatusAccessory; -import io.github.hapjava.accessories.MotionSensor; +import io.github.hapjava.accessories.MotionSensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.impl.MotionSensorService; /** * * @author Tim Harper - Initial contribution */ -public class HomekitMotionSensorImpl extends AbstractHomekitAccessoryImpl - implements MotionSensor, BatteryStatusAccessory { - private BatteryStatus batteryStatus; - private BooleanItemReader motionSensedReader; +public class HomekitMotionSensorImpl extends AbstractHomekitAccessoryImpl implements MotionSensorAccessory { + private final BooleanItemReader motionSensedReader; - public HomekitMotionSensorImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, BatteryStatus batteryStatus) { - super(taggedItem, itemRegistry, updater, GenericItem.class); - this.motionSensedReader = new BooleanItemReader(taggedItem.getItem(), OnOffType.ON, OpenClosedType.OPEN); - this.batteryStatus = batteryStatus; + public HomekitMotionSensorImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.motionSensedReader = new BooleanItemReader( + getItem(HomekitCharacteristicType.MOTION_DETECTED_STATE, GenericItem.class), OnOffType.ON, + OpenClosedType.OPEN); + + getServices().add(new MotionSensorService(this)); } @Override public CompletableFuture getMotionDetected() { - return CompletableFuture.completedFuture(motionSensedReader.getValue()); + return CompletableFuture + .completedFuture((this.motionSensedReader.getValue() != null) ? motionSensedReader.getValue() : false); } @Override public void subscribeMotionDetected(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.MOTION_DETECTED_STATE, callback); } @Override public void unsubscribeMotionDetected() { - getUpdater().unsubscribe(getItem()); - } - - @Override - public CompletableFuture getLowBatteryState() { - return CompletableFuture.completedFuture(batteryStatus.isLow()); - } - - @Override - public void subscribeLowBatteryState(HomekitCharacteristicChangeCallback callback) { - batteryStatus.subscribe(getUpdater(), callback); - } - - @Override - public void unsubscribeLowBatteryState() { - batteryStatus.unsubscribe(getUpdater()); + unsubscribe(HomekitCharacteristicType.MOTION_DETECTED_STATE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOccupancySensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOccupancySensorImpl.java index aa4fb2c64dac8..b2b6761c4c496 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOccupancySensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOccupancySensorImpl.java @@ -12,63 +12,52 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.OpenClosedType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import org.openhab.io.homekit.internal.battery.BatteryStatus; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.BatteryStatusAccessory; -import io.github.hapjava.accessories.OccupancySensor; +import io.github.hapjava.accessories.OccupancySensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.occupancysensor.OccupancyDetectedEnum; +import io.github.hapjava.services.impl.OccupancySensorService; /** * * @author Tim Harper - Initial contribution */ -public class HomekitOccupancySensorImpl extends AbstractHomekitAccessoryImpl - implements OccupancySensor, BatteryStatusAccessory { - private BatteryStatus batteryStatus; - private BooleanItemReader occupancySensedReader; - - public HomekitOccupancySensorImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, BatteryStatus batteryStatus) { - super(taggedItem, itemRegistry, updater, GenericItem.class); - this.occupancySensedReader = new BooleanItemReader(taggedItem.getItem(), OnOffType.ON, OpenClosedType.OPEN); - this.batteryStatus = batteryStatus; +public class HomekitOccupancySensorImpl extends AbstractHomekitAccessoryImpl implements OccupancySensorAccessory { + private final BooleanItemReader occupancySensedReader; + + public HomekitOccupancySensorImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.occupancySensedReader = new BooleanItemReader( + getItem(HomekitCharacteristicType.OCCUPANCY_DETECTED_STATE, GenericItem.class), OnOffType.ON, + OpenClosedType.OPEN); + getServices().add(new OccupancySensorService(this)); } @Override - public CompletableFuture getOccupancyDetected() { - return CompletableFuture.completedFuture(occupancySensedReader.getValue()); + public CompletableFuture getOccupancyDetected() { + return (this.occupancySensedReader.getValue() != null && this.occupancySensedReader.getValue()) + ? CompletableFuture.completedFuture(OccupancyDetectedEnum.DETECTED) + : CompletableFuture.completedFuture(OccupancyDetectedEnum.NOT_DETECTED); } @Override public void subscribeOccupancyDetected(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.OCCUPANCY_DETECTED_STATE, callback); } @Override public void unsubscribeOccupancyDetected() { - getUpdater().unsubscribe(getItem()); - } - - @Override - public CompletableFuture getLowBatteryState() { - return CompletableFuture.completedFuture(batteryStatus.isLow()); - } - - @Override - public void subscribeLowBatteryState(HomekitCharacteristicChangeCallback callback) { - batteryStatus.subscribe(getUpdater(), callback); - } - - @Override - public void unsubscribeLowBatteryState() { - batteryStatus.unsubscribe(getUpdater()); + unsubscribe(HomekitCharacteristicType.OCCUPANCY_DETECTED_STATE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOutletImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOutletImpl.java new file mode 100644 index 0000000000000..d73cb702c484e --- /dev/null +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitOutletImpl.java @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.io.homekit.internal.accessories; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.smarthome.core.items.GenericItem; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; +import org.openhab.io.homekit.internal.HomekitTaggedItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.hapjava.accessories.OutletAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.impl.OutletService; + +/** + * + * @author Eugen Freiter - Initial contribution + */ +public class HomekitOutletImpl extends AbstractHomekitAccessoryImpl implements OutletAccessory { + private final Logger logger = LoggerFactory.getLogger(HomekitOutletImpl.class); + + private final BooleanItemReader inUseReader; + private final BooleanItemReader onReader; + + public HomekitOutletImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.inUseReader = new BooleanItemReader(getItem(HomekitCharacteristicType.INUSE_STATUS, GenericItem.class), + OnOffType.ON, OpenClosedType.OPEN); + this.onReader = new BooleanItemReader(getItem(HomekitCharacteristicType.ON_STATE, GenericItem.class), + OnOffType.ON, OpenClosedType.OPEN); + getServices().add(new OutletService(this)); + } + + @Override + public CompletableFuture getPowerState() { + return CompletableFuture.completedFuture(this.onReader.getValue() != null && this.onReader.getValue()); + } + + @Override + public CompletableFuture getOutletInUse() { + return CompletableFuture.completedFuture(this.inUseReader.getValue() != null && this.onReader.getValue()); + } + + @Override + public CompletableFuture setPowerState(final boolean state) throws Exception { + this.onReader.setValue(state); + return CompletableFuture.completedFuture(null); + } + + @Override + public void subscribePowerState(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.ON_STATE, callback); + } + + @Override + public void subscribeOutletInUse(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.INUSE_STATUS, callback); + } + + @Override + public void unsubscribePowerState() { + unsubscribe(HomekitCharacteristicType.ON_STATE); + } + + @Override + public void unsubscribeOutletInUse() { + unsubscribe(HomekitCharacteristicType.INUSE_STATUS); + } +} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSecuritySystemImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSecuritySystemImpl.java new file mode 100644 index 0000000000000..f63f1ccae479f --- /dev/null +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSecuritySystemImpl.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.io.homekit.internal.accessories; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.library.items.StringItem; +import org.eclipse.smarthome.core.library.types.StringType; +import org.eclipse.smarthome.core.types.State; +import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; +import org.openhab.io.homekit.internal.HomekitTaggedItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.hapjava.accessories.SecuritySystemAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.securitysystem.CurrentSecuritySystemStateEnum; +import io.github.hapjava.characteristics.impl.securitysystem.TargetSecuritySystemStateEnum; +import io.github.hapjava.services.impl.SecuritySystemService; + +/** + * Implements SecuritySystem as a GroupedAccessory made up of multiple items: + *
    + *
  • CurrentSecuritySystemState: String type
  • + *
  • TargetSecuritySystemState: String type
  • + *
+ * + * @author Cody Cutrer - Initial contribution + */ +public class HomekitSecuritySystemImpl extends AbstractHomekitAccessoryImpl implements SecuritySystemAccessory { + private final Logger logger = LoggerFactory.getLogger(HomekitSecuritySystemImpl.class); + + public HomekitSecuritySystemImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + getServices().add(new SecuritySystemService(this)); + } + + @Override + public CompletableFuture getCurrentSecuritySystemState() { + CurrentSecuritySystemStateEnum state; + final @Nullable State itemState = getStateAs(HomekitCharacteristicType.SECURITY_SYSTEM_CURRENT_STATE, + StringType.class); + if (itemState != null) { + String stringValue = itemState.toString(); + switch (stringValue.toUpperCase()) { + case "DISARMED": + state = CurrentSecuritySystemStateEnum.DISARMED; + break; + case "AWAY_ARM": + state = CurrentSecuritySystemStateEnum.AWAY_ARM; + break; + case "STAY_ARM": + state = CurrentSecuritySystemStateEnum.STAY_ARM; + break; + case "NIGHT_ARM": + state = CurrentSecuritySystemStateEnum.NIGHT_ARM; + break; + case "TRIGGERED": + state = CurrentSecuritySystemStateEnum.TRIGGERED; + break; + case "UNDEF": + case "NULL": + logger.warn("Security system target state not available. Relaying value of DISARM to HomeKit"); + state = CurrentSecuritySystemStateEnum.DISARMED; + break; + default: + logger.warn( + "Unrecognized security system target state: {}. Expected DISARM, AWAY_ARM, STAY_ARM, NIGHT_ARM strings in value.", + stringValue); + state = CurrentSecuritySystemStateEnum.DISARMED; + break; + } + } else { + logger.warn("Security system target state not available. Relaying value of DISARM to HomeKit"); + state = CurrentSecuritySystemStateEnum.DISARMED; + } + return CompletableFuture.completedFuture(state); + } + + @Override + public void setTargetSecuritySystemState(final TargetSecuritySystemStateEnum state) { + final @Nullable StringItem item = getItem(HomekitCharacteristicType.SECURITY_SYSTEM_TARGET_STATE, + StringItem.class); + if (item != null) + item.send(new StringType(state.toString())); + else + logger.warn("Item for target security state at accessory {} not found.", this.getName()); + } + + @Override + public CompletableFuture getTargetSecuritySystemState() { + TargetSecuritySystemStateEnum state; + + final @Nullable State itemState = getStateAs(HomekitCharacteristicType.SECURITY_SYSTEM_TARGET_STATE, + StringType.class); + if (itemState != null) { + String stringValue = itemState.toString(); + switch (stringValue.toUpperCase()) { + case "DISARM": + state = TargetSecuritySystemStateEnum.DISARM; + break; + case "AWAY_ARM": + state = TargetSecuritySystemStateEnum.AWAY_ARM; + break; + case "STAY_ARM": + state = TargetSecuritySystemStateEnum.STAY_ARM; + break; + case "NIGHT_ARM": + state = TargetSecuritySystemStateEnum.NIGHT_ARM; + break; + case "UNDEF": + case "NULL": + logger.warn("Security system target state not available. Relaying value of DISARM to HomeKit"); + state = TargetSecuritySystemStateEnum.DISARM; + break; + default: + logger.warn( + "Unrecognized security system target state: {}. Expected DISARM, AWAY_ARM, STAY_ARM, NIGHT_ARM strings in value.", + stringValue); + state = TargetSecuritySystemStateEnum.DISARM; + break; + + } + } else { + logger.warn("Security system target state not available. Relaying value of DISARM to HomeKit"); + state = TargetSecuritySystemStateEnum.DISARM; + } + return CompletableFuture.completedFuture(state); + } + + @Override + public void subscribeCurrentSecuritySystemState(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.SECURITY_SYSTEM_CURRENT_STATE, callback); + } + + @Override + public void unsubscribeCurrentSecuritySystemState() { + unsubscribe(HomekitCharacteristicType.SECURITY_SYSTEM_CURRENT_STATE); + } + + @Override + public void subscribeTargetSecuritySystemState(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.SECURITY_SYSTEM_TARGET_STATE, callback); + } + + @Override + public void unsubscribeTargetSecuritySystemState() { + unsubscribe(HomekitCharacteristicType.SECURITY_SYSTEM_TARGET_STATE); + } +} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSmokeSensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSmokeSensorImpl.java index e8efb734d68cc..51905acaa2d7d 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSmokeSensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSmokeSensorImpl.java @@ -12,73 +12,53 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; -import org.eclipse.jdt.annotation.NonNull; import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.types.OnOffType; import org.eclipse.smarthome.core.library.types.OpenClosedType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import org.openhab.io.homekit.internal.battery.BatteryStatus; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.BatteryStatusAccessory; -import io.github.hapjava.accessories.SmokeSensor; -import io.github.hapjava.accessories.properties.SmokeDetectedState; +import io.github.hapjava.accessories.SmokeSensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.smokesensor.SmokeDetectedStateEnum; +import io.github.hapjava.services.impl.SmokeSensorService; /** * * @author Cody Cutrer - Initial contribution */ -public class HomekitSmokeSensorImpl extends AbstractHomekitAccessoryImpl - implements SmokeSensor, BatteryStatusAccessory { +public class HomekitSmokeSensorImpl extends AbstractHomekitAccessoryImpl implements SmokeSensorAccessory { - @NonNull - private BatteryStatus batteryStatus; + private final BooleanItemReader smokeDetectedReader; - private BooleanItemReader smokeDetectedReader; - - public HomekitSmokeSensorImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, BatteryStatus batteryStatus) { - super(taggedItem, itemRegistry, updater, GenericItem.class); - - this.smokeDetectedReader = new BooleanItemReader(taggedItem.getItem(), OnOffType.ON, OpenClosedType.OPEN); - this.batteryStatus = batteryStatus; + public HomekitSmokeSensorImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.smokeDetectedReader = new BooleanItemReader( + getItem(HomekitCharacteristicType.SMOKE_DETECTED_STATE, GenericItem.class), OnOffType.ON, + OpenClosedType.OPEN); + this.getServices().add(new SmokeSensorService(this)); } @Override - public CompletableFuture getSmokeDetectedState() { + public CompletableFuture getSmokeDetectedState() { Boolean state = this.smokeDetectedReader.getValue(); - if (state == null) { - return CompletableFuture.completedFuture(null); - } - return CompletableFuture.completedFuture(state ? SmokeDetectedState.DETECTED : SmokeDetectedState.NOT_DETECTED); + return CompletableFuture.completedFuture( + (state != null && state) ? SmokeDetectedStateEnum.DETECTED : SmokeDetectedStateEnum.NOT_DETECTED); } @Override public void subscribeSmokeDetectedState(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.SMOKE_DETECTED_STATE, callback); } @Override public void unsubscribeSmokeDetectedState() { - getUpdater().unsubscribe(getItem()); - } - - @Override - public CompletableFuture getLowBatteryState() { - return CompletableFuture.completedFuture(batteryStatus.isLow()); - } - - @Override - public void subscribeLowBatteryState(HomekitCharacteristicChangeCallback callback) { - batteryStatus.subscribe(getUpdater(), callback); - } - - @Override - public void unsubscribeLowBatteryState() { - batteryStatus.unsubscribe(getUpdater()); + unsubscribe(HomekitCharacteristicType.SMOKE_DETECTED_STATE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSpeakerImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSpeakerImpl.java new file mode 100644 index 0000000000000..8383c9a6129a7 --- /dev/null +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSpeakerImpl.java @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.io.homekit.internal.accessories; + +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.smarthome.core.items.GenericItem; +import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; +import org.openhab.io.homekit.internal.HomekitTaggedItem; + +import io.github.hapjava.accessories.SpeakerAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.impl.SpeakerService; + +/** + * Implements Speaker using an Item that provides an On/Off state for Mute. + * + * @author Eugen Freiter - Initial contribution + */ +public class HomekitSpeakerImpl extends AbstractHomekitAccessoryImpl implements SpeakerAccessory { + private final BooleanItemReader muteReader; + + public HomekitSpeakerImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.muteReader = new BooleanItemReader(getItem(HomekitCharacteristicType.MUTE, GenericItem.class), + OnOffType.ON, OpenClosedType.OPEN); + getServices().add(new SpeakerService(this)); + } + + @Override + public CompletableFuture isMuted() { + return CompletableFuture.completedFuture(this.muteReader.getValue() != null && this.muteReader.getValue()); + } + + @Override + public CompletableFuture setMute(final boolean state) { + this.muteReader.setValue(state); + return CompletableFuture.completedFuture(null); + } + + @Override + public void subscribeMuteState(final HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.MUTE, callback); + } + + @Override + public void unsubscribeMuteState() { + unsubscribe(HomekitCharacteristicType.MUTE); + } +} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSwitchImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSwitchImpl.java index 796e552e2d25d..d1dd579626bb4 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSwitchImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitSwitchImpl.java @@ -12,54 +12,59 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; import org.eclipse.smarthome.core.items.GenericItem; import org.eclipse.smarthome.core.items.GroupItem; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.items.SwitchItem; import org.eclipse.smarthome.core.library.types.OnOffType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.Switch; +import io.github.hapjava.accessories.SwitchAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.impl.SwitchService; /** * Implements Switch using an Item that provides an On/Off state. * * @author Andy Lintner - Initial contribution */ -public class HomekitSwitchImpl extends AbstractHomekitAccessoryImpl implements Switch { +public class HomekitSwitchImpl extends AbstractHomekitAccessoryImpl implements SwitchAccessory { - public HomekitSwitchImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, HomekitAccessoryUpdater updater) { - super(taggedItem, itemRegistry, updater, SwitchItem.class); + public HomekitSwitchImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + getServices().add(new SwitchService(this)); } @Override public CompletableFuture getSwitchState() { - OnOffType state = getItem().getStateAs(OnOffType.class); + OnOffType state = getStateAs(HomekitCharacteristicType.ON_STATE, OnOffType.class); return CompletableFuture.completedFuture(state == OnOffType.ON); } @Override - public CompletableFuture setSwitchState(boolean state) throws Exception { - GenericItem item = getItem(); + public CompletableFuture setSwitchState(boolean state) { + GenericItem item = getItem(HomekitCharacteristicType.ON_STATE, GenericItem.class); if (item instanceof SwitchItem) { - ((SwitchItem) item).send(state ? OnOffType.ON : OnOffType.OFF); + ((SwitchItem) item).send(OnOffType.from(state)); } else if (item instanceof GroupItem) { - ((GroupItem) item).send(state ? OnOffType.ON : OnOffType.OFF); + ((GroupItem) item).send(OnOffType.from(state)); } return CompletableFuture.completedFuture(null); } @Override public void subscribeSwitchState(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.ON_STATE, callback); } @Override public void unsubscribeSwitchState() { - getUpdater().unsubscribe(getItem()); + unsubscribe(HomekitCharacteristicType.ON_STATE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java index 9f82d1065a798..31e5777c6c0a0 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitTemperatureSensorImpl.java @@ -12,47 +12,47 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; -import org.eclipse.smarthome.core.items.ItemRegistry; -import org.eclipse.smarthome.core.library.items.NumberItem; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.types.DecimalType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.TemperatureSensor; +import io.github.hapjava.accessories.TemperatureSensorAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.services.impl.TemperatureSensorService; /** * Implements a HomeKit TemperatureSensor using a NumberItem * * @author Andy Lintner - Initial contribution */ -class HomekitTemperatureSensorImpl extends AbstractTemperatureHomekitAccessoryImpl - implements TemperatureSensor { +class HomekitTemperatureSensorImpl extends AbstractHomekitAccessoryImpl implements TemperatureSensorAccessory { - public HomekitTemperatureSensorImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, HomekitSettings settings) { - super(taggedItem, itemRegistry, updater, settings, NumberItem.class); + public HomekitTemperatureSensorImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + getServices().add(new TemperatureSensorService(this)); } @Override public CompletableFuture getCurrentTemperature() { - DecimalType state = getItem().getStateAs(DecimalType.class); - if (state == null) { - return CompletableFuture.completedFuture(null); - } - return CompletableFuture.completedFuture(convertToCelsius(state.doubleValue())); + @Nullable + DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE, DecimalType.class); + return CompletableFuture.completedFuture(state != null ? convertToCelsius(state.doubleValue()) : 0.0); } @Override public void subscribeCurrentTemperature(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE, callback); } @Override public void unsubscribeCurrentTemperature() { - getUpdater().unsubscribe(getItem()); + unsubscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java index deb64643658f4..495bffbdc8f79 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitThermostatImpl.java @@ -13,21 +13,14 @@ package org.openhab.io.homekit.internal.accessories; import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; +import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.items.GroupItem; -import org.eclipse.smarthome.core.items.Item; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.items.NumberItem; import org.eclipse.smarthome.core.library.items.StringItem; import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.StringType; -import org.eclipse.smarthome.core.types.State; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; import org.openhab.io.homekit.internal.HomekitCharacteristicType; import org.openhab.io.homekit.internal.HomekitSettings; @@ -35,9 +28,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.properties.ThermostatMode; -import io.github.hapjava.accessories.thermostat.BasicThermostat; +import io.github.hapjava.accessories.ThermostatAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.thermostat.CurrentHeatingCoolingStateEnum; +import io.github.hapjava.characteristics.impl.thermostat.TargetHeatingCoolingStateEnum; +import io.github.hapjava.characteristics.impl.thermostat.TemperatureDisplayUnitEnum; +import io.github.hapjava.services.impl.ThermostatService; /** * Implements Thermostat as a GroupedAccessory made up of multiple items: @@ -50,154 +46,108 @@ * * @author Andy Lintner - Initial contribution */ -class HomekitThermostatImpl extends AbstractTemperatureHomekitAccessoryImpl implements BasicThermostat { - private final HomekitSettings settings; - - private @NonNull NumberItem currentTemperatureItem; - private @NonNull StringItem targetHeatingCoolingModeItem; - private @Nullable StringItem currentHeatingCoolingModeItem; - private @NonNull NumberItem targetTemperatureItem; - +class HomekitThermostatImpl extends AbstractHomekitAccessoryImpl implements ThermostatAccessory { private Logger logger = LoggerFactory.getLogger(HomekitThermostatImpl.class); - @SuppressWarnings("deprecation") - public HomekitThermostatImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater, HomekitSettings settings, Item currentTemperatureItem, - Map origCharacteristicItems) throws IncompleteAccessoryException { - super(taggedItem, itemRegistry, updater, settings, GroupItem.class); - - HashMap characteristicItems = new HashMap<>(origCharacteristicItems); - this.settings = settings; - - if (currentTemperatureItem instanceof NumberItem) { - this.currentTemperatureItem = (NumberItem) currentTemperatureItem; - } else { - throw new IncompleteAccessoryException(currentTemperatureItem.getUID() - + "tagged as thermostat currentTemperatureItem has wrong item type (NumberItem needed)"); - } - - Item targetHeatingCoolingModeItem = getItemWithDeprecation(characteristicItems, - HomekitCharacteristicType.TARGET_HEATING_COOLING_MODE, - HomekitCharacteristicType.OLD_TARGET_HEATING_COOLING_MODE).orElseThrow( - () -> new IncompleteAccessoryException(HomekitCharacteristicType.TARGET_HEATING_COOLING_MODE)); - if (targetHeatingCoolingModeItem instanceof StringItem) { - this.targetHeatingCoolingModeItem = (StringItem) targetHeatingCoolingModeItem; - } else { - throw new IncompleteAccessoryException(targetHeatingCoolingModeItem.getUID() - + " tagged as thermostat targetHeatingCoolingMode has wrong item type (String needed)"); - } - - Item targetTemperatureItem = getItemWithDeprecation(characteristicItems, - HomekitCharacteristicType.TARGET_TEMPERATURE, HomekitCharacteristicType.OLD_TARGET_TEMPERATURE) - .orElseThrow( - () -> new IncompleteAccessoryException(HomekitCharacteristicType.TARGET_TEMPERATURE)); - if (targetTemperatureItem instanceof NumberItem) { - this.targetTemperatureItem = (NumberItem) targetTemperatureItem; - } else { - throw new IncompleteAccessoryException(targetTemperatureItem.getUID() - + " tagged as thermostat targetTemperature has wrong item type (Number needed)"); - } - - Item currentHeatingCoolingModeItem = characteristicItems - .remove(HomekitCharacteristicType.CURRENT_HEATING_COOLING_STATE); - if (currentHeatingCoolingModeItem instanceof StringItem || currentHeatingCoolingModeItem == null) { - this.currentHeatingCoolingModeItem = (StringItem) currentHeatingCoolingModeItem; - } else { - throw new IncompleteAccessoryException(currentHeatingCoolingModeItem.getUID() - + " tagged as thermostat currentHeatingCoolingMode has wrong item type (String needed)"); - } - - characteristicItems.entrySet().stream().forEach(entry -> { - logger.warn("Item {} has unrecognized thermostat characteristic: {}", entry.getValue().getUID(), - entry.getKey().getTag()); - }); - } - - private Optional getItemWithDeprecation(HashMap characteristicItems, - HomekitCharacteristicType currentTag, HomekitCharacteristicType deprecatedTag) { - Optional targetTempItem = Optional.ofNullable(characteristicItems.remove(currentTag)); - if (!targetTempItem.isPresent()) { - targetTempItem = Optional.ofNullable(characteristicItems.remove(deprecatedTag)); - targetTempItem.ifPresent(item -> { - logger.warn("The tag {} has been renamed to {}; please update your things, accordingly", - deprecatedTag.getTag(), currentTag.getTag()); - }); - } - return targetTempItem; + public HomekitThermostatImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.getServices().add(new ThermostatService(this)); } @Override - public CompletableFuture getCurrentMode() { + public CompletableFuture getCurrentState() { + final HomekitSettings settings = getSettings(); String stringValue = settings.thermostatCurrentModeOff; - if (currentHeatingCoolingModeItem != null) { - stringValue = currentHeatingCoolingModeItem.getState().toString(); + final Optional characteristic = getCharacteristic( + HomekitCharacteristicType.CURRENT_HEATING_COOLING_STATE); + if (characteristic.isPresent()) { + stringValue = characteristic.get().getItem().getState().toString(); + } else { + logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.CURRENT_HEATING_COOLING_STATE); } - ThermostatMode mode; + + CurrentHeatingCoolingStateEnum mode; if (stringValue.equalsIgnoreCase(settings.thermostatCurrentModeCooling)) { - mode = ThermostatMode.COOL; + mode = CurrentHeatingCoolingStateEnum.COOL; } else if (stringValue.equalsIgnoreCase(settings.thermostatCurrentModeHeating)) { - mode = ThermostatMode.HEAT; + mode = CurrentHeatingCoolingStateEnum.HEAT; } else if (stringValue.equalsIgnoreCase(settings.thermostatCurrentModeOff)) { - mode = ThermostatMode.OFF; + mode = CurrentHeatingCoolingStateEnum.OFF; } else if (stringValue.equals("UNDEF") || stringValue.equals("NULL")) { - logger.debug("Heating cooling target mode not available. Relaying value of OFF to Homekit"); - mode = ThermostatMode.OFF; + logger.warn("Heating cooling target mode not available. Relaying value of OFF to Homekit"); + mode = CurrentHeatingCoolingStateEnum.OFF; } else { - logger.error("Unrecognized heatingCoolingCurrentMode: {}. Expected {}, {}, or {} strings in value.", + logger.warn("Unrecognized heatingCoolingCurrentMode: {}. Expected {}, {}, or {} strings in value.", stringValue, settings.thermostatCurrentModeCooling, settings.thermostatCurrentModeHeating, settings.thermostatCurrentModeOff); - mode = ThermostatMode.OFF; + mode = CurrentHeatingCoolingStateEnum.OFF; } return CompletableFuture.completedFuture(mode); } @Override public CompletableFuture getCurrentTemperature() { - DecimalType state = currentTemperatureItem.getStateAs(DecimalType.class); - if (state == null) { - return CompletableFuture.completedFuture(null); - } - return CompletableFuture.completedFuture(convertToCelsius(state.doubleValue())); + DecimalType state = getStateAs(HomekitCharacteristicType.CURRENT_TEMPERATURE, DecimalType.class); + return CompletableFuture.completedFuture(state != null ? convertToCelsius(state.doubleValue()) : 0.0); } @Override - public CompletableFuture getTargetMode() { - State state = targetHeatingCoolingModeItem.getState(); - ThermostatMode mode; + public CompletableFuture getTargetState() { + final HomekitSettings settings = getSettings(); + String stringValue = settings.thermostatTargetModeOff; + + final Optional characteristic = getCharacteristic( + HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE); + if (characteristic.isPresent()) { + stringValue = characteristic.get().getItem().getState().toString(); + } else { + logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE); + } + TargetHeatingCoolingStateEnum mode; - String stringValue = state.toString(); if (stringValue.equalsIgnoreCase(settings.thermostatTargetModeCool)) { - mode = ThermostatMode.COOL; + mode = TargetHeatingCoolingStateEnum.COOL; } else if (stringValue.equalsIgnoreCase(settings.thermostatTargetModeHeat)) { - mode = ThermostatMode.HEAT; + mode = TargetHeatingCoolingStateEnum.HEAT; } else if (stringValue.equalsIgnoreCase(settings.thermostatTargetModeAuto)) { - mode = ThermostatMode.AUTO; + mode = TargetHeatingCoolingStateEnum.AUTO; } else if (stringValue.equalsIgnoreCase(settings.thermostatTargetModeOff)) { - mode = ThermostatMode.OFF; + mode = TargetHeatingCoolingStateEnum.OFF; } else if (stringValue.equals("UNDEF") || stringValue.equals("NULL")) { - logger.debug("Heating cooling target mode not available. Relaying value of OFF to Homekit"); - mode = ThermostatMode.OFF; + logger.warn("Heating cooling target mode not available. Relaying value of OFF to Homekit"); + mode = TargetHeatingCoolingStateEnum.OFF; } else { logger.warn("Unrecognized heating cooling target mode: {}. Expected {}, {}, {}, or {} strings in value.", stringValue, settings.thermostatTargetModeCool, settings.thermostatTargetModeHeat, settings.thermostatTargetModeAuto, settings.thermostatTargetModeOff); - mode = ThermostatMode.OFF; + mode = TargetHeatingCoolingStateEnum.OFF; } return CompletableFuture.completedFuture(mode); } + @Override + public CompletableFuture getTemperatureDisplayUnit() { + return CompletableFuture + .completedFuture(getSettings().useFahrenheitTemperature ? TemperatureDisplayUnitEnum.FAHRENHEIT + : TemperatureDisplayUnitEnum.CELSIUS); + } + + @Override + public void setTemperatureDisplayUnit(final TemperatureDisplayUnitEnum value) throws Exception { + // TODO: add support for display unit change + } + @Override public CompletableFuture getTargetTemperature() { - DecimalType state = targetTemperatureItem.getStateAs(DecimalType.class); - if (state == null) { - return CompletableFuture.completedFuture(null); - } - return CompletableFuture.completedFuture(convertToCelsius(state.doubleValue())); + DecimalType state = getStateAs(HomekitCharacteristicType.TARGET_TEMPERATURE, DecimalType.class); + return CompletableFuture.completedFuture(state != null ? convertToCelsius(state.doubleValue()) : 0.0); } @Override - public void setTargetMode(ThermostatMode mode) throws Exception { + public void setTargetState(TargetHeatingCoolingStateEnum mode) { + final HomekitSettings settings = getSettings(); String modeString = null; switch (mode) { case AUTO: @@ -216,53 +166,74 @@ public void setTargetMode(ThermostatMode mode) throws Exception { modeString = settings.thermostatTargetModeOff; break; } - targetHeatingCoolingModeItem.send(new StringType(modeString)); + final Optional characteristic = getCharacteristic( + HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE); + if (characteristic.isPresent()) { + ((StringItem) characteristic.get().getItem()).send(new StringType(modeString)); + } else { + logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE); + } } @Override - public void setTargetTemperature(Double value) throws Exception { - targetTemperatureItem.send(new DecimalType(BigDecimal.valueOf(convertFromCelsius(value)))); + public void setTargetTemperature(Double value) { + final Optional characteristic = getCharacteristic( + HomekitCharacteristicType.TARGET_TEMPERATURE); + if (characteristic.isPresent()) { + ((NumberItem) characteristic.get().getItem()) + .send(new DecimalType(BigDecimal.valueOf(convertFromCelsius(value)))); + } else { + logger.warn("Missing mandatory characteristic {}", HomekitCharacteristicType.TARGET_TEMPERATURE); + } } @Override - public void subscribeCurrentMode(HomekitCharacteristicChangeCallback callback) { - if (currentHeatingCoolingModeItem != null) { - getUpdater().subscribe(currentHeatingCoolingModeItem, callback); - } + public void subscribeCurrentState(HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.CURRENT_HEATING_COOLING_STATE, callback); } @Override public void subscribeCurrentTemperature(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(currentTemperatureItem, callback); + subscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE, callback); } @Override - public void subscribeTargetMode(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(targetHeatingCoolingModeItem, callback); + public void subscribeTargetState(HomekitCharacteristicChangeCallback callback) { + subscribe(HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE, callback); } @Override public void subscribeTargetTemperature(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(targetTemperatureItem, callback); + subscribe(HomekitCharacteristicType.TARGET_TEMPERATURE, callback); + } + + @Override + public void subscribeTemperatureDisplayUnit(final HomekitCharacteristicChangeCallback callback) { + // TODO: add support for display unit change } @Override - public void unsubscribeCurrentMode() { - getUpdater().unsubscribe(targetHeatingCoolingModeItem); + public void unsubscribeCurrentState() { + unsubscribe(HomekitCharacteristicType.CURRENT_HEATING_COOLING_STATE); } @Override public void unsubscribeCurrentTemperature() { - getUpdater().unsubscribe(currentTemperatureItem); + unsubscribe(HomekitCharacteristicType.CURRENT_TEMPERATURE); + } + + @Override + public void unsubscribeTemperatureDisplayUnit() { + // TODO: add support for display unit change } @Override - public void unsubscribeTargetMode() { - getUpdater().unsubscribe(targetHeatingCoolingModeItem); + public void unsubscribeTargetState() { + unsubscribe(HomekitCharacteristicType.TARGET_HEATING_COOLING_STATE); } @Override public void unsubscribeTargetTemperature() { - getUpdater().unsubscribe(targetTemperatureItem); + unsubscribe(HomekitCharacteristicType.TARGET_TEMPERATURE); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitValveImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitValveImpl.java index ca76890f1805a..4433778241072 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitValveImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitValveImpl.java @@ -12,75 +12,197 @@ */ package org.openhab.io.homekit.internal.accessories; +import static org.openhab.io.homekit.internal.HomekitCharacteristicType.REMAINING_DURATION; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.items.GenericItem; -import org.eclipse.smarthome.core.items.ItemRegistry; import org.eclipse.smarthome.core.library.items.SwitchItem; +import org.eclipse.smarthome.core.library.types.DecimalType; import org.eclipse.smarthome.core.library.types.OnOffType; +import org.eclipse.smarthome.core.library.types.OpenClosedType; +import org.eclipse.smarthome.core.types.RefreshType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.Valve; -import io.github.hapjava.accessories.properties.ValveType; +import io.github.hapjava.accessories.ValveAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.common.ActiveEnum; +import io.github.hapjava.characteristics.impl.common.InUseEnum; +import io.github.hapjava.characteristics.impl.valve.RemainingDurationCharacteristic; +import io.github.hapjava.characteristics.impl.valve.ValveTypeEnum; +import io.github.hapjava.services.impl.ValveService; /** * * @author Tim Harper - Initial contribution + * @author Eugen Freiter - timer implementation */ -public class HomekitValveImpl extends AbstractHomekitAccessoryImpl implements Valve { - public HomekitValveImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, HomekitAccessoryUpdater updater) { - super(taggedItem, itemRegistry, updater, SwitchItem.class); +public class HomekitValveImpl extends AbstractHomekitAccessoryImpl implements ValveAccessory { + private final Logger logger = LoggerFactory.getLogger(HomekitValveImpl.class); + private static final String CONFIG_VALVE_TYPE = "homekitValveType"; + public static final String CONFIG_DEFAULT_DURATION = "homekitDefaultDuration"; + private static final String CONFIG_TIMER = "homekitTimer"; + + private static final Map CONFIG_VALVE_TYPE_MAPPING = new HashMap() { + { + put("GENERIC", ValveTypeEnum.GENERIC); + put("IRRIGATION", ValveTypeEnum.IRRIGATION); + put("SHOWER", ValveTypeEnum.SHOWER); + put("FAUCET", ValveTypeEnum.WATER_FAUCET); + } + }; + private final BooleanItemReader inUseReader; + private final BooleanItemReader activeReader; + private final ScheduledExecutorService timerService = Executors.newSingleThreadScheduledExecutor(); + private ScheduledFuture valveTimer; + private final boolean homekitTimer; + + public HomekitValveImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.inUseReader = new BooleanItemReader(getItem(HomekitCharacteristicType.INUSE_STATUS, GenericItem.class), + OnOffType.ON, OpenClosedType.OPEN); + this.activeReader = new BooleanItemReader(getItem(HomekitCharacteristicType.ACTIVE_STATUS, GenericItem.class), + OnOffType.ON, OpenClosedType.OPEN); + ValveService service = new ValveService(this); + getServices().add(service); + final String timerConfig = getAccessoryConfiguration(CONFIG_TIMER, ""); + homekitTimer = timerConfig.equalsIgnoreCase("yes") || timerConfig.equalsIgnoreCase("true"); + if (homekitTimer) { + addRemainingDurationCharacteristic(taggedItem, updater, service); + } } - @Override - public CompletableFuture getValveActive() { - OnOffType state = getItem().getStateAs(OnOffType.class); - if (state == null) { - return CompletableFuture.completedFuture(null); + private void addRemainingDurationCharacteristic(HomekitTaggedItem taggedItem, HomekitAccessoryUpdater updater, + ValveService service) { + logger.trace("addRemainingDurationCharacteristic for {}", taggedItem); + service.addOptionalCharacteristic(new RemainingDurationCharacteristic(() -> { + int remainingTime = 0; + ScheduledFuture future = valveTimer; + if (future != null && !future.isDone()) { + remainingTime = Math.toIntExact(future.getDelay(TimeUnit.SECONDS)); + } + return CompletableFuture.completedFuture(remainingTime); + }, HomekitCharacteristicFactory.getSubscriber(taggedItem, REMAINING_DURATION, updater), + HomekitCharacteristicFactory.getUnsubscriber(taggedItem, REMAINING_DURATION, updater))); + } + + /** + * return duration set by home app at corresponding OH items. if ot set, then return the default duration from + * configuration. + * + * @return duraion + */ + private int getDuration() { + int duration = 0; + final @Nullable DecimalType durationState = getStateAs(HomekitCharacteristicType.DURATION, DecimalType.class); + if (durationState != null) { + duration = durationState.intValue(); + } + return duration; + } + + private void startTimer() { + int duration = getDuration(); + logger.trace("start timer for duration {}", duration); + if (duration > 0) { + stopTimer(); + valveTimer = timerService.schedule(() -> { + logger.trace("valve timer is over. switching off the valve"); + switchOffValve(); + // let home app refresh the remaining duration, which is 0 + ((GenericItem) getRootAccessory().getItem()).send(RefreshType.REFRESH); + }, duration, TimeUnit.SECONDS); + logger.trace("started valve timer for {} seconds.", duration); + } else { + logger.debug("valve timer not started as duration = 0"); } - return CompletableFuture.completedFuture(state == OnOffType.ON); + } + + private void stopTimer() { + ScheduledFuture future = valveTimer; + if (future != null && !future.isDone()) { + future.cancel(true); + } + } + + @Override + public CompletableFuture getValveActive() { + return CompletableFuture.completedFuture( + (this.activeReader.getValue() != null && this.activeReader.getValue()) ? ActiveEnum.ACTIVE + : ActiveEnum.INACTIVE); } @Override - public CompletableFuture setValveActive(boolean state) throws Exception { - GenericItem item = getItem(); - if (item instanceof SwitchItem) { - ((SwitchItem) item).send(state ? OnOffType.ON : OnOffType.OFF); + public CompletableFuture setValveActive(ActiveEnum state) { + SwitchItem item = getItem(HomekitCharacteristicType.ACTIVE_STATUS, SwitchItem.class); + if (item != null) { + item.send(OnOffType.from(state == ActiveEnum.ACTIVE)); + if (homekitTimer) { + if ((state == ActiveEnum.ACTIVE)) { + startTimer(); + } else { + stopTimer(); + } + // let home app refresh the remaining duration + ((GenericItem) getRootAccessory().getItem()).send(RefreshType.REFRESH); + } } return CompletableFuture.completedFuture(null); } + private void switchOffValve() { + SwitchItem item = getItem(HomekitCharacteristicType.ACTIVE_STATUS, SwitchItem.class); + if (item != null) { + item.send(OnOffType.OFF); + } + } + @Override public void subscribeValveActive(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.ACTIVE_STATUS, callback); } @Override public void unsubscribeValveActive() { - getUpdater().unsubscribe(getItem()); + unsubscribe(HomekitCharacteristicType.ACTIVE_STATUS); } @Override - public CompletableFuture getValveInUse() { - return getValveActive(); + public CompletableFuture getValveInUse() { + return CompletableFuture + .completedFuture((this.inUseReader.getValue() != null && this.inUseReader.getValue()) ? InUseEnum.IN_USE + : InUseEnum.NOT_IN_USE); } @Override public void subscribeValveInUse(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), "inUse", callback); + subscribe(HomekitCharacteristicType.INUSE_STATUS, callback); } @Override public void unsubscribeValveInUse() { - getUpdater().unsubscribe(getItem(), "inUse"); + unsubscribe(HomekitCharacteristicType.INUSE_STATUS); } @Override - public CompletableFuture getValveType() { - // TODO - make this configurable; possibly via additional tags? ValveType:Generic etc - return CompletableFuture.completedFuture(ValveType.GENERIC); + public CompletableFuture getValveType() { + final String valveType = getAccessoryConfiguration(CONFIG_VALVE_TYPE, "GENERIC"); + ValveTypeEnum type = CONFIG_VALVE_TYPE_MAPPING.get(valveType.toUpperCase()); + return CompletableFuture.completedFuture(type != null ? type : ValveTypeEnum.GENERIC); } @Override diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitWindowCoveringImpl.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitWindowCoveringImpl.java index c893f449c8784..3cecde71c6dc9 100644 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitWindowCoveringImpl.java +++ b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/accessories/HomekitWindowCoveringImpl.java @@ -12,42 +12,43 @@ */ package org.openhab.io.homekit.internal.accessories; +import java.util.List; import java.util.concurrent.CompletableFuture; -import org.eclipse.smarthome.core.items.ItemRegistry; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.smarthome.core.library.items.RollershutterItem; import org.eclipse.smarthome.core.library.types.PercentType; import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; +import org.openhab.io.homekit.internal.HomekitCharacteristicType; +import org.openhab.io.homekit.internal.HomekitSettings; import org.openhab.io.homekit.internal.HomekitTaggedItem; -import io.github.hapjava.HomekitCharacteristicChangeCallback; -import io.github.hapjava.accessories.BasicWindowCovering; -import io.github.hapjava.accessories.properties.WindowCoveringPositionState; +import io.github.hapjava.accessories.WindowCoveringAccessory; +import io.github.hapjava.characteristics.HomekitCharacteristicChangeCallback; +import io.github.hapjava.characteristics.impl.windowcovering.PositionStateEnum; +import io.github.hapjava.services.impl.WindowCoveringService; /** * * @author epike - Initial contribution */ -public class HomekitWindowCoveringImpl extends AbstractHomekitAccessoryImpl - implements BasicWindowCovering { +public class HomekitWindowCoveringImpl extends AbstractHomekitAccessoryImpl implements WindowCoveringAccessory { - public HomekitWindowCoveringImpl(HomekitTaggedItem taggedItem, ItemRegistry itemRegistry, - HomekitAccessoryUpdater updater) { - super(taggedItem, itemRegistry, updater, RollershutterItem.class); + public HomekitWindowCoveringImpl(HomekitTaggedItem taggedItem, List mandatoryCharacteristics, + HomekitAccessoryUpdater updater, HomekitSettings settings) throws IncompleteAccessoryException { + super(taggedItem, mandatoryCharacteristics, updater, settings); + this.getServices().add(new WindowCoveringService(this)); } @Override public CompletableFuture getCurrentPosition() { - PercentType value = getItem().getStateAs(PercentType.class); - if (value == null) { - return CompletableFuture.completedFuture(null); - } - return CompletableFuture.completedFuture(100 - value.intValue()); + PercentType value = getStateAs(HomekitCharacteristicType.CURRENT_POSITION, PercentType.class); + return CompletableFuture.completedFuture(value != null ? 100 - value.intValue() : 100); } @Override - public CompletableFuture getPositionState() { - return CompletableFuture.completedFuture(WindowCoveringPositionState.STOPPED); + public CompletableFuture getPositionState() { + return CompletableFuture.completedFuture(PositionStateEnum.STOPPED); } @Override @@ -57,13 +58,17 @@ public CompletableFuture getTargetPosition() { @Override public CompletableFuture setTargetPosition(int value) throws Exception { - ((RollershutterItem) getItem()).send(new PercentType(100 - value)); + final @Nullable RollershutterItem item = getItem(HomekitCharacteristicType.TARGET_POSITION, + RollershutterItem.class); + if (item != null) { + item.send(new PercentType(100 - value)); + } return CompletableFuture.completedFuture(null); } @Override public void subscribeCurrentPosition(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), callback); + subscribe(HomekitCharacteristicType.CURRENT_POSITION, callback); } @Override @@ -73,12 +78,12 @@ public void subscribePositionState(HomekitCharacteristicChangeCallback callback) @Override public void subscribeTargetPosition(HomekitCharacteristicChangeCallback callback) { - getUpdater().subscribe(getItem(), "targetPosition", callback); + subscribe(HomekitCharacteristicType.TARGET_POSITION, callback); } @Override public void unsubscribeCurrentPosition() { - getUpdater().unsubscribe(getItem()); + unsubscribe(HomekitCharacteristicType.CURRENT_POSITION); } @Override @@ -88,6 +93,6 @@ public void unsubscribePositionState() { @Override public void unsubscribeTargetPosition() { - getUpdater().unsubscribe(getItem(), "targetPosition"); + unsubscribe(HomekitCharacteristicType.CURRENT_POSITION); } } diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryLevelStatus.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryLevelStatus.java deleted file mode 100644 index 38031e5de72e5..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryLevelStatus.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.battery; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.items.NumberItem; -import org.eclipse.smarthome.core.library.types.DecimalType; -import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; - -import io.github.hapjava.HomekitCharacteristicChangeCallback; - -/** - * - * @author Tim Harper - Initial contribution - */ -@NonNullByDefault -public class BatteryLevelStatus implements BatteryStatus { - private NumberItem batteryLevelItem; - - BatteryLevelStatus(NumberItem batteryLevelItem) { - this.batteryLevelItem = batteryLevelItem; - } - - @Override - public @Nullable Boolean isLow() { - DecimalType level = batteryLevelItem.getStateAs(DecimalType.class); - - if (level == null) { - return null; - } else { - return level.intValue() < 10; - } - } - - @Override - public void subscribe(HomekitAccessoryUpdater updater, HomekitCharacteristicChangeCallback callback) { - updater.subscribe(batteryLevelItem, callback); - } - - @Override - public void unsubscribe(HomekitAccessoryUpdater updater) { - updater.unsubscribe(batteryLevelItem); - } -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryLowStatus.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryLowStatus.java deleted file mode 100644 index 71b5b727b7353..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryLowStatus.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.battery; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.library.items.SwitchItem; -import org.eclipse.smarthome.core.library.types.OnOffType; -import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; - -import io.github.hapjava.HomekitCharacteristicChangeCallback; - -/** - * - * @author Tim Harper - Initial contribution - */ -@NonNullByDefault -public class BatteryLowStatus implements BatteryStatus { - private SwitchItem batterySwitchItem; - - BatteryLowStatus(SwitchItem batterySwitchItem) { - this.batterySwitchItem = batterySwitchItem; - } - - @Override - @Nullable - public Boolean isLow() { - OnOffType state = batterySwitchItem.getStateAs(OnOffType.class); - if (state == null) { - return null; - } else { - return state == OnOffType.ON; - } - } - - @Override - public void subscribe(HomekitAccessoryUpdater updater, HomekitCharacteristicChangeCallback callback) { - updater.subscribe(batterySwitchItem, callback); - } - - @Override - public void unsubscribe(HomekitAccessoryUpdater updater) { - updater.unsubscribe(batterySwitchItem); - } -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryStatus.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryStatus.java deleted file mode 100644 index 27fb3fb5dddd0..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/BatteryStatus.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.battery; - -import java.util.Map; - -import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.smarthome.core.items.Item; -import org.eclipse.smarthome.core.library.items.NumberItem; -import org.eclipse.smarthome.core.library.items.SwitchItem; -import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; -import org.openhab.io.homekit.internal.HomekitCharacteristicType; - -import io.github.hapjava.HomekitCharacteristicChangeCallback; - -/** - * - * @author Tim Harper - Initial contribution - */ -@NonNullByDefault -public interface BatteryStatus { - @Nullable - Boolean isLow(); - - void subscribe(HomekitAccessoryUpdater updater, HomekitCharacteristicChangeCallback callback); - - public void unsubscribe(HomekitAccessoryUpdater updater); - - static BatteryStatus getFromCharacteristics(Map characteristicItems) { - if (characteristicItems.containsKey(HomekitCharacteristicType.BATTERY_LEVEL)) { - return new BatteryLevelStatus( - (NumberItem) characteristicItems.get(HomekitCharacteristicType.BATTERY_LEVEL)); - } else if (characteristicItems.containsKey(HomekitCharacteristicType.BATTERY_LOW_STATUS)) { - return new BatteryLowStatus( - (SwitchItem) characteristicItems.get(HomekitCharacteristicType.BATTERY_LOW_STATUS)); - } else { - return new NoBatteryStatus(); - } - } -} diff --git a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/NoBatteryStatus.java b/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/NoBatteryStatus.java deleted file mode 100644 index e4bcb8b3e1aee..0000000000000 --- a/bundles/org.openhab.io.homekit/src/main/java/org/openhab/io/homekit/internal/battery/NoBatteryStatus.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.homekit.internal.battery; - -import org.eclipse.jdt.annotation.NonNull; -import org.eclipse.jdt.annotation.Nullable; -import org.openhab.io.homekit.internal.HomekitAccessoryUpdater; - -import io.github.hapjava.HomekitCharacteristicChangeCallback; - -/** - * - * @author Tim Harper - Initial contribution - */ -public class NoBatteryStatus implements BatteryStatus { - @Override - public @Nullable Boolean isLow() { - return false; - } - - @Override - public void subscribe(@NonNull HomekitAccessoryUpdater updater, - @NonNull HomekitCharacteristicChangeCallback callback) { - // do nothing - } - - @Override - public void unsubscribe(@NonNull HomekitAccessoryUpdater updater) { - // do nothing - } -} diff --git a/bundles/org.openhab.io.homekit/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.io.homekit/src/main/resources/ESH-INF/config/config.xml index 55bd681453d39..08837e2bd4cab 100644 --- a/bundles/org.openhab.io.homekit/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.io.homekit/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,6 @@ - @@ -36,47 +37,61 @@ Defines the IP address of the network interface to expose the HomeKit integration on.
- + + + HomeKit start delay in case of item configuration differences. + 30 + Defines whether or not to direct HomeKit clients to use fahrenheit temperatures instead of celsius. false - + Word used to set the target heatingCoolingMode to COOL (if a thermostat is defined). CoolOn - + Word used to set the target heatingCoolingMode to HEAT (if a thermostat is defined). HeatOn - + Word used to set the target heatingCoolingMode to AUTO (if a thermostat is defined). Auto - + Word used to set the target heatingCoolingMode to OFF (if a thermostat is defined). Off - + - Value for setting target heatingCoolingCurrentMode to HEAT (IE: indicating that the heater is currently warming the home). + Value for setting target heatingCoolingCurrentMode to HEAT (IE: indicating that the heater is currently + warming the home). Heating - + - Value for setting target heatingCoolingCurrentMode to COOL (IE: indicating that the air condition is currently cooling the home). + Value for setting target heatingCoolingCurrentMode to COOL (IE: indicating that the air condition is + currently cooling the home). Cooling - + - Value for setting target heatingCoolingCurrentMode to OFF (IE: the hvac is currently idle, because the target temperature has been reached per the mode). + Value for setting target heatingCoolingCurrentMode to OFF (IE: the hvac is currently idle, because the + target temperature has been reached per the mode). Off diff --git a/bundles/org.openhab.io.hueemulation/README.md b/bundles/org.openhab.io.hueemulation/README.md index 6671f9e7d8159..b82aa26396a8c 100644 --- a/bundles/org.openhab.io.hueemulation/README.md +++ b/bundles/org.openhab.io.hueemulation/README.md @@ -114,7 +114,7 @@ This option allows you to override what addresses are used for the announcement. You can have multiple comma separated entries. ``` -org.openhab.hueemulation:discoveryIps=192.168.1.100,::FFFF:A9DB:0D85 +org.openhab.hueemulation:discoveryIp=192.168.1.100,::FFFF:A9DB:0D85 ``` The hue emulation service supports three types of emulated bulbs. diff --git a/bundles/org.openhab.io.hueemulation/pom.xml b/bundles/org.openhab.io.hueemulation/pom.xml index 2a3414c2a46f8..d3d20faf5611d 100644 --- a/bundles/org.openhab.io.hueemulation/pom.xml +++ b/bundles/org.openhab.io.hueemulation/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.hueemulation diff --git a/bundles/org.openhab.io.hueemulation/src/main/feature/feature.xml b/bundles/org.openhab.io.hueemulation/src/main/feature/feature.xml index 2b3db1b14baa9..412ffa8bdd8ce 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.hueemulation/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-upnp - openhab-core-automation - mvn:org.openhab.addons.bundles/org.openhab.io.hueemulation/${project.version} - + + openhab-runtime-base + openhab-transport-upnp + openhab-core-automation + mvn:org.openhab.addons.bundles/org.openhab.io.hueemulation/${project.version} + diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/ConfigStore.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/ConfigStore.java index 15af0ea76b1ab..37be77a66e07a 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/ConfigStore.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/ConfigStore.java @@ -193,8 +193,8 @@ public void modified(Map properties) { InetAddress configuredAddress = null; int networkPrefixLength = 24; // Default for most networks: 255.255.255.0 - if (config.discoveryIps != null) { - discoveryIps = Collections.unmodifiableSet(Stream.of(config.discoveryIps.split(",")).map(String::trim) + if (config.discoveryIp != null) { + discoveryIps = Collections.unmodifiableSet(Stream.of(config.discoveryIp.split(",")).map(String::trim) .map(this::byName).filter(e -> e != null).collect(Collectors.toSet())); } else { discoveryIps = new LinkedHashSet<>(); diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationConfig.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationConfig.java index b146b288f2b0d..49565ef370981 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationConfig.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationConfig.java @@ -38,7 +38,11 @@ public class HueEmulationConfig { /** Pairing timeout in seconds */ public int pairingTimeout = 60; - public @Nullable String discoveryIps; + /** + * The field discoveryIps was named discoveryIp in the frontend for some time and thus user probably + * have it in their local config saved under the non plural version. + */ + public @Nullable String discoveryIp; public int discoveryHttpPort = 0; /** Comma separated list of tags */ public String restrictToTagsSwitches = "Switchable"; diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java index 68623f35208e5..893f7253cb8c7 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/HueEmulationService.java @@ -96,7 +96,8 @@ public void filter(ContainerRequestContext requestContext) { * Jetty returns 415 on any GET request if a client sends the Content-Type header. * This is a workaround - stripping it away in the preMatching stage. */ - if (requestContext.getMethod() == HttpMethod.GET && requestContext.getHeaders().containsKey(HttpHeader.CONTENT_TYPE.asString())){ + if (requestContext.getMethod() == HttpMethod.GET + && requestContext.getHeaders().containsKey(HttpHeader.CONTENT_TYPE.asString())) { requestContext.getHeaders().remove(HttpHeader.CONTENT_TYPE.asString()); } } @@ -113,7 +114,6 @@ public void filter(ContainerRequestContext requestContext, ContainerResponseCont logger.debug("REST request {} {}", requestContext.getMethod(), requestContext.getUriInfo().getPath()); logger.debug("REST response: {}", responseContext.getEntity()); } - } private final ContainerRequestFilter requestCleaner = new RequestInterceptor(); diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/NetworkUtils.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/NetworkUtils.java index c451ebb64d2b0..032ce3516ea2d 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/NetworkUtils.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/NetworkUtils.java @@ -138,5 +138,4 @@ public static Response successList(Gson gson, List successLis return Response.ok(gson.toJson(responses, new TypeToken>() { }.getType())).build(); } - } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueRuleEntry.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueRuleEntry.java index 8b29101e130a0..b12164d342769 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueRuleEntry.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueRuleEntry.java @@ -136,5 +136,4 @@ public Condition deserialize(JsonElement json, Type typeOfT, JsonDeserialization return c; } } - } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueScheduleEntry.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueScheduleEntry.java index bdc291060082f..f842ea12260de 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueScheduleEntry.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueScheduleEntry.java @@ -12,8 +12,8 @@ */ package org.openhab.io.hueemulation.internal.dto; -import org.openhab.io.hueemulation.internal.dto.changerequest.HueCommand; import org.openhab.io.hueemulation.internal.dto.changerequest.HueChangeScheduleEntry; +import org.openhab.io.hueemulation.internal.dto.changerequest.HueCommand; /** * Hue API scan result object. diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueStateColorBulb.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueStateColorBulb.java index 0ea2c10d3a23d..2021cbde6e83b 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueStateColorBulb.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/dto/HueStateColorBulb.java @@ -124,7 +124,7 @@ public HSBType toHSBType() { } double hueSat = Math.floor((delta / maxValue) * 254.0d); int percentSat = (int) ((100.0d * hueSat) / (MAX_SAT)); - + int bri = this.bri * 100 / MAX_BRI; if (!this.on) { bri = 0; diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Scenes.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Scenes.java index ab7ca3cf89bda..c4b18a39d39b3 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Scenes.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Scenes.java @@ -419,5 +419,4 @@ public Response modifySceneLightStateApi(@Context UriInfo uri, // new HueSuccessGeneric(changeRequest.transitiontime, "/scenes/" + id + "/lightstates/" + lightid + "/transitiontime"))); } - } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Schedules.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Schedules.java index 1e130aa5e40a2..b0c883e645498 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Schedules.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Schedules.java @@ -339,5 +339,4 @@ public Response postNewSchedule(@Context UriInfo uri, return NetworkUtils.singleSuccess(cs.gson, uid, "id"); } - } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Sensors.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Sensors.java index 3d22fec656b31..1f6dee66f51d5 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Sensors.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/Sensors.java @@ -120,7 +120,6 @@ public synchronized void added(Item newElement) { HueSensorEntry sensor = new HueSensorEntry(element); cs.ds.sensors.put(hueID, sensor); - } @Override diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/StatusResource.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/StatusResource.java index cf2366d6dc95d..4450a1dd632f2 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/StatusResource.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/rest/StatusResource.java @@ -249,7 +249,6 @@ public void localDeviceAdded(Registry registry, LocalDevice device) { @NonNullByDefault({}) @Override public void localDeviceRemoved(Registry registry, LocalDevice device) { - } @NonNullByDefault({}) @@ -261,5 +260,4 @@ public void beforeShutdown(Registry registry) { public void afterShutdown() { selfTestUpnpFound = upnpStatus.service_not_registered; } - } diff --git a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java index b0f2c4124eaa9..62dda2b0a81e1 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java +++ b/bundles/org.openhab.io.hueemulation/src/main/java/org/openhab/io/hueemulation/internal/upnp/UpnpServer.java @@ -233,7 +233,6 @@ private void useAddressPort(HueEmulationConfigWithRuntime r) { xmlDocWithAddress = String.format(xmlDoc, urlBase, r.addressString, cs.ds.config.bridgeid, cs.ds.config.uuid, cs.ds.config.devicename); - } protected @Nullable HueEmulationConfigWithRuntime performAddressTest( diff --git a/bundles/org.openhab.io.hueemulation/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.io.hueemulation/src/main/resources/ESH-INF/config/config.xml index b82216a8944bd..a0a9d284bd7af 100644 --- a/bundles/org.openhab.io.hueemulation/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.io.hueemulation/src/main/resources/ESH-INF/config/config.xml @@ -7,7 +7,8 @@ - Pairing must be enabled to connect a new device. Pairing is automatically disabled after the configured pairing time (usually 60 seconds). + Pairing must be enabled to connect a new device. Pairing is automatically disabled after the configured + pairing time (usually 60 seconds). false @@ -18,51 +19,64 @@ - Set this option to create new users on the fly during the next pairing mode period. This helps with Amazon Echo device discovery. This option is automatically switched off after the timeout. + Set this option to create new users on the fly during the next pairing mode period. This helps with + Amazon Echo device discovery. This option is automatically switched off after the timeout. false - Some Amazon Echos only support V1 bridges (round hardware bridge). This option is only active during discovery and automatically switched off after the timeout. + Some Amazon Echos only support V1 bridges (round hardware bridge). This option is only active during + discovery and automatically switched off after the timeout. false - There is no obvious reason to not emulate the newer bridge all the time, but here is the option if you want the old (round Hue bridge) to be emulated. + There is no obvious reason to not emulate the newer bridge all the time, but here is the option if you + want the old (round Hue bridge) to be emulated. false - The HUE emulation can either publish Switch items if this is set to an empty string or filter items by tags. Use commas to separate multiple entries. + The HUE emulation can either publish Switch items if this is set to an empty string or filter items by + tags. Use commas to separate multiple entries. Switchable - The HUE emulation can either publish all Color items if this is set to an empty string or filter items by tags. Use commas to separate multiple entries. + The HUE emulation can either publish all Color items if this is set to an empty string or filter items + by tags. Use commas to separate multiple entries. ColorLighting - The HUE emulation can either publish all Dimmer items if this is set to an empty string or filter items by tags. Use commas to separate multiple entries. + The HUE emulation can either publish all Dimmer items if this is set to an empty string or filter items + by tags. Use commas to separate multiple entries. Lighting - All items that are tagged with the given tags are ignore by the Hue Emulation Service. Use commas to separate multiple entries. + All items that are tagged with the given tags are ignore by the Hue Emulation Service. Use commas to + separate multiple entries. internal - If your host has multiple IP addresses you may specify the IP you would like to advertise in the UPNP discovery process. You may safely leave this empty on most systems. + If your host has multiple IP addresses you may specify the IP(s) you would like to advertise in the UPNP + discovery process. You may safely leave this empty on most systems. Use commas to separate multiple entries. - Some Hue applications require a different port (80) then what openHAB runs on by default (8080). This option will only advertise a different port then what we are listening on. Useful if you have an iptables rule redirect traffic from this port to the openHAB port. + Some Hue applications require a different port (80) then what openHAB runs on by default (8080). This + option will only advertise a different port then what we are listening on. Useful if you have an iptables rule + redirect traffic from this port to the openHAB port. + true - Each Hue bridge has a universal unique id (UUID) assigned. This is random generated if no value has been assigned. Note on Amazon Alexa Echo devices: It might help to change the UUID after you have changed item ids. The Echos will recognize this service as a new bridge. + Each Hue bridge has a universal unique id (UUID) assigned. This is random generated if no value has been + assigned. Note on Amazon Alexa Echo devices: It might help to change the UUID after you have changed item ids. The + Echos will recognize this service as a new bridge. true diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/automation/RuleConditionHandlerTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/automation/RuleConditionHandlerTests.java index ff738564b350b..24a9a3a095f4b 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/automation/RuleConditionHandlerTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/automation/RuleConditionHandlerTests.java @@ -56,7 +56,6 @@ private static class HueRuleConditionHandlerEx extends HueRuleConditionHandler { public HueRuleConditionHandlerEx(Condition module, HueDataStore ds) { super(module, ds); - } @Override @@ -211,5 +210,4 @@ public void ltOperator() { subject = new HueRuleConditionHandler(c, ds); assertThat(subject.isSatisfied(context), is(true)); } - } diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroupsTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroupsTests.java index 078e70e4c187a..ce0a07f2c5d21 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroupsTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/LightsAndGroupsTests.java @@ -94,7 +94,6 @@ public void addSwitchableByCategory() { HueLightEntry device = cs.ds.lights.get(cs.mapItemUIDtoHueID(item)); assertThat(device.item, is(item)); assertThat(device.state, is(instanceOf(HueStatePlug.class))); - } @Test diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/RulesTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/RulesTests.java index c11ecf69029de..4e7d8155722b4 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/RulesTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/RulesTests.java @@ -276,5 +276,4 @@ public void getAll() { assertThat(entry.actions.get(0).address, is("/lights/switch1/state")); assertThat(entry.conditions.get(0).address, is("/lights/switch1/state/on")); } - } diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/UsersAndConfigTests.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/UsersAndConfigTests.java index c2f4e0b240afd..642cc6141383c 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/UsersAndConfigTests.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/UsersAndConfigTests.java @@ -136,5 +136,4 @@ public void UnauthorizedAccessTest() { assertThat(response.getStatus(), is(403)); assertThat(response.readEntity(String.class), containsString("error")); } - } diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyItemRegistry.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyItemRegistry.java index df0a264f66347..eddbbd74716f7 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyItemRegistry.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyItemRegistry.java @@ -138,11 +138,9 @@ public Collection getItemsByTag(Class typeFilter, String. @Override public void addRegistryHook(RegistryHook hook) { - } @Override public void removeRegistryHook(RegistryHook hook) { - } } diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyMetadataRegistry.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyMetadataRegistry.java index 57ea98bd83f36..91ef2bf20e421 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyMetadataRegistry.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyMetadataRegistry.java @@ -93,7 +93,5 @@ public boolean isInternalNamespace(String namespace) { @Override public void removeItemMetadata(String name) { - } - } diff --git a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyUsersStorage.java b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyUsersStorage.java index 21597ffacadd2..f76ba87007b07 100644 --- a/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyUsersStorage.java +++ b/bundles/org.openhab.io.hueemulation/src/test/java/org/openhab/io/hueemulation/internal/rest/mocks/DummyUsersStorage.java @@ -60,5 +60,4 @@ public boolean containsKey(String key) { public Collection<@Nullable HueUserAuthWithSecrets> getValues() { return users.values(); } - } diff --git a/bundles/org.openhab.io.imperihome/pom.xml b/bundles/org.openhab.io.imperihome/pom.xml index a64b179369011..4c3d8f3cd59de 100644 --- a/bundles/org.openhab.io.imperihome/pom.xml +++ b/bundles/org.openhab.io.imperihome/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.imperihome diff --git a/bundles/org.openhab.io.imperihome/src/main/feature/feature.xml b/bundles/org.openhab.io.imperihome/src/main/feature/feature.xml index d7b274a6dd619..198bb7efb991a 100644 --- a/bundles/org.openhab.io.imperihome/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.imperihome/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-core-model-item - mvn:org.openhab.addons.bundles/org.openhab.io.imperihome/${project.version} - + + openhab-runtime-base + openhab-core-model-item + mvn:org.openhab.addons.bundles/org.openhab.io.imperihome/${project.version} + diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/ImperiHomeApiServlet.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/ImperiHomeApiServlet.java index 3fe20999c093f..4e01e7faf1459 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/ImperiHomeApiServlet.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/ImperiHomeApiServlet.java @@ -247,5 +247,4 @@ private void setHeaders(HttpServletResponse response) { response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/ImperiHomeConfig.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/ImperiHomeConfig.java index 967d04511ae82..7ac1504b4f2b0 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/ImperiHomeConfig.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/ImperiHomeConfig.java @@ -56,5 +56,4 @@ public String getSystemId() { public String getRootUrl() { return rootUrl; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/Action.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/Action.java index f8c9b8fb3827b..8da554ed73645 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/Action.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/Action.java @@ -52,5 +52,4 @@ protected Action(EventPublisher eventPublisher) { * @param value Action parameter value. */ public abstract void perform(AbstractDevice device, Item item, String value); - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/ActionRegistry.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/ActionRegistry.java index 9c240aeefe240..37d617abdc1ea 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/ActionRegistry.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/ActionRegistry.java @@ -41,5 +41,4 @@ public ActionRegistry(EventPublisher eventPublisher, DeviceRegistry deviceRegist public Action get(String action) { return actions.get(action); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/LaunchSceneAction.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/LaunchSceneAction.java index 3fa3d1ad87f4e..d6dcdeac1187a 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/LaunchSceneAction.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/LaunchSceneAction.java @@ -55,5 +55,4 @@ public void perform(AbstractDevice device, Item item, String value) { eventPublisher.post(event); } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetChoiceAction.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetChoiceAction.java index a221bf45cc8aa..8c933e579bf3d 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetChoiceAction.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetChoiceAction.java @@ -60,5 +60,4 @@ public void perform(AbstractDevice device, Item item, String value) { COMMAND_SOURCE); eventPublisher.post(event); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetColorAction.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetColorAction.java index a0568dda7b7af..a9d7672e87f7c 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetColorAction.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetColorAction.java @@ -57,5 +57,4 @@ public void perform(AbstractDevice device, Item item, String value) { eventPublisher.post(event); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetLevelAction.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetLevelAction.java index b37b22d38e648..38a09f2220ed3 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetLevelAction.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetLevelAction.java @@ -41,5 +41,4 @@ public void perform(AbstractDevice device, Item item, String value) { COMMAND_SOURCE); eventPublisher.post(event); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetModeAction.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetModeAction.java index 83fae1847f707..f9d0a0b08df1e 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetModeAction.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetModeAction.java @@ -50,14 +50,15 @@ public void perform(AbstractDevice device, Item item, String value) { String modeDeviceName = device.getLinks().get("curmode"); AbstractDevice modeDevice = deviceRegistry.getDevice(ItemProcessor.getDeviceId(modeDeviceName)); if (modeDevice == null) { - logger.error("Couldn't resolve linked CurMode device '{}', make sure the Item has iss tags", modeDeviceName); + logger.error("Couldn't resolve linked CurMode device '{}', make sure the Item has iss tags", + modeDeviceName); return; } Item modeItem = modeDevice.getItem(); - ItemCommandEvent event = ItemEventFactory.createCommandEvent(modeItem.getName(), new StringType(value), COMMAND_SOURCE); + ItemCommandEvent event = ItemEventFactory.createCommandEvent(modeItem.getName(), new StringType(value), + COMMAND_SOURCE); eventPublisher.post(event); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetSetPointAction.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetSetPointAction.java index 510c2e2baa294..3c540f1a77249 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetSetPointAction.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetSetPointAction.java @@ -61,5 +61,4 @@ public void perform(AbstractDevice device, Item item, String value) { ItemCommandEvent event = ItemEventFactory.createCommandEvent(item.getName(), command, COMMAND_SOURCE); eventPublisher.post(event); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetStatusAction.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetStatusAction.java index 37a5f7385b996..092517ab99f72 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetStatusAction.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/SetStatusAction.java @@ -23,6 +23,7 @@ /** * Action setting device status to 1 or 0. + * * @author Pepijn de Geus - Initial contribution */ public class SetStatusAction extends Action { @@ -46,5 +47,4 @@ public void perform(AbstractDevice device, Item item, String value) { ItemCommandEvent event = ItemEventFactory.createCommandEvent(item.getName(), cmdValue, COMMAND_SOURCE); eventPublisher.post(event); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/StopShutterAction.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/StopShutterAction.java index 06c88ede60011..e8f895c20311e 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/StopShutterAction.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/action/StopShutterAction.java @@ -47,7 +47,8 @@ public void perform(AbstractDevice device, Item item, String value) { String modeDeviceName = device.getLinks().get("stopper"); AbstractDevice modeDevice = deviceRegistry.getDevice(ItemProcessor.getDeviceId(modeDeviceName)); if (modeDevice == null) { - logger.error("Couldn't resolve linked Stopper device '{}', make sure the Item has iss tags", modeDeviceName); + logger.error("Couldn't resolve linked Stopper device '{}', make sure the Item has iss tags", + modeDeviceName); return; } @@ -56,5 +57,4 @@ public void perform(AbstractDevice device, Item item, String value) { ItemCommandEvent event = ItemEventFactory.createCommandEvent(modeItem.getName(), OnOffType.ON, COMMAND_SOURCE); eventPublisher.post(event); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DeviceActionHandler.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DeviceActionHandler.java index 51f7e6bddd394..fa6e58b4b8ac4 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DeviceActionHandler.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DeviceActionHandler.java @@ -64,5 +64,4 @@ public void handle(HttpServletRequest req, Matcher urlMatcher) { device.performAction(action, value); } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DeviceHistoryHandler.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DeviceHistoryHandler.java index a8898842dd5d2..cef327fa6b351 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DeviceHistoryHandler.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DeviceHistoryHandler.java @@ -119,5 +119,4 @@ private HistoryList serveHistory(AbstractDevice device, QueryablePersistenceServ return new HistoryList(resultItems); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DevicesListHandler.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DevicesListHandler.java index c03e90c611c3d..3176d94903809 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DevicesListHandler.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/DevicesListHandler.java @@ -50,5 +50,4 @@ public DeviceList handle(HttpServletRequest req) { logger.debug("Device list response: {}", response); return response; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/RoomListHandler.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/RoomListHandler.java index 00c2775ad1491..6cf95122e3da1 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/RoomListHandler.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/RoomListHandler.java @@ -35,5 +35,4 @@ public RoomList handle(HttpServletRequest req) { response.setRooms(deviceRegistry.getRooms()); return response; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/SystemHandler.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/SystemHandler.java index aba38793e43a6..2e8437d6a6784 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/SystemHandler.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/handler/SystemHandler.java @@ -36,5 +36,4 @@ public System handle(HttpServletRequest req) { system.setApiVersion(1); return system; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/DeviceParametersSerializer.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/DeviceParametersSerializer.java index 33ecb364a2ac5..157465c2621fa 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/DeviceParametersSerializer.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/DeviceParametersSerializer.java @@ -38,5 +38,4 @@ public JsonElement serialize(DeviceParameters params, Type type, } return result; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/DeviceTypeSerializer.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/DeviceTypeSerializer.java index 5e39fd3f1f59a..f917f4712d3f2 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/DeviceTypeSerializer.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/DeviceTypeSerializer.java @@ -32,5 +32,4 @@ public class DeviceTypeSerializer implements JsonSerializer { public JsonElement serialize(DeviceType deviceType, Type type, JsonSerializationContext jsonSerializationContext) { return new JsonPrimitive(deviceType.getApiString()); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/ParamTypeSerializer.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/ParamTypeSerializer.java index 530b2ba55bdac..9b3ed109cad13 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/ParamTypeSerializer.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/io/ParamTypeSerializer.java @@ -32,5 +32,4 @@ public class ParamTypeSerializer implements JsonSerializer { public JsonElement serialize(ParamType paramType, Type type, JsonSerializationContext jsonSerializationContext) { return new JsonPrimitive(paramType.getApiString()); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/HistoryItem.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/HistoryItem.java index 20067a92e385e..2a6720ab8f437 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/HistoryItem.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/HistoryItem.java @@ -48,5 +48,4 @@ public Number getValue() { public void setValue(Number value) { this.value = value; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/HistoryList.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/HistoryList.java index a222e2927b1da..a1d9badd9dc3d 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/HistoryList.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/HistoryList.java @@ -39,5 +39,4 @@ public List getValues() { public void setValues(List values) { this.values = values; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/Room.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/Room.java index 2e2e262c37aa8..23348651c8bff 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/Room.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/Room.java @@ -61,5 +61,4 @@ public int hashCode() { public String toString() { return "Room{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/RoomList.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/RoomList.java index e36f60b5d007c..0d231dad79519 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/RoomList.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/RoomList.java @@ -30,5 +30,4 @@ public Collection getRooms() { public void setRooms(Collection rooms) { this.rooms = rooms; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/System.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/System.java index eb81b15bb4a19..b94ec0a0a4b17 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/System.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/System.java @@ -37,5 +37,4 @@ public int getApiVersion() { public void setApiVersion(int apiVersion) { this.apiVersion = apiVersion; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractDevice.java index fa10c7ac6e32b..84eb1959bad34 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractDevice.java @@ -185,6 +185,7 @@ public String getItemName() { /** * Process any device-specific ISS tags. + * * @param issTags ISS tags map. */ public void processCustomTags(Map> issTags) { @@ -239,8 +240,7 @@ public void stateUpdated(Item item, State newState) { @Override public String toString() { - return getClass().getSimpleName() + "{id='" + id + '\'' + ", name='" + name + '\'' + ", room='" + room + '\'' + ", type=" - + type + ", invert=" + inverted + ", icon=" + defaultIcon + ", links=" + links + '}'; + return getClass().getSimpleName() + "{id='" + id + '\'' + ", name='" + name + '\'' + ", room='" + room + '\'' + + ", type=" + type + ", invert=" + inverted + ", icon=" + defaultIcon + ", links=" + links + '}'; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractEnergyLinkDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractEnergyLinkDevice.java index 9f17253ed665d..b7effda3758e1 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractEnergyLinkDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractEnergyLinkDevice.java @@ -50,5 +50,4 @@ public void updateParams() { } } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractNumericValueDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractNumericValueDevice.java index 5114d82e206f8..c424d1b2362a6 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractNumericValueDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/AbstractNumericValueDevice.java @@ -41,5 +41,4 @@ public void setUnit(String unit) { public String toString() { return getClass().getSimpleName() + "{" + "super=" + super.toString() + ", unit='" + unit + '\'' + '}'; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/Co2SensorDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/Co2SensorDevice.java index bfa38f1850571..dcbae11c83afa 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/Co2SensorDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/Co2SensorDevice.java @@ -36,5 +36,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.CO2_VALUE, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DeviceList.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DeviceList.java index 85f26d555d698..1183d390ce225 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DeviceList.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DeviceList.java @@ -35,5 +35,4 @@ public void setDevices(Collection devices) { public String toString() { return "DeviceList{" + "devices=" + devices + '}'; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DeviceType.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DeviceType.java index 5798a6e0cf173..ac572c78e2d72 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DeviceType.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DeviceType.java @@ -73,5 +73,4 @@ public static DeviceType forApiString(String apiString) { return null; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DimmerDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DimmerDevice.java index a6c80870a4859..58aeee0a02997 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DimmerDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/DimmerDevice.java @@ -43,5 +43,4 @@ public void stateUpdated(Item item, State newState) { addParam(new DeviceParam(ParamType.LEVEL, String.valueOf(level))); addParam(new DeviceParam(ParamType.STATUS, (level > 0) ^ isInverted() ? "1" : "0")); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ElectricityDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ElectricityDevice.java index 3c3b3de4683a8..33a37eb3c1496 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ElectricityDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ElectricityDevice.java @@ -114,5 +114,4 @@ private void setKwhParam(AbstractDevice device) { kwhParam.setValue(valueParam.getValue()); addParam(kwhParam); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/GenericSensorDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/GenericSensorDevice.java index 9b8fc51c90077..58626346eb31f 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/GenericSensorDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/GenericSensorDevice.java @@ -43,5 +43,4 @@ public void stateUpdated(Item item, State newState) { addParam(new DeviceParam(ParamType.GENERIC_VALUE, strVal)); } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/HygrometryDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/HygrometryDevice.java index e7fd81a9aa7f6..79c8e1da65114 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/HygrometryDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/HygrometryDevice.java @@ -36,5 +36,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.HYGROMETRY_VALUE, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/LockDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/LockDevice.java index 1099f3c502265..d1143aff01907 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/LockDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/LockDevice.java @@ -42,5 +42,4 @@ public void stateUpdated(Item item, State newState) { } } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/LuminosityDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/LuminosityDevice.java index 83339336871bb..12bf675bdc6aa 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/LuminosityDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/LuminosityDevice.java @@ -36,5 +36,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.LUMINOSITY_VALUE, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/MultiSwitchDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/MultiSwitchDevice.java index b5ef39f55ddc8..a0abff5ffb267 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/MultiSwitchDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/MultiSwitchDevice.java @@ -67,5 +67,4 @@ public void stateUpdated(Item item, State newState) { itemValue = String.valueOf(((DecimalType) state).intValue()); } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/NoiseDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/NoiseDevice.java index 83eb95a8e4297..25def6223d5cb 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/NoiseDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/NoiseDevice.java @@ -36,5 +36,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.NOISE_VALUE, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/PressureDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/PressureDevice.java index bb184dc27a213..9a986c2bdecdc 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/PressureDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/PressureDevice.java @@ -36,5 +36,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.PRESSURE_VALUE, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/RainDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/RainDevice.java index 1d1fa270a524a..3bdf54f9a4faa 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/RainDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/RainDevice.java @@ -70,5 +70,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.RAIN_VALUE, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/RgbLightDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/RgbLightDevice.java index e22fa80c2939b..1dd8522dc9770 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/RgbLightDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/RgbLightDevice.java @@ -86,5 +86,4 @@ private int convertPercentToByte(PercentType percent) { return percent.toBigDecimal().multiply(BigDecimal.valueOf(255)) .divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP).intValue(); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/SceneDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/SceneDevice.java index d0ed9e7ade23d..a994c58759a7f 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/SceneDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/SceneDevice.java @@ -24,5 +24,4 @@ public class SceneDevice extends AbstractDevice { public SceneDevice(Item item) { super(DeviceType.SCENE, item); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ShutterDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ShutterDevice.java index 35c3108901c1d..39f587eb80047 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ShutterDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ShutterDevice.java @@ -44,5 +44,4 @@ public void stateUpdated(Item item, State newState) { addParam(new DeviceParam(ParamType.STOPPABLE, getLinks().containsKey("stopper") ? "1" : "0")); addParam(new DeviceParam(ParamType.LEVEL, String.valueOf(level))); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/SwitchDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/SwitchDevice.java index fe6df71c68f97..3b6cb2fdffae4 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/SwitchDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/SwitchDevice.java @@ -42,5 +42,4 @@ public void stateUpdated(Item item, State newState) { } } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TempHygroDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TempHygroDevice.java index cb2e85db2efa6..6632fae13cd3f 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TempHygroDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TempHygroDevice.java @@ -118,5 +118,4 @@ private void setTempParam(AbstractDevice device) { tempParam.setValue(valueParam.getValue()); addParam(tempParam); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TemperatureDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TemperatureDevice.java index 0f29a0661875c..774b1244930bf 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TemperatureDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TemperatureDevice.java @@ -36,5 +36,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.TEMPERATURE_VALUE, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ThermostatDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ThermostatDevice.java index a203046e59ead..9354d5096628b 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ThermostatDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/ThermostatDevice.java @@ -118,9 +118,9 @@ private AbstractDevice getLinkedDevice(String linkName, boolean logWhenMissing) device = getDeviceRegistry().getDevice(deviceId); } if (logWhenMissing && device == null) { - logger.error("Couldn't resolve linked {} device '{}', make sure the Item has iss tags", linkName, deviceName); + logger.error("Couldn't resolve linked {} device '{}', make sure the Item has iss tags", linkName, + deviceName); } return device; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TrippableDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TrippableDevice.java index caf20086a05be..3ce9a0f2b2f11 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TrippableDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/TrippableDevice.java @@ -65,5 +65,4 @@ public void stateUpdated(Item item, State newState) { addParam(new DeviceParam(ParamType.LAST_TRIP, String.valueOf(System.currentTimeMillis()))); } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/UvDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/UvDevice.java index e2b1dedc6adf3..9c9c7f2528bfd 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/UvDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/UvDevice.java @@ -36,5 +36,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.UV_VALUE, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/WindDevice.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/WindDevice.java index ac26c2b415d02..7b91f03e86f2f 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/WindDevice.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/device/WindDevice.java @@ -70,5 +70,4 @@ public void stateUpdated(Item item, State newState) { DecimalType value = (DecimalType) item.getStateAs(DecimalType.class); addParam(new NumericValueParam(ParamType.SPEED, getUnit(), value)); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/DeviceParam.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/DeviceParam.java index 5eedd4618d8c4..060970733ffb4 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/DeviceParam.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/DeviceParam.java @@ -69,5 +69,4 @@ public int hashCode() { public String toString() { return "DeviceParam{" + "key=" + key + ", value='" + value + '\'' + '}'; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/DeviceParameters.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/DeviceParameters.java index de259047c35da..9bde1ae4ec7e2 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/DeviceParameters.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/DeviceParameters.java @@ -28,5 +28,4 @@ public class DeviceParameters extends HashMap { public void set(DeviceParam param) { put(param.getKey(), param); } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/NumericValueParam.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/NumericValueParam.java index 929a399da2659..b179d0a685501 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/NumericValueParam.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/NumericValueParam.java @@ -84,5 +84,4 @@ public String toString() { return "NumericValueParam{" + "super=" + super.toString() + ", unit='" + unit + '\'' + ", graphable=" + graphable + '}'; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/ParamType.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/ParamType.java index a07c0ad3f0f65..d64eeab0c2db8 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/ParamType.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/model/param/ParamType.java @@ -52,7 +52,7 @@ public enum ParamType { STOPPABLE("stopable"), PULSEABLE("pulseable"), - //Thermostat parameters + // Thermostat parameters CUR_MODE("curmode"), CUR_SETPOINT("cursetpoint"), CUR_TEMP("curtemp"), @@ -70,5 +70,4 @@ public enum ParamType { public String getApiString() { return apiString; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/DeviceRegistry.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/DeviceRegistry.java index 16ef248f014ea..9a716f1d48ccc 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/DeviceRegistry.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/DeviceRegistry.java @@ -62,10 +62,11 @@ public boolean hasDevice(String deviceId) { } public void add(AbstractDevice device) { - //Workaround for Eclipse SH bug: ignore add-event for same item - //https://github.com/eclipse/smarthome/issues/3160 + // Workaround for Eclipse SH bug: ignore add-event for same item + // https://github.com/eclipse/smarthome/issues/3160 if (devices.containsKey(device.getId())) { - logger.warn("Ignoring duplicate device #{}, name={}, item={}", device.getId(), device.getName(), device.getItemName()); + logger.warn("Ignoring duplicate device #{}, name={}, item={}", device.getId(), device.getName(), + device.getItemName()); return; } @@ -112,5 +113,4 @@ private void updateRooms() { } rooms = newRooms; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/ItemProcessor.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/ItemProcessor.java index cae6172f441b0..c1657b10f074b 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/ItemProcessor.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/ItemProcessor.java @@ -451,5 +451,4 @@ public void allItemsChanged(Collection oldItems) { } } } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/TagType.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/TagType.java index 2e6fdec4c807e..f2df8698ad2fa 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/TagType.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/processor/TagType.java @@ -54,5 +54,4 @@ public String getPrefix() { public boolean isMultiValue() { return multiValue; } - } diff --git a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/util/DigestUtil.java b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/util/DigestUtil.java index 825afb26d5c1c..4928406c3315b 100644 --- a/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/util/DigestUtil.java +++ b/bundles/org.openhab.io.imperihome/src/main/java/org/openhab/io/imperihome/internal/util/DigestUtil.java @@ -39,5 +39,4 @@ public static String sha1(String input) { // Hidden constructor private DigestUtil() { } - } diff --git a/bundles/org.openhab.io.javasound/pom.xml b/bundles/org.openhab.io.javasound/pom.xml index faa2d7c2d64f7..0099a025c6c36 100644 --- a/bundles/org.openhab.io.javasound/pom.xml +++ b/bundles/org.openhab.io.javasound/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.javasound diff --git a/bundles/org.openhab.io.javasound/src/main/feature/feature.xml b/bundles/org.openhab.io.javasound/src/main/feature/feature.xml index e9c531da8cff2..c61817bd7873c 100644 --- a/bundles/org.openhab.io.javasound/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.javasound/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:commons-collections/commons-collections/3.2.2 - mvn:org.openhab.addons.bundles/org.openhab.io.javasound/${project.version} - + + openhab-runtime-base + mvn:commons-collections/commons-collections/3.2.2 + mvn:org.openhab.addons.bundles/org.openhab.io.javasound/${project.version} + diff --git a/bundles/org.openhab.io.javasound/src/main/java/org/openhab/io/javasound/internal/JavaSoundAudioSink.java b/bundles/org.openhab.io.javasound/src/main/java/org/openhab/io/javasound/internal/JavaSoundAudioSink.java index 3293270397fff..f3a783661a8fa 100644 --- a/bundles/org.openhab.io.javasound/src/main/java/org/openhab/io/javasound/internal/JavaSoundAudioSink.java +++ b/bundles/org.openhab.io.javasound/src/main/java/org/openhab/io/javasound/internal/JavaSoundAudioSink.java @@ -20,6 +20,8 @@ import java.util.Locale; import java.util.Set; import java.util.stream.Stream; +import javazoom.jl.decoder.JavaLayerException; +import javazoom.jl.player.Player; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.FloatControl; @@ -43,9 +45,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javazoom.jl.decoder.JavaLayerException; -import javazoom.jl.player.Player; - /** * This is an audio sink that is registered as a service, which can play wave files to the hosts outputs (e.g. speaker, * line-out). diff --git a/bundles/org.openhab.io.javasound/src/main/java/org/openhab/io/javasound/internal/JavaSoundAudioSource.java b/bundles/org.openhab.io.javasound/src/main/java/org/openhab/io/javasound/internal/JavaSoundAudioSource.java index 52f5358b422ec..d1b0455fa35f2 100644 --- a/bundles/org.openhab.io.javasound/src/main/java/org/openhab/io/javasound/internal/JavaSoundAudioSource.java +++ b/bundles/org.openhab.io.javasound/src/main/java/org/openhab/io/javasound/internal/JavaSoundAudioSource.java @@ -131,5 +131,4 @@ public String getLabel(Locale locale) { public Set getSupportedFormats() { return Collections.singleton(audioFormat); } - } diff --git a/bundles/org.openhab.io.mqttembeddedbroker/README.md b/bundles/org.openhab.io.mqttembeddedbroker/README.md index 52e61d117a3c2..2eace0bcff127 100644 --- a/bundles/org.openhab.io.mqttembeddedbroker/README.md +++ b/bundles/org.openhab.io.mqttembeddedbroker/README.md @@ -1,5 +1,9 @@ # MQTT Broker Moquette +**Attention:** Moquette is no longer maintained upstream and this add-on is therefore considered deprecated in openHAB. +It is recommended to switch to an external broker like mosquitto. +The Moquette add-on will be removed in a future release of openHAB. + MQTT is a machine-to-machine (M2M)/"Internet of Things" connectivity protocol. It was designed as an extremely lightweight publish/subscribe messaging transport. diff --git a/bundles/org.openhab.io.mqttembeddedbroker/pom.xml b/bundles/org.openhab.io.mqttembeddedbroker/pom.xml index d5159cc6265bc..46d5abe3ace44 100644 --- a/bundles/org.openhab.io.mqttembeddedbroker/pom.xml +++ b/bundles/org.openhab.io.mqttembeddedbroker/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.mqttembeddedbroker diff --git a/bundles/org.openhab.io.mqttembeddedbroker/src/main/feature/feature.xml b/bundles/org.openhab.io.mqttembeddedbroker/src/main/feature/feature.xml index ca21d23c24ab1..4710c1786b61f 100644 --- a/bundles/org.openhab.io.mqttembeddedbroker/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.mqttembeddedbroker/src/main/feature/feature.xml @@ -1,13 +1,13 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-mqtt - openhab.tp-netty - mvn:com.h2database/h2-mvstore/1.4.199 - mvn:commons-codec/commons-codec/1.10 - mvn:org.openhab.addons.bundles/org.openhab.io.mqttembeddedbroker/${project.version} - + + openhab-runtime-base + openhab-transport-mqtt + openhab.tp-netty + mvn:com.h2database/h2-mvstore/1.4.199 + mvn:commons-codec/commons-codec/1.10 + mvn:org.openhab.addons.bundles/org.openhab.io.mqttembeddedbroker/${project.version} + diff --git a/bundles/org.openhab.io.mqttembeddedbroker/src/main/java/org/openhab/io/mqttembeddedbroker/internal/EmbeddedBrokerService.java b/bundles/org.openhab.io.mqttembeddedbroker/src/main/java/org/openhab/io/mqttembeddedbroker/internal/EmbeddedBrokerService.java index e2de677f8f1ba..1d6eb207a0a75 100644 --- a/bundles/org.openhab.io.mqttembeddedbroker/src/main/java/org/openhab/io/mqttembeddedbroker/internal/EmbeddedBrokerService.java +++ b/bundles/org.openhab.io.mqttembeddedbroker/src/main/java/org/openhab/io/mqttembeddedbroker/internal/EmbeddedBrokerService.java @@ -86,7 +86,7 @@ ConfigurableService.SERVICE_PROPERTY_LABEL + "=MQTT Embedded Broker" }) @NonNullByDefault public class EmbeddedBrokerService - implements ConfigurableService, MqttConnectionObserver, MqttServiceObserver, MqttEmbeddedBrokerStartedListener { + implements MqttConnectionObserver, MqttServiceObserver, MqttEmbeddedBrokerStartedListener { private final MqttService service; private String persistenceFilename = ""; // private NetworkServerTls networkServerTls; //TODO wait for NetworkServerTls implementation diff --git a/bundles/org.openhab.io.mqttembeddedbroker/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.io.mqttembeddedbroker/src/main/resources/ESH-INF/config/config.xml index 9b7762c220710..3ec7c7c9ff8d1 100644 --- a/bundles/org.openhab.io.mqttembeddedbroker/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.io.mqttembeddedbroker/src/main/resources/ESH-INF/config/config.xml @@ -9,14 +9,16 @@ A custom broker connection port. Leave empty to use the - default MQTT ports 1883 and 8883 (SSL) for secure or non-secure + default MQTT ports 1883 and 8883 (SSL) for secure + or non-secure connections. If set, hosts a secure SSL connection on port 8883 or - otherwise a non secure connection on port 1883 (if not overwritten + otherwise a non secure connection on port 1883 (if + not overwritten by the port parameter) false @@ -30,17 +32,21 @@ Connections need to provide this password to access the - broker. Should only be used if it is a secure connection, because + broker. Should only be used if it is a secure + connection, because the password is transferred plain over the wire. An optional persistence file. Retained messages are - stored in this file. Can be empty to not store anything. If it + stored in this file. Can be empty to not store + anything. If it starts with "/" on Linux/MacOS or with a drive letter and colon (eg - "c:/") it will be treated as an absolute path. Be careful to select - a path that you have write access to. + "c:/") it will be treated as an + absolute path. Be careful to select + a path that you have write access to. + mqttembedded.bin diff --git a/bundles/org.openhab.io.neeo/.classpath b/bundles/org.openhab.io.neeo/.classpath index a5d95095ccaaf..f2513389b0443 100644 --- a/bundles/org.openhab.io.neeo/.classpath +++ b/bundles/org.openhab.io.neeo/.classpath @@ -18,6 +18,7 @@ + diff --git a/bundles/org.openhab.io.neeo/NOTICE b/bundles/org.openhab.io.neeo/NOTICE index 38d625e349232..1b52e85062af0 100644 --- a/bundles/org.openhab.io.neeo/NOTICE +++ b/bundles/org.openhab.io.neeo/NOTICE @@ -11,3 +11,9 @@ https://www.eclipse.org/legal/epl-2.0/. == Source Code https://github.com/openhab/openhab-addons + +== Third-party Content + +This binding includes a class from Jersey in the src/3rdparty/java folder. +* License: CDDL License +* Project: https://eclipse-ee4j.github.io/jersey/ diff --git a/bundles/org.openhab.io.neeo/pom.xml b/bundles/org.openhab.io.neeo/pom.xml index 0554618b9c4a2..fb0aa578f51ef 100644 --- a/bundles/org.openhab.io.neeo/pom.xml +++ b/bundles/org.openhab.io.neeo/pom.xml @@ -1,15 +1,39 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.neeo openHAB Add-ons :: Bundles :: IO :: NEEO Integration + + + + org.codehaus.mojo + build-helper-maven-plugin + + + + add-source + + generate-sources + + + src/3rdparty/java + + + + + + + + diff --git a/bundles/org.openhab.io.neeo/src/3rdparty/java/org/glassfish/jersey/filter/LoggingFilter.java b/bundles/org.openhab.io.neeo/src/3rdparty/java/org/glassfish/jersey/filter/LoggingFilter.java new file mode 100644 index 0000000000000..4457671c5cde2 --- /dev/null +++ b/bundles/org.openhab.io.neeo/src/3rdparty/java/org/glassfish/jersey/filter/LoggingFilter.java @@ -0,0 +1,355 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 2011-2015 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * http://glassfish.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package org.glassfish.jersey.filter; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; +import java.util.logging.Logger; + +import javax.annotation.Priority; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.ClientRequestContext; +import javax.ws.rs.client.ClientRequestFilter; +import javax.ws.rs.client.ClientResponseContext; +import javax.ws.rs.client.ClientResponseFilter; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; + +/** + * Universal logging filter. + *

+ * Can be used on client or server side. Has the highest priority. + * + * @author Pavel Bucek (pavel.bucek at oracle.com) + * @author Martin Matula + */ +@PreMatching +@Priority(Integer.MIN_VALUE) +public final class LoggingFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, + ClientResponseFilter, WriterInterceptor { + + public static final Charset UTF8 = Charset.forName("UTF-8"); + + private static final Logger LOGGER = Logger.getLogger(LoggingFilter.class.getName()); + private static final String NOTIFICATION_PREFIX = "* "; + private static final String REQUEST_PREFIX = "> "; + private static final String RESPONSE_PREFIX = "< "; + private static final String ENTITY_LOGGER_PROPERTY = LoggingFilter.class.getName() + ".entityLogger"; + private static final String LOGGING_ID_PROPERTY = LoggingFilter.class.getName() + ".id"; + + private static final Comparator>> COMPARATOR = new Comparator>>() { + + @Override + public int compare(final Map.Entry> o1, final Map.Entry> o2) { + return o1.getKey().compareToIgnoreCase(o2.getKey()); + } + }; + + private static final int DEFAULT_MAX_ENTITY_SIZE = 8 * 1024; + + // + private final Logger logger; + private final AtomicLong _id = new AtomicLong(0); + private final boolean printEntity; + private final int maxEntitySize; + + /** + * Create a logging filter logging the request and response to a default JDK + * logger, named as the fully qualified class name of this class. Entity + * logging is turned off by default. + */ + public LoggingFilter() { + this(LOGGER, false); + } + + /** + * Create a logging filter with custom logger and custom settings of entity + * logging. + * + * @param logger the logger to log requests and responses. + * @param printEntity if true, entity will be logged as well up to the default maxEntitySize, which is 8KB + */ + public LoggingFilter(final Logger logger, final boolean printEntity) { + this.logger = logger; + this.printEntity = printEntity; + this.maxEntitySize = DEFAULT_MAX_ENTITY_SIZE; + } + + /** + * Creates a logging filter with custom logger and entity logging turned on, but potentially limiting the size + * of entity to be buffered and logged. + * + * @param logger the logger to log requests and responses. + * @param maxEntitySize maximum number of entity bytes to be logged (and buffered) - if the entity is larger, + * logging filter will print (and buffer in memory) only the specified number of bytes + * and print "...more..." string at the end. Negative values are interpreted as zero. + */ + public LoggingFilter(final Logger logger, final int maxEntitySize) { + this.logger = logger; + this.printEntity = true; + this.maxEntitySize = Math.max(0, maxEntitySize); + } + + private void log(final StringBuilder b) { + if (logger != null) { + logger.info(b.toString()); + } + } + + private StringBuilder prefixId(final StringBuilder b, final long id) { + b.append(Long.toString(id)).append(" "); + return b; + } + + private void printRequestLine(final StringBuilder b, final String note, final long id, final String method, + final URI uri) { + prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") + .append(Thread.currentThread().getName()).append("\n"); + prefixId(b, id).append(REQUEST_PREFIX).append(method).append(" ").append(uri.toASCIIString()).append("\n"); + } + + private void printResponseLine(final StringBuilder b, final String note, final long id, final int status) { + prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") + .append(Thread.currentThread().getName()).append("\n"); + prefixId(b, id).append(RESPONSE_PREFIX).append(Integer.toString(status)).append("\n"); + } + + private void printPrefixedHeaders(final StringBuilder b, final long id, final String prefix, + final MultivaluedMap headers) { + for (final Map.Entry> headerEntry : getSortedHeaders(headers.entrySet())) { + final List val = headerEntry.getValue(); + final String header = headerEntry.getKey(); + + if (val.size() == 1) { + prefixId(b, id).append(prefix).append(header).append(": ").append(val.get(0)).append("\n"); + } else { + final StringBuilder sb = new StringBuilder(); + boolean add = false; + for (final Object s : val) { + if (add) { + sb.append(','); + } + add = true; + sb.append(s); + } + prefixId(b, id).append(prefix).append(header).append(": ").append(sb.toString()).append("\n"); + } + } + } + + private Set>> getSortedHeaders(final Set>> headers) { + final TreeSet>> sortedHeaders = new TreeSet>>( + COMPARATOR); + sortedHeaders.addAll(headers); + return sortedHeaders; + } + + private InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) + throws IOException { + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + stream.mark(maxEntitySize + 1); + final byte[] entity = new byte[maxEntitySize + 1]; + final int entitySize = stream.read(entity); + b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); + if (entitySize > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + stream.reset(); + return stream; + } + + @Override + public void filter(final ClientRequestContext context) throws IOException { + final long id = _id.incrementAndGet(); + context.setProperty(LOGGING_ID_PROPERTY, id); + + final StringBuilder b = new StringBuilder(); + + printRequestLine(b, "Sending client request", id, context.getMethod(), context.getUri()); + printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getStringHeaders()); + + if (printEntity && context.hasEntity()) { + final OutputStream stream = new LoggingStream(b, context.getEntityStream()); + context.setEntityStream(stream); + context.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) + throws IOException { + final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); + final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); + + final StringBuilder b = new StringBuilder(); + + printResponseLine(b, "Client response received", id, responseContext.getStatus()); + printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getHeaders()); + + if (printEntity && responseContext.hasEntity()) { + responseContext.setEntityStream( + logInboundEntity(b, responseContext.getEntityStream(), getCharset(responseContext.getMediaType()))); + } + + log(b); + } + + @Override + public void filter(final ContainerRequestContext context) throws IOException { + final long id = _id.incrementAndGet(); + context.setProperty(LOGGING_ID_PROPERTY, id); + + final StringBuilder b = new StringBuilder(); + + printRequestLine(b, "Server has received a request", id, context.getMethod(), + context.getUriInfo().getRequestUri()); + printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getHeaders()); + + if (printEntity && context.hasEntity()) { + context.setEntityStream(logInboundEntity(b, context.getEntityStream(), getCharset(context.getMediaType()))); + } + + log(b); + } + + @Override + public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) + throws IOException { + final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); + final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); + + final StringBuilder b = new StringBuilder(); + + printResponseLine(b, "Server responded with a response", id, responseContext.getStatus()); + printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getStringHeaders()); + + if (printEntity && responseContext.hasEntity()) { + final OutputStream stream = new LoggingStream(b, responseContext.getEntityStream()); + responseContext.setEntityStream(stream); + requestContext.setProperty(ENTITY_LOGGER_PROPERTY, stream); + // not calling log(b) here - it will be called by the interceptor + } else { + log(b); + } + } + + @Override + public void aroundWriteTo(final WriterInterceptorContext writerInterceptorContext) + throws IOException, WebApplicationException { + final LoggingStream stream = (LoggingStream) writerInterceptorContext.getProperty(ENTITY_LOGGER_PROPERTY); + writerInterceptorContext.proceed(); + if (stream != null) { + log(stream.getStringBuilder(getCharset(writerInterceptorContext.getMediaType()))); + } + } + + private class LoggingStream extends FilterOutputStream { + + private final StringBuilder b; + private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + LoggingStream(final StringBuilder b, final OutputStream inner) { + super(inner); + + this.b = b; + } + + StringBuilder getStringBuilder(final Charset charset) { + // write entity to the builder + final byte[] entity = baos.toByteArray(); + + b.append(new String(entity, 0, Math.min(entity.length, maxEntitySize), charset)); + if (entity.length > maxEntitySize) { + b.append("...more..."); + } + b.append('\n'); + + return b; + } + + @Override + public void write(final int i) throws IOException { + if (baos.size() <= maxEntitySize) { + baos.write(i); + } + out.write(i); + } + } + + /** + * Get the character set from a media type. + *

+ * The character set is obtained from the media type parameter "charset". + * If the parameter is not present the {@link #UTF8} charset is utilized. + * + * @param m the media type. + * @return the character set. + */ + public static Charset getCharset(MediaType m) { + String name = (m == null) ? null : m.getParameters().get(MediaType.CHARSET_PARAMETER); + return (name == null) ? UTF8 : Charset.forName(name); + } + +} diff --git a/bundles/org.openhab.io.neeo/src/main/feature/feature.xml b/bundles/org.openhab.io.neeo/src/main/feature/feature.xml index a79306941ab2c..939089a228540 100644 --- a/bundles/org.openhab.io.neeo/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.neeo/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.io.neeo/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.io.neeo/${project.version} + diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoDeviceDefinitions.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoDeviceDefinitions.java index ec908c7ddc747..7d57cff527312 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoDeviceDefinitions.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoDeviceDefinitions.java @@ -190,7 +190,7 @@ public List getExposed() { * {@link NeeoDevice} that is bound (according to the {@link NeeoDeviceKeys}) and then will determine if the item * name has been bound on that {@link NeeoDevice}. * - * @param keys a non-null {@link NeeoDeviceKeys} + * @param keys a non-null {@link NeeoDeviceKeys} * @param itemName a non-null, non-empty item name to use * @return true if bound, false otherwise */ @@ -231,7 +231,7 @@ public List> getBound(NeeoDeviceKeys ke * Gets the list of {@link NeeoDevice} and {@link NeeoDeviceChannel} that are currently bound for the given itemName * (or all if the itemName is null) * - * @param keys a non-null {@link NeeoDeviceKeys} + * @param keys a non-null {@link NeeoDeviceKeys} * @param itemName a possibly null, possibly empty item name to use * @return a non-null, possibly empty list */ diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoUtil.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoUtil.java index 188c727879775..6c021df485d5d 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoUtil.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/NeeoUtil.java @@ -196,7 +196,7 @@ public static String encodeURIComponent(String s) { * Write a response out to the {@link HttpServletResponse} * * @param resp the non-null {@link HttpServletResponse} - * @param str the possibly null, possibly empty string content to write + * @param str the possibly null, possibly empty string content to write * @throws IOException Signals that an I/O exception has occurred. */ public static void write(HttpServletResponse resp, String str) throws IOException { @@ -259,7 +259,7 @@ static void cancel(@Nullable Future future) { * Require the specified value to be a non-null, non-empty string * * @param value the value to check - * @param msg the msg to use when throwing an {@link IllegalArgumentException} + * @param msg the msg to use when throwing an {@link IllegalArgumentException} * @throws IllegalArgumentException if value is null or an empty string */ public static void requireNotEmpty(String value, String msg) { @@ -272,7 +272,7 @@ public static void requireNotEmpty(String value, String msg) { /** * Converts a JSON property to a string * - * @param jo the non-null {@link JsonObject} to use + * @param jo the non-null {@link JsonObject} to use * @param propertyName the non-empty property name * @return the possibly null string representation */ @@ -288,7 +288,7 @@ public static String getString(JsonObject jo, String propertyName) { /** * Converts a JSON property to an integer * - * @param jo the non-null {@link JsonObject} to use + * @param jo the non-null {@link JsonObject} to use * @param propertyName the non-empty property name * @return the possibly null integer */ @@ -304,7 +304,7 @@ public static Integer getInt(JsonObject jo, String propertyName) { /** * Gets the {@link Command} for the specified enum name - ignoring case * - * @param cmd the non-null {@link Command} + * @param cmd the non-null {@link Command} * @param enumName the non-empty enum name to search for * @return the {@link Command} or null if not found (or null if cmd's class is not an enum) */ @@ -337,7 +337,7 @@ static NeeoDeviceType guessType(Thing thing) { /** * Gets the label to use from the item or channelType * - * @param item the possibly null item + * @param item the possibly null item * @param channelType the possibly null channel type * @return the label to use (or null if no label) */ @@ -362,7 +362,7 @@ public static String getLabel(@Nullable Item item, @Nullable ChannelType channel /** * Gets the pattern to use from the item or channelType * - * @param item the possibly null item + * @param item the possibly null item * @param channelType the possibly null channel type * @return the pattern to use (or null if no pattern to use) */ @@ -396,7 +396,7 @@ public static String getPattern(@Nullable Item item, @Nullable ChannelType chann /** * Returns the unique label name given a set of labels. The unique label will be added to the set of labels. * - * @param labels the non-null, possibly empty set of labels + * @param labels the non-null, possibly empty set of labels * @param itemLabel the possibly null, possibly empty item label to get a unique name for * @return the unique label */ @@ -420,7 +420,7 @@ public static String getUniqueLabel(Set labels, String itemLabel) { * Returns the group label for the given {@link ThingType} and groupId * * @param thingType a non null thingType - * @param groupId a possibly empty, possibly null group ID + * @param groupId a possibly empty, possibly null group ID * @return the group label or null if none */ @Nullable diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/BrainDiscovery.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/BrainDiscovery.java index 8bb09789db4e9..4507984ba1bf2 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/BrainDiscovery.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/BrainDiscovery.java @@ -64,5 +64,4 @@ public interface BrainDiscovery extends AutoCloseable { */ @Override void close(); - } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/MdnsBrainDiscovery.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/MdnsBrainDiscovery.java index 3bdfe84e0f152..1ae286ed0d4c5 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/MdnsBrainDiscovery.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/discovery/MdnsBrainDiscovery.java @@ -92,7 +92,6 @@ public void serviceResolved(@Nullable ServiceEvent event) { considerService(event.getInfo()); } } - }; /** The service context */ diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/BrainStatus.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/BrainStatus.java index 6668431e6e889..a6cce5c49bbb4 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/BrainStatus.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/BrainStatus.java @@ -126,5 +126,4 @@ public String toString() { return "BrainStatus [brainId=" + brainId + ", brainName=" + brainName + ", brainUrl=" + brainUrl + ", callbackUrl=" + callbackUrl + ", connected=" + connected + "]"; } - } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDeviceChannelDirectoryListItem.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDeviceChannelDirectoryListItem.java index 368f1a7eed5d3..a8db614db87d8 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDeviceChannelDirectoryListItem.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDeviceChannelDirectoryListItem.java @@ -42,10 +42,10 @@ public class NeeoDeviceChannelDirectoryListItem { /** * Constructs the list item from the attributes * - * @param itemValue a possibly null, possibly empty item value - * @param title a non-null, non-empty title + * @param itemValue a possibly null, possibly empty item value + * @param title a non-null, non-empty title * @param thumbNailUri a possibly null, possibly empty thumbnail URI - * @param uiAction the non-null UI action + * @param uiAction the non-null UI action */ public NeeoDeviceChannelDirectoryListItem(String itemValue, String title, @Nullable String thumbNailUri, ListUiAction uiAction) { diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryRequest.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryRequest.java index a5f5e370cf609..84abd8b6d2c40 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryRequest.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryRequest.java @@ -86,5 +86,4 @@ public String toString() { return "NeeoDiscoveryListResultPosition [offset=" + offset + ", limit=" + limit + ", browseIdentifier=" + browseIdentifier + "]"; } - } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryResultItem.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryResultItem.java index 510e9869bee89..265b15dd4f3d5 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryResultItem.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryResultItem.java @@ -121,5 +121,4 @@ public String toString() { return "NeeoDiscoveryListResultItem [title=" + title + ", thumbnailUri=" + thumbnailUri + ", browseIdentifier=" + browseIdentifier + ", actionIdentifier=" + actionIdentifier + ", isQueueable=" + isQueueable + "]"; } - } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryResultMeta.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryResultMeta.java index da0e7e7a4d2ab..9ed666c846005 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryResultMeta.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoDirectoryResultMeta.java @@ -121,5 +121,4 @@ public String toString() { return "NeeoDiscoveryListResultMeta [totalItems=" + totalItems + ", totalMatchingItems=" + totalMatchingItems + ", current=" + current + ", previous=" + previous + ", next=" + next + "]"; } - } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoSystemInfo.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoSystemInfo.java index 8b5de11430be6..392f5e5887e84 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoSystemInfo.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/NeeoSystemInfo.java @@ -138,5 +138,4 @@ public boolean equals(@Nullable Object obj) { return StringUtils.equals(hostname, ((NeeoSystemInfo) obj).hostname); } - } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/TokenScore.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/TokenScore.java index d090d86aadc21..7b4008488241d 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/TokenScore.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/models/TokenScore.java @@ -79,5 +79,4 @@ public int compareTo(@Nullable TokenScore o) { } return i; } - } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/serialization/NeeoBrainDeviceSerializer.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/serialization/NeeoBrainDeviceSerializer.java index 508ea0401af2b..5809b62140e42 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/serialization/NeeoBrainDeviceSerializer.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/serialization/NeeoBrainDeviceSerializer.java @@ -240,10 +240,10 @@ public JsonElement serialize(NeeoDevice device, @Nullable Type deviceType, /** * Helper method to create a base element with the given name/label/type/path * - * @param name the element name + * @param name the element name * @param label the element label - * @param type the element type - * @param path the element path + * @param type the element type + * @param path the element path * @return the json object representing the base element */ private JsonObject createBase(String name, String label, String type, String path) { @@ -253,10 +253,10 @@ private JsonObject createBase(String name, String label, String type, String pat /** * Helper method to create a base element with the given name/label/type/path/sensor * - * @param name the element name - * @param label the element label - * @param type the element type - * @param path the element path + * @param name the element name + * @param label the element label + * @param type the element type + * @param path the element path * @param sensor the element sensor * @return the json object representing the base element */ @@ -267,12 +267,12 @@ private JsonObject createBase(String name, String label, String type, String pat /** * Helper method to create a base element with the given name/label/type/path/sensorname/sensor * - * @param name the element name - * @param label the element label - * @param type the element type - * @param path the element path + * @param name the element name + * @param label the element label + * @param type the element type + * @param path the element path * @param sensorName the element sensor name - * @param sensor the element sensor + * @param sensor the element sensor * @return the json object representing the base element */ private JsonObject createBase(String name, String label, String type, String path, @Nullable String sensorName, diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/serialization/NeeoThingUIDSerializer.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/serialization/NeeoThingUIDSerializer.java index aece19495e48b..65317374d86e3 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/serialization/NeeoThingUIDSerializer.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/serialization/NeeoThingUIDSerializer.java @@ -62,5 +62,4 @@ public JsonElement serialize(NeeoThingUID uid, @Nullable Type type, return new JsonPrimitive(uid.getAsString()); } - } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainSearchService.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainSearchService.java index 1a80cb4f78b0c..ca4e26b336142 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainSearchService.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainSearchService.java @@ -121,7 +121,7 @@ public void handleGet(HttpServletRequest req, String[] paths, HttpServletRespons * Does the search of all things and returns the results * * @param queryString the non-null, possibly empty query string - * @param resp the non-null response to write to + * @param resp the non-null response to write to * @throws IOException Signals that an I/O exception has occurred. */ private void doSearch(String queryString, HttpServletResponse resp) throws IOException { @@ -154,7 +154,7 @@ private void doSearch(String queryString, HttpServletResponse resp) throws IOExc /** * Does a query for the NEEO device definition * - * @param id the non-empty (last) search identifier + * @param id the non-empty (last) search identifier * @param resp the non-null response to write to * @throws IOException Signals that an I/O exception has occurred. */ @@ -184,7 +184,7 @@ private void doAdapterDefinition(String id, HttpServletResponse resp) throws IOE /** * Does a query for the NEEO device definition * - * @param id the non-empty (last) search identifier + * @param id the non-empty (last) search identifier * @param resp the non-null response to write to * @throws IOException Signals that an I/O exception has occurred. */ diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainService.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainService.java index 3327b14964e63..59bdd8c8a5373 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainService.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/NeeoBrainService.java @@ -232,7 +232,6 @@ public void handleGet(HttpServletRequest req, String[] paths, HttpServletRespons logger.debug("Unknown/unhandled brain service route (GET): {}", StringUtils.join(paths, '/')); } } - } /** @@ -443,7 +442,6 @@ public boolean apply(@Nullable Event event) { logger.trace("Apply Event: {} --- {} --- {} = {}", event, itemName, isBound, keys); return isBound; } - }; } diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java index 7cd80673955e2..f567ca2ec93d7 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/ThingDashboardService.java @@ -197,7 +197,7 @@ public void handlePost(HttpServletRequest req, String[] paths, HttpServletRespon /** * Helper method to produce an examples rules file and write it to the {@link HttpServletResponse} * - * @param resp the non-null {@link HttpServletResponse} + * @param resp the non-null {@link HttpServletResponse} * @param device the non-null {@link NeeoDevice} * @throws IOException if an IOException occurs while writing the file */ @@ -235,7 +235,7 @@ private void writeExampleRules(HttpServletResponse resp, NeeoDevice device) thro /** * Helper method to append a line of text ot the string builder with a line separator * - * @param sb a non-null string builder + * @param sb a non-null string builder * @param text the non-null, possibly empty text */ private void appendLine(StringBuilder sb, String text) { diff --git a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/models/PathInfo.java b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/models/PathInfo.java index 843a02694d981..302da05f4bee4 100644 --- a/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/models/PathInfo.java +++ b/bundles/org.openhab.io.neeo/src/main/java/org/openhab/io/neeo/internal/servletservices/models/PathInfo.java @@ -171,5 +171,4 @@ public String toString() { + channelNbr + ", componentType=" + componentType + ", componentSubType=" + componentSubType + ", actionValue=" + actionValue + "]"; } - } diff --git a/bundles/org.openhab.io.neeo/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.io.neeo/src/main/resources/ESH-INF/config/config.xml index ff009509b614b..88fd24ff54c0e 100644 --- a/bundles/org.openhab.io.neeo/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.io.neeo/src/main/resources/ESH-INF/config/config.xml @@ -1,5 +1,8 @@ - + diff --git a/bundles/org.openhab.io.openhabcloud/README.md b/bundles/org.openhab.io.openhabcloud/README.md index 094125b25b931..9b703bd6f0644 100644 --- a/bundles/org.openhab.io.openhabcloud/README.md +++ b/bundles/org.openhab.io.openhabcloud/README.md @@ -35,8 +35,10 @@ After installing this add-on, you will find configuration options in the Paper U ![Configuration](contrib/doc/cfg.png) -Please note, that you don't need to expose all your items in this settings dialog. -You just need to expose those items, which you want to be accessible by a third party service. +Please note, that you should not expose all your items in this settings dialog. +Also note that at present this feature is currently turned off. +You just need to expose those items, which you want to be accessible by IFTTT. +This setting has no affect on Alexa or Google Assistant functionality. Alternatively, you can configure the settings in the file `conf/services/openhabcloud.cfg`: diff --git a/bundles/org.openhab.io.openhabcloud/pom.xml b/bundles/org.openhab.io.openhabcloud/pom.xml index be95b546b5b56..d69d6ce1db8c0 100644 --- a/bundles/org.openhab.io.openhabcloud/pom.xml +++ b/bundles/org.openhab.io.openhabcloud/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.openhabcloud diff --git a/bundles/org.openhab.io.openhabcloud/src/main/feature/feature.xml b/bundles/org.openhab.io.openhabcloud/src/main/feature/feature.xml index 02618f5802419..20fb95b9e3830 100644 --- a/bundles/org.openhab.io.openhabcloud/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.openhabcloud/src/main/feature/feature.xml @@ -1,16 +1,16 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:${project.groupId}/openhab-addons-external/${project.version}/cfg/openhabcloud - mvn:org.json/json/20180813 - mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jsr305/3.0.2_1 - mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.okhttp/3.8.1_1 - mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.okio/1.13.0_1 - mvn:org.openhab.osgiify/io.socket.socket.io-client/1.0.0 - mvn:org.openhab.osgiify/io.socket.engine.io-client/1.0.0 - mvn:org.openhab.addons.bundles/org.openhab.io.openhabcloud/${project.version} - + + openhab-runtime-base + mvn:${project.groupId}/openhab-addons-external/${project.version}/cfg/openhabcloud + mvn:org.json/json/20180813 + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jsr305/3.0.2_1 + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.okhttp/3.8.1_1 + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.okio/1.13.0_1 + mvn:org.openhab.osgiify/io.socket.socket.io-client/1.0.0 + mvn:org.openhab.osgiify/io.socket.engine.io-client/1.0.0 + mvn:org.openhab.addons.bundles/org.openhab.io.openhabcloud/${project.version} + diff --git a/bundles/org.openhab.io.openhabcloud/src/main/java/org/openhab/io/openhabcloud/NotificationAction.java b/bundles/org.openhab.io.openhabcloud/src/main/java/org/openhab/io/openhabcloud/NotificationAction.java index 1a9adffba8dc1..e536cafd5706f 100644 --- a/bundles/org.openhab.io.openhabcloud/src/main/java/org/openhab/io/openhabcloud/NotificationAction.java +++ b/bundles/org.openhab.io.openhabcloud/src/main/java/org/openhab/io/openhabcloud/NotificationAction.java @@ -118,5 +118,4 @@ public static void sendBroadcastNotification(String message, String icon, String cloudService.sendBroadcastNotification(message, icon, severity); } } - } diff --git a/bundles/org.openhab.io.openhabcloud/src/main/java/org/openhab/io/openhabcloud/internal/CloudService.java b/bundles/org.openhab.io.openhabcloud/src/main/java/org/openhab/io/openhabcloud/internal/CloudService.java index 9d0257c7db091..5002f4fbaecd0 100644 --- a/bundles/org.openhab.io.openhabcloud/src/main/java/org/openhab/io/openhabcloud/internal/CloudService.java +++ b/bundles/org.openhab.io.openhabcloud/src/main/java/org/openhab/io/openhabcloud/internal/CloudService.java @@ -394,5 +394,4 @@ public void receive(Event event) { cloudClient.sendItemUpdate(ise.getItemName(), ise.getItemState().toString()); } } - } diff --git a/bundles/org.openhab.io.transport.modbus/pom.xml b/bundles/org.openhab.io.transport.modbus/pom.xml index ee142d70aab85..1eeefc0887c2b 100644 --- a/bundles/org.openhab.io.transport.modbus/pom.xml +++ b/bundles/org.openhab.io.transport.modbus/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.transport.modbus @@ -13,6 +15,7 @@ openHAB Add-ons :: Bundles :: IO :: Modbus Transport + gnu.io;version="[3.12,6)" commons-pool2 diff --git a/bundles/org.openhab.io.transport.modbus/src/main/feature/feature.xml b/bundles/org.openhab.io.transport.modbus/src/main/feature/feature.xml index 540940576e548..fda06931c2498 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.transport.modbus/src/main/feature/feature.xml @@ -1,11 +1,11 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab-transport-serial - mvn:org.apache.commons/commons-pool2/2.4.3 - mvn:org.openhab.addons.bundles/org.openhab.io.transport.modbus/${project.version} - + + openhab-runtime-base + openhab-transport-serial + mvn:org.apache.commons/commons-pool2/2.4.3 + mvn:org.openhab.addons.bundles/org.openhab.io.transport.modbus/${project.version} + diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusReadRequestBlueprint.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusReadRequestBlueprint.java index 7b3492737f1b5..f3ad6c59adbf9 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusReadRequestBlueprint.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusReadRequestBlueprint.java @@ -104,5 +104,4 @@ public boolean equals(@Nullable Object obj) { return new EqualsBuilder().append(slaveId, rhs.slaveId).append(functionCode, rhs.functionCode) .append(start, rhs.start).append(length, rhs.length).isEquals(); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusRegisterArray.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusRegisterArray.java index 00867608d165c..90f08a525922a 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusRegisterArray.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusRegisterArray.java @@ -75,5 +75,4 @@ public String toString() { StringBuffer buffer = new StringBuffer(registers.length * 2).append("ModbusRegisterArrayImpl("); return appendHexString(buffer).append(')').toString(); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusWriteCoilRequestBlueprint.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusWriteCoilRequestBlueprint.java index c771990a38ad8..0fa478c531c35 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusWriteCoilRequestBlueprint.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusWriteCoilRequestBlueprint.java @@ -47,7 +47,6 @@ public SingleBitArray(boolean bit) { public String toString() { return "SingleBitArray(bit=" + toBinaryString() + ")"; } - } private int slaveId; diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusWriteRegisterRequestBlueprint.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusWriteRegisterRequestBlueprint.java index bddf9baf8940a..e84f1426a362e 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusWriteRegisterRequestBlueprint.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicModbusWriteRegisterRequestBlueprint.java @@ -101,5 +101,4 @@ public String toString() { .append("functionCode", getFunctionCode()).append("registers", registers).append("maxTries", maxTries) .toString(); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicPollTaskImpl.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicPollTaskImpl.java index d7f06a0dc47dd..b436d72169506 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicPollTaskImpl.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BasicPollTaskImpl.java @@ -95,5 +95,4 @@ public boolean equals(@Nullable Object obj) { return new EqualsBuilder().append(request, rhs.request).append(endpoint, rhs.endpoint) .append(getCallback(), rhs.getCallback()).isEquals(); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BitArray.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BitArray.java index 309a9c20b1420..5b969b03be5f7 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BitArray.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/BitArray.java @@ -85,5 +85,4 @@ default String toBinaryString() { IntStream.range(0, size()).mapToObj(i -> getBit(i) ? '1' : '0').forEach(buffer::append); return buffer.toString(); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusBitUtilities.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusBitUtilities.java index d870755ee51b6..e5834c68077c3 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusBitUtilities.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusBitUtilities.java @@ -412,5 +412,4 @@ public static Optional translateCommand2Boolean(Command command) { } return Optional.empty(); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusConstants.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusConstants.java index 3c7f9a144914b..45cbdd2c133c3 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusConstants.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusConstants.java @@ -99,5 +99,4 @@ public String toString() { .orElseThrow(() -> new IllegalArgumentException("Invalid valueType " + configValueType)); } } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusManager.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusManager.java index a7767568715bd..cfd0d2f5574bb 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusManager.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusManager.java @@ -103,5 +103,4 @@ public void setEndpointPoolConfiguration(ModbusSlaveEndpoint endpoint, * @return set of registered regular polls */ public Set getRegisteredRegularPolls(); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusManagerListener.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusManagerListener.java index 0fd454dd5b12c..8c800ca70bf54 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusManagerListener.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusManagerListener.java @@ -33,5 +33,4 @@ public interface ModbusManagerListener { */ public void onEndpointPoolConfigurationSet(ModbusSlaveEndpoint endpoint, @Nullable EndpointPoolConfiguration configuration); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusReadCallback.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusReadCallback.java index b4b13dc9b1f03..44b1fb34fdce6 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusReadCallback.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusReadCallback.java @@ -46,5 +46,4 @@ public interface ModbusReadCallback extends ModbusCallback { * {@link ModbusUnexpectedTransactionIdException} or {@link ModbusTransportException}. */ void onError(ModbusReadRequestBlueprint request, Exception error); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusReadRequestBlueprint.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusReadRequestBlueprint.java index 7ee0d7533e098..bf517e7da7e2d 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusReadRequestBlueprint.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusReadRequestBlueprint.java @@ -55,5 +55,4 @@ public interface ModbusReadRequestBlueprint extends ModbusRequestBlueprint { * @see net.wimpi.modbus.Modbus */ public ModbusReadFunctionCode getFunctionCode(); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRegister.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRegister.java index 736e1f453d332..22178b36700d5 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRegister.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRegister.java @@ -74,5 +74,4 @@ default StringBuffer appendHexString(StringBuffer buffer) { } return buffer; } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRegisterArray.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRegisterArray.java index d6207072e06dd..42527279c3489 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRegisterArray.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRegisterArray.java @@ -79,5 +79,4 @@ default StringBuffer appendHexString(StringBuffer buffer) { }); return buffer; } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRequestBlueprint.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRequestBlueprint.java index 01391f6725f0d..096ce85c040e3 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRequestBlueprint.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusRequestBlueprint.java @@ -60,5 +60,4 @@ public default int getProtocolID() { * @return number of maximum tries */ public int getMaxTries(); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusResponse.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusResponse.java index ff16114f7be65..d135016a588c0 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusResponse.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusResponse.java @@ -33,5 +33,4 @@ public interface ModbusResponse { * @return function code of the response */ public int getFunctionCode(); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusSlaveErrorResponseException.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusSlaveErrorResponseException.java index fdf01e4029731..d2f89d15ac9b8 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusSlaveErrorResponseException.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusSlaveErrorResponseException.java @@ -103,5 +103,4 @@ public abstract class ModbusSlaveErrorResponseException extends ModbusTransportE * @return the Modbus exception code that happened */ public abstract int getExceptionCode(); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusSlaveIOException.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusSlaveIOException.java index 245da4a8684b4..8ea22f7a6de57 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusSlaveIOException.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusSlaveIOException.java @@ -24,5 +24,4 @@ public class ModbusSlaveIOException extends ModbusTransportException { private static final long serialVersionUID = -8568199166837844463L; - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusTransportException.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusTransportException.java index 4b77fc7cab4be..9f9c0e78ef196 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusTransportException.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusTransportException.java @@ -24,5 +24,4 @@ public class ModbusTransportException extends Exception { private static final long serialVersionUID = 1684767401685843339L; - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedResponseFunctionCodeException.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedResponseFunctionCodeException.java index 09577459c6547..b4000cc8496b7 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedResponseFunctionCodeException.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedResponseFunctionCodeException.java @@ -30,7 +30,6 @@ public class ModbusUnexpectedResponseFunctionCodeException extends ModbusTranspo public ModbusUnexpectedResponseFunctionCodeException(int requestFunctionCode, int responseFunctionCode) { this.requestFunctionCode = requestFunctionCode; this.responseFunctionCode = responseFunctionCode; - } @Override @@ -45,5 +44,4 @@ public String toString() { "ModbusUnexpectedResponseFunctionCodeException(requestFunctionCode=%d, responseFunctionCode=%d)", requestFunctionCode, responseFunctionCode); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedResponseSizeException.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedResponseSizeException.java index 94f7ec5e2c210..62d0101dd34ab 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedResponseSizeException.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedResponseSizeException.java @@ -30,7 +30,6 @@ public class ModbusUnexpectedResponseSizeException extends ModbusTransportExcept public ModbusUnexpectedResponseSizeException(int requestSize, int responseSize) { this.requestSize = requestSize; this.responseSize = responseSize; - } @Override @@ -44,5 +43,4 @@ public String toString() { return String.format("ModbusUnexpectedResponseSizeException(requestFunctionCode=%d, responseFunctionCode=%d)", requestSize, responseSize); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedTransactionIdException.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedTransactionIdException.java index 264c8524083b8..183a001198d44 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedTransactionIdException.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusUnexpectedTransactionIdException.java @@ -30,7 +30,6 @@ public class ModbusUnexpectedTransactionIdException extends ModbusTransportExcep public ModbusUnexpectedTransactionIdException(int requestId, int responseId) { this.requestId = requestId; this.responseId = responseId; - } @Override @@ -53,5 +52,4 @@ public int getRequestId() { public int getResponseId() { return responseId; } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteCallback.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteCallback.java index 534ffd6ab844c..7003a483e3d7e 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteCallback.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteCallback.java @@ -42,5 +42,4 @@ public interface ModbusWriteCallback extends ModbusCallback { * @param response response matching the write request */ void onWriteResponse(ModbusWriteRequestBlueprint request, ModbusResponse response); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteFunctionCode.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteFunctionCode.java index 0fa99a5b75575..9bc160bc48432 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteFunctionCode.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteFunctionCode.java @@ -56,5 +56,4 @@ public int getFunctionCode() { return Stream.of(ModbusWriteFunctionCode.values()).filter(v -> v.getFunctionCode() == functionCode).findFirst() .orElseThrow(() -> new IllegalArgumentException("Invalid functionCode")); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteRequestBlueprint.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteRequestBlueprint.java index 2c310f0b14a11..f79840c32765a 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteRequestBlueprint.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteRequestBlueprint.java @@ -89,5 +89,4 @@ public default int getProtocolID() { * @param visitor */ public void accept(ModbusWriteRequestBlueprintVisitor visitor); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteRequestBlueprintVisitor.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteRequestBlueprintVisitor.java index 02302f125cad6..ab24d4cccac8b 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteRequestBlueprintVisitor.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/ModbusWriteRequestBlueprintVisitor.java @@ -37,5 +37,4 @@ public interface ModbusWriteRequestBlueprintVisitor { * @param blueprint */ public void visit(ModbusWriteRegisterRequestBlueprint blueprint); - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/EndpointPoolConfiguration.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/EndpointPoolConfiguration.java index 843ba6d857470..44f1cbfb6fa3a 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/EndpointPoolConfiguration.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/EndpointPoolConfiguration.java @@ -139,5 +139,4 @@ public boolean equals(@Nullable Object obj) { .append(connectMaxTries, rhs.connectMaxTries).append(reconnectAfterMillis, rhs.reconnectAfterMillis) .append(connectTimeoutMillis, rhs.connectTimeoutMillis).isEquals(); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/ModbusTCPSlaveEndpoint.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/ModbusTCPSlaveEndpoint.java index b6f844bfa3c7a..177fa538810d4 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/ModbusTCPSlaveEndpoint.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/ModbusTCPSlaveEndpoint.java @@ -31,5 +31,4 @@ public ModbusTCPSlaveEndpoint(String address, int port) { public R accept(ModbusSlaveEndpointVisitor factory) { return factory.visit(this); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/ModbusUDPSlaveEndpoint.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/ModbusUDPSlaveEndpoint.java index e8557828fcb73..33499980ac019 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/ModbusUDPSlaveEndpoint.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/endpoint/ModbusUDPSlaveEndpoint.java @@ -31,5 +31,4 @@ public ModbusUDPSlaveEndpoint(String address, int port) { public R accept(ModbusSlaveEndpointVisitor factory) { return factory.visit(this); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/BitArrayWrappingBitVector.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/BitArrayWrappingBitVector.java index ce7e2c3eadaeb..ffc89bcec71bc 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/BitArrayWrappingBitVector.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/BitArrayWrappingBitVector.java @@ -66,5 +66,4 @@ public String toString() { public boolean equals(@Nullable Object obj) { return sizeAndValuesEquals(obj); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusLibraryWrapper.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusLibraryWrapper.java index 73494557f605b..0cea5684f06f9 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusLibraryWrapper.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusLibraryWrapper.java @@ -324,5 +324,4 @@ public static void invokeCallbackWithResponse(ModbusReadRequestBlueprint request response); } } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusManagerImpl.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusManagerImpl.java index 9aa4942d018c4..dbf50dcd6aecc 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusManagerImpl.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusManagerImpl.java @@ -117,7 +117,6 @@ private interface ModbusOperation { public void accept(AggregateStopWatch timer, T task, ModbusSlaveConnection connection) throws ModbusException, IIOException, ModbusUnexpectedTransactionIdException, ModbusUnexpectedResponseFunctionCodeException, ModbusUnexpectedResponseSizeException; - } /** @@ -368,7 +367,6 @@ public void onSwallowException(@Nullable Exception e) { Optional.ofNullable(e).map(ex -> ex.getClass().getSimpleName()).orElse(""), Optional.ofNullable(e).map(ex -> ex.getMessage()).orElse(""), e); } - }); connectionPool = genericKeyedObjectPool; this.connectionFactory = connectionFactory; @@ -959,5 +957,4 @@ private void logTaskQueueInfo() { pollMonitorLogger.trace(""); } } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusResponseImpl.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusResponseImpl.java index 7857cbccbce5b..13a853366a7c5 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusResponseImpl.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/ModbusResponseImpl.java @@ -41,5 +41,4 @@ public int getFunctionCode() { public String toString() { return String.format("ModbusResponseImpl(responseFC=%d)", responseFunctionCode); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/RegisterArrayWrappingInputRegister.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/RegisterArrayWrappingInputRegister.java index 1816ebe47fde9..49e30a12f78ce 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/RegisterArrayWrappingInputRegister.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/RegisterArrayWrappingInputRegister.java @@ -58,7 +58,6 @@ public String toString() { buffer.append("uint16=").append(toUnsignedShort()).append(", hex="); return appendHexString(buffer).append(')').toString(); } - } private InputRegister[] wrapped; @@ -86,5 +85,4 @@ public String toString() { StringBuffer buffer = new StringBuffer(wrapped.length * 2).append("RegisterArrayWrappingInputRegister("); return appendHexString(buffer).append(')').toString(); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/SimpleStopWatch.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/SimpleStopWatch.java index 0e1a95f41199c..6bedf4c81905c 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/SimpleStopWatch.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/SimpleStopWatch.java @@ -171,5 +171,4 @@ public void timeConsumer(Consumer consumer, T parameter) { this.suspend(); } } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/pooling/ModbusSlaveConnectionFactoryImpl.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/pooling/ModbusSlaveConnectionFactoryImpl.java index 814567e1b87b2..b897ee4da1a8e 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/pooling/ModbusSlaveConnectionFactoryImpl.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/internal/pooling/ModbusSlaveConnectionFactoryImpl.java @@ -75,7 +75,6 @@ public long getLastConnected() { public void setLastConnected(long lastConnected) { this.lastConnected = lastConnected; } - } private final Logger logger = LoggerFactory.getLogger(ModbusSlaveConnectionFactoryImpl.class); @@ -344,5 +343,4 @@ public static long waitAtleast(@Nullable Long lastOperation, long waitMillis) th public void disconnectOnReturn(ModbusSlaveEndpoint endpoint, long disconnectBeforeConnectedMillis) { disconnectIfConnectedBefore.put(endpoint, disconnectBeforeConnectedMillis); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/json/WriteRequestJsonUtilities.java b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/json/WriteRequestJsonUtilities.java index ca39ebd0d084f..78816e8f7f8f9 100644 --- a/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/json/WriteRequestJsonUtilities.java +++ b/bundles/org.openhab.io.transport.modbus/src/main/java/org/openhab/io/transport/modbus/json/WriteRequestJsonUtilities.java @@ -206,5 +206,4 @@ private static ModbusWriteRequestBlueprint constructBluerint(int unitId, @Nullab throw new IllegalArgumentException("Unknown function code"); } } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesCommandToRegistersTest.java b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesCommandToRegistersTest.java index 7fc332cff6dd1..8e66e97dfe921 100644 --- a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesCommandToRegistersTest.java +++ b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesCommandToRegistersTest.java @@ -292,7 +292,6 @@ ValueType.UINT64_SWAP, shorts(0x0, 0x0, 0x8, 0x0), }, // should pick the low 64 bits ValueType.UINT64_SWAP, shorts(0x7909, 0x772E, 0xBBB7, 0xDFC5), }) .collect(Collectors.toList())); - } @SuppressWarnings({ "unchecked", "rawtypes" }) diff --git a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesExtractStateFromRegistersTest.java b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesExtractStateFromRegistersTest.java index 40684081722f2..d1688680cd565 100644 --- a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesExtractStateFromRegistersTest.java +++ b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesExtractStateFromRegistersTest.java @@ -382,7 +382,6 @@ ValueType.INT64_SWAP, shortArrayToRegisterArray(0x0, 0x0, 0x8, 0x0), 0 }, new DecimalType("16124500437522872585"), ValueType.UINT64_SWAP, shortArrayToRegisterArray(0x7909, 0x772E, 0xBBB7, 0xDFC5), 0 }) .collect(Collectors.toList())); - } @SuppressWarnings({ "unchecked", "rawtypes" }) diff --git a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesExtractStringFromRegistersTest.java b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesExtractStringFromRegistersTest.java index 47c570c403abc..292cf46912691 100644 --- a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesExtractStringFromRegistersTest.java +++ b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/BitUtilitiesExtractStringFromRegistersTest.java @@ -112,5 +112,4 @@ public void testExtractStringFromRegisters() { assertThat(String.format("registers=%s, index=%d, length=%d", registers, index, length), actualState, is(equalTo(expectedResult))); } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/IntegrationTestSupport.java b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/IntegrationTestSupport.java index 88de18d286b15..84ffb85de4db7 100644 --- a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/IntegrationTestSupport.java +++ b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/IntegrationTestSupport.java @@ -164,7 +164,6 @@ public long getAsLong() { public void tearDown() { stopServer(); modbusManager.close(); - } protected void waitForRequests(int expectedRequestCount) { @@ -315,7 +314,6 @@ public class TCPSlaveConnectionFactoryImpl implements TCPSlaveConnectionFactory public TCPSlaveConnection create(Socket socket) { return new TCPSlaveConnection(socket, new SpyingModbusTCPTransportFactory()); } - } public class UDPSlaveTerminalFactoryImpl implements UDPSlaveTerminalFactory { @@ -326,7 +324,6 @@ public UDPSlaveTerminal create(InetAddress interfac, int port) { terminal.setLocalPort(port); return terminal; } - } public class SerialConnectionFactoryImpl implements SerialConnectionFactory { @@ -358,5 +355,4 @@ public void close() { deactivate(); } } - } diff --git a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/ResultCaptor.java b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/ResultCaptor.java index 04caa7315ae75..75c9a696505a2 100644 --- a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/ResultCaptor.java +++ b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/ResultCaptor.java @@ -1,53 +1,52 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.io.transport.modbus.test; - -import java.util.ArrayList; -import java.util.function.LongSupplier; - -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -/** - * @author Sami Salonen - Initial contribution - * - * @param - */ -public class ResultCaptor implements Answer { - - private ArrayList results = new ArrayList<>(); - private LongSupplier longSupplier; - - public ResultCaptor(LongSupplier longSupplier) { - this.longSupplier = longSupplier; - - } - - public ArrayList getAllReturnValues() { - return results; - } - - @SuppressWarnings("unchecked") - @Override - public T answer(InvocationOnMock invocationOnMock) throws Throwable { - T result = (T) invocationOnMock.callRealMethod(); - synchronized (this.results) { - results.add(result); - } - long wait = longSupplier.getAsLong(); - if (wait > 0) { - Thread.sleep(wait); - } - return result; - } -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.io.transport.modbus.test; + +import java.util.ArrayList; +import java.util.function.LongSupplier; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +/** + * @author Sami Salonen - Initial contribution + * + * @param + */ +public class ResultCaptor implements Answer { + + private ArrayList results = new ArrayList<>(); + private LongSupplier longSupplier; + + public ResultCaptor(LongSupplier longSupplier) { + this.longSupplier = longSupplier; + } + + public ArrayList getAllReturnValues() { + return results; + } + + @SuppressWarnings("unchecked") + @Override + public T answer(InvocationOnMock invocationOnMock) throws Throwable { + T result = (T) invocationOnMock.callRealMethod(); + synchronized (this.results) { + results.add(result); + } + long wait = longSupplier.getAsLong(); + if (wait > 0) { + Thread.sleep(wait); + } + return result; + } +} diff --git a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/SmokeTest.java b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/SmokeTest.java index 1ef816b2a1af9..65f580b52ea10 100644 --- a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/SmokeTest.java +++ b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/SmokeTest.java @@ -904,7 +904,6 @@ public void onEndpointPoolConfigurationSet(ModbusSlaveEndpoint endpoint, assertThat(unexpectedCount.get(), is(equalTo(0))); assertThat(expectedCount.get(), is(equalTo(2))); assertThat(callbackCalled.getCount(), is(equalTo(0L))); - } @Test @@ -922,6 +921,5 @@ public void testGetRegisteredRegularPolls() { modbusManager.unregisterRegularPoll(task); assertThat(modbusManager.getRegisteredRegularPolls(), is(equalTo(Stream.of(task2).collect(Collectors.toSet())))); - } } diff --git a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/WriteRequestJsonUtilitiesTest.java b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/WriteRequestJsonUtilitiesTest.java index f525a4d288e15..48343a2fa5501 100644 --- a/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/WriteRequestJsonUtilitiesTest.java +++ b/bundles/org.openhab.io.transport.modbus/src/test/java/org/openhab/io/transport/modbus/test/WriteRequestJsonUtilitiesTest.java @@ -168,5 +168,4 @@ public void testNumber() { public void testEmptyList() { assertThat(WriteRequestJsonUtilities.fromJson(3, "[]").size(), is(equalTo(0))); } - } diff --git a/bundles/org.openhab.io.webaudio/pom.xml b/bundles/org.openhab.io.webaudio/pom.xml index 166e84c6eb522..a50ab906b936a 100644 --- a/bundles/org.openhab.io.webaudio/pom.xml +++ b/bundles/org.openhab.io.webaudio/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.io.webaudio diff --git a/bundles/org.openhab.io.webaudio/src/main/feature/feature.xml b/bundles/org.openhab.io.webaudio/src/main/feature/feature.xml index d28a67a69aba3..e30135fe127d0 100644 --- a/bundles/org.openhab.io.webaudio/src/main/feature/feature.xml +++ b/bundles/org.openhab.io.webaudio/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.io.webaudio/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.io.webaudio/${project.version} + diff --git a/bundles/org.openhab.io.webaudio/src/main/java/org/openhab/io/webaudio/internal/WebAudioAudioSink.java b/bundles/org.openhab.io.webaudio/src/main/java/org/openhab/io/webaudio/internal/WebAudioAudioSink.java index 060eb656a0ff0..174aed7c27f64 100644 --- a/bundles/org.openhab.io.webaudio/src/main/java/org/openhab/io/webaudio/internal/WebAudioAudioSink.java +++ b/bundles/org.openhab.io.webaudio/src/main/java/org/openhab/io/webaudio/internal/WebAudioAudioSink.java @@ -136,5 +136,4 @@ protected void setAudioHTTPServer(AudioHTTPServer audioHTTPServer) { protected void unsetAudioHTTPServer(AudioHTTPServer audioHTTPServer) { this.audioHTTPServer = null; } - } diff --git a/bundles/org.openhab.io.webaudio/src/main/java/org/openhab/io/webaudio/internal/WebAudioEventFactory.java b/bundles/org.openhab.io.webaudio/src/main/java/org/openhab/io/webaudio/internal/WebAudioEventFactory.java index 715006037bed0..8a9902c2cd00b 100644 --- a/bundles/org.openhab.io.webaudio/src/main/java/org/openhab/io/webaudio/internal/WebAudioEventFactory.java +++ b/bundles/org.openhab.io.webaudio/src/main/java/org/openhab/io/webaudio/internal/WebAudioEventFactory.java @@ -56,5 +56,4 @@ public static PlayURLEvent createPlayURLEvent(String url) { String payload = serializePayload(url); return new PlayURLEvent(PLAY_URL_TOPIC, payload, url); } - } diff --git a/bundles/org.openhab.transform.bin2json/pom.xml b/bundles/org.openhab.transform.bin2json/pom.xml index b63c5512da759..8ec75731c4c86 100644 --- a/bundles/org.openhab.transform.bin2json/pom.xml +++ b/bundles/org.openhab.transform.bin2json/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.bin2json diff --git a/bundles/org.openhab.transform.bin2json/src/main/feature/feature.xml b/bundles/org.openhab.transform.bin2json/src/main/feature/feature.xml index d2b47cabbeba0..1ba9cc0ccf77b 100644 --- a/bundles/org.openhab.transform.bin2json/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.bin2json/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.transform.bin2json/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.transform.bin2json/${project.version} + diff --git a/bundles/org.openhab.transform.exec/pom.xml b/bundles/org.openhab.transform.exec/pom.xml index 5ae09c7822b4b..666dd7953bd3b 100644 --- a/bundles/org.openhab.transform.exec/pom.xml +++ b/bundles/org.openhab.transform.exec/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.exec diff --git a/bundles/org.openhab.transform.exec/src/main/feature/feature.xml b/bundles/org.openhab.transform.exec/src/main/feature/feature.xml index f75cafe2c918d..c4960a9139ddc 100644 --- a/bundles/org.openhab.transform.exec/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.exec/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:${project.groupId}/openhab-addons-external/${project.version}/cfg/exec.whitelist - mvn:org.openhab.addons.bundles/org.openhab.transform.exec/${project.version} - + + openhab-runtime-base + mvn:${project.groupId}/openhab-addons-external/${project.version}/cfg/exec.whitelist + mvn:org.openhab.addons.bundles/org.openhab.transform.exec/${project.version} + diff --git a/bundles/org.openhab.transform.exec/src/main/java/org/openhab/transform/exec/internal/ExecTransformationService.java b/bundles/org.openhab.transform.exec/src/main/java/org/openhab/transform/exec/internal/ExecTransformationService.java index bcc6a70c37846..107d5eb3c977d 100644 --- a/bundles/org.openhab.transform.exec/src/main/java/org/openhab/transform/exec/internal/ExecTransformationService.java +++ b/bundles/org.openhab.transform.exec/src/main/java/org/openhab/transform/exec/internal/ExecTransformationService.java @@ -39,12 +39,14 @@ public class ExecTransformationService implements TransformationService { @Activate public ExecTransformationService( @Reference ExecTransformationWhitelistWatchService execTransformationWhitelistWatchService) { - this.execTransformationWhitelistWatchService = execTransformationWhitelistWatchService; } + this.execTransformationWhitelistWatchService = execTransformationWhitelistWatchService; + } /** * Transforms the input source by the command line. * - * @param commandLine the command to execute. Command line should contain %s string, which will be replaced by the input data. + * @param commandLine the command to execute. Command line should contain %s string, which will be replaced by the + * input data. * @param source the input to transform */ @Override diff --git a/bundles/org.openhab.transform.exec/src/main/resources/ESH-INF/config/execProfile.xml b/bundles/org.openhab.transform.exec/src/main/resources/ESH-INF/config/execProfile.xml index 014500d2847a7..23c64ab60a91e 100644 --- a/bundles/org.openhab.transform.exec/src/main/resources/ESH-INF/config/execProfile.xml +++ b/bundles/org.openhab.transform.exec/src/main/resources/ESH-INF/config/execProfile.xml @@ -7,7 +7,8 @@ - Command to be executed on the command line. It should contain %s which will be substituted with the state. + Command to be executed on the command line. It should contain %s which will be substituted with the + state. diff --git a/bundles/org.openhab.transform.javascript/pom.xml b/bundles/org.openhab.transform.javascript/pom.xml index a7b9f69807520..2ccaadb8d3407 100644 --- a/bundles/org.openhab.transform.javascript/pom.xml +++ b/bundles/org.openhab.transform.javascript/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.javascript diff --git a/bundles/org.openhab.transform.javascript/src/main/feature/feature.xml b/bundles/org.openhab.transform.javascript/src/main/feature/feature.xml index 4081672ac78a1..9c356183270e1 100644 --- a/bundles/org.openhab.transform.javascript/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.javascript/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.transform.javascript/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.transform.javascript/${project.version} + diff --git a/bundles/org.openhab.transform.javascript/src/main/java/org/openhab/transform/javascript/internal/JavaScriptTransformationService.java b/bundles/org.openhab.transform.javascript/src/main/java/org/openhab/transform/javascript/internal/JavaScriptTransformationService.java index 605374f2e5080..074cf480815f7 100644 --- a/bundles/org.openhab.transform.javascript/src/main/java/org/openhab/transform/javascript/internal/JavaScriptTransformationService.java +++ b/bundles/org.openhab.transform.javascript/src/main/java/org/openhab/transform/javascript/internal/JavaScriptTransformationService.java @@ -55,9 +55,9 @@ public void unsetJavaScriptEngineManager(JavaScriptEngineManager manager) { * transformations one should use subfolders. * * @param filename the name of the file which contains the Java script - * transformation rule. Transformation service inject input - * (source) to 'input' variable. - * @param source the input to transform + * transformation rule. Transformation service inject input + * (source) to 'input' variable. + * @param source the input to transform */ @Override public @Nullable String transform(String filename, String source) throws TransformationException { diff --git a/bundles/org.openhab.transform.javascript/src/main/resources/ESH-INF/config/javascriptProfile.xml b/bundles/org.openhab.transform.javascript/src/main/resources/ESH-INF/config/javascriptProfile.xml index 21f7df45459f4..75887da9f0d33 100644 --- a/bundles/org.openhab.transform.javascript/src/main/resources/ESH-INF/config/javascriptProfile.xml +++ b/bundles/org.openhab.transform.javascript/src/main/resources/ESH-INF/config/javascriptProfile.xml @@ -7,7 +7,8 @@ - Filename of the JavaScript in the transform folder. The state will be available in the variable \"input\". + Filename of the JavaScript in the transform folder. The state will be available in the variable + \"input\". diff --git a/bundles/org.openhab.transform.jinja/pom.xml b/bundles/org.openhab.transform.jinja/pom.xml index 772adf04c4660..d8b78feb0afab 100644 --- a/bundles/org.openhab.transform.jinja/pom.xml +++ b/bundles/org.openhab.transform.jinja/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.jinja @@ -13,6 +15,18 @@ openHAB Add-ons :: Bundles :: Transformation Service :: Jinja + + com.fasterxml.jackson.core + jackson-databind + 2.9.10 + compile + + + org.javassist + javassist + 3.22.0-GA + compile + org.openhab.osgiify com.hubspot.jinjava.jinjava diff --git a/bundles/org.openhab.transform.jinja/src/main/feature/feature.xml b/bundles/org.openhab.transform.jinja/src/main/feature/feature.xml index d819d8eb53c14..3072b94c7138e 100644 --- a/bundles/org.openhab.transform.jinja/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.jinja/src/main/feature/feature.xml @@ -1,18 +1,19 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab.tp-jackson - mvn:com.google.guava/guava/21.0 - mvn:ch.obermuhlner/big-math/2.1.0 - mvn:org.jsoup/jsoup/1.8.3 - mvn:org.openhab.osgiify/com.google.re2j.re2j/1.2 - mvn:de.odysseus.juel/juel-api/2.2.7 - mvn:de.odysseus.juel/juel-impl/2.2.7 - mvn:org.apache.commons/commons-lang3/3.4 - mvn:org.openhab.osgiify/com.hubspot.jinjava.jinjava/2.5.0 - mvn:org.openhab.addons.bundles/org.openhab.transform.jinja/${project.version} - + + openhab-runtime-base + openhab.tp-jackson + mvn:com.google.guava/guava/21.0 + mvn:ch.obermuhlner/big-math/2.1.0 + mvn:org.jsoup/jsoup/1.8.3 + mvn:org.openhab.osgiify/com.google.re2j.re2j/1.2 + mvn:de.odysseus.juel/juel-api/2.2.7 + mvn:de.odysseus.juel/juel-impl/2.2.7 + mvn:org.apache.commons/commons-lang3/3.4 + mvn:org.javassist/javassist/3.22.0-GA + mvn:org.openhab.osgiify/com.hubspot.jinjava.jinjava/2.5.0 + mvn:org.openhab.addons.bundles/org.openhab.transform.jinja/${project.version} + diff --git a/bundles/org.openhab.transform.jinja/src/main/java/org/openhab/transform/jinja/internal/JinjaTransformationService.java b/bundles/org.openhab.transform.jinja/src/main/java/org/openhab/transform/jinja/internal/JinjaTransformationService.java index 78397b290dc16..000200f236127 100644 --- a/bundles/org.openhab.transform.jinja/src/main/java/org/openhab/transform/jinja/internal/JinjaTransformationService.java +++ b/bundles/org.openhab.transform.jinja/src/main/java/org/openhab/transform/jinja/internal/JinjaTransformationService.java @@ -51,7 +51,7 @@ public class JinjaTransformationService implements TransformationService { * Transforms the input value by Jinja template. * * @param template Jinja template - * @param value String may contain JSON + * @param value String may contain JSON * @throws TransformationException */ @Override diff --git a/bundles/org.openhab.transform.jinja/src/test/java/org/openhab/transform/jinja/internal/JinjaTransformationServiceTest.java b/bundles/org.openhab.transform.jinja/src/test/java/org/openhab/transform/jinja/internal/JinjaTransformationServiceTest.java index a01ef6bb73ea0..d288c6fe4d016 100644 --- a/bundles/org.openhab.transform.jinja/src/test/java/org/openhab/transform/jinja/internal/JinjaTransformationServiceTest.java +++ b/bundles/org.openhab.transform.jinja/src/test/java/org/openhab/transform/jinja/internal/JinjaTransformationServiceTest.java @@ -58,5 +58,4 @@ public void testQuotedStringOnly() throws TransformationException { // Asserts Assert.assertEquals("Hello world!", transformedResponse); } - } diff --git a/bundles/org.openhab.transform.jsonpath/pom.xml b/bundles/org.openhab.transform.jsonpath/pom.xml index c8c5f079f5af1..558ba2f858011 100644 --- a/bundles/org.openhab.transform.jsonpath/pom.xml +++ b/bundles/org.openhab.transform.jsonpath/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.jsonpath diff --git a/bundles/org.openhab.transform.jsonpath/src/main/feature/feature.xml b/bundles/org.openhab.transform.jsonpath/src/main/feature/feature.xml index 06a1176713877..47c5a6bf35d7f 100644 --- a/bundles/org.openhab.transform.jsonpath/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.jsonpath/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.transform.jsonpath/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.transform.jsonpath/${project.version} + diff --git a/bundles/org.openhab.transform.jsonpath/src/main/java/org/openhab/transform/jsonpath/internal/JSonPathTransformationService.java b/bundles/org.openhab.transform.jsonpath/src/main/java/org/openhab/transform/jsonpath/internal/JSonPathTransformationService.java index dc3183bf23bae..118877cd2d99b 100644 --- a/bundles/org.openhab.transform.jsonpath/src/main/java/org/openhab/transform/jsonpath/internal/JSonPathTransformationService.java +++ b/bundles/org.openhab.transform.jsonpath/src/main/java/org/openhab/transform/jsonpath/internal/JSonPathTransformationService.java @@ -47,9 +47,9 @@ public class JSonPathTransformationService implements TransformationService { * Transforms the input source by JSonPath expression. * * @param function JsonPath expression - * @param source String which contains JSON + * @param source String which contains JSON * @throws TransformationException If the JsonPath expression is invalid, a {@link InvalidPathException} is thrown, - * which is encapsulated in a {@link TransformationException}. + * which is encapsulated in a {@link TransformationException}. */ @Override public @Nullable String transform(String jsonPathExpression, String source) throws TransformationException { diff --git a/bundles/org.openhab.transform.map/pom.xml b/bundles/org.openhab.transform.map/pom.xml index d24413a02c52d..1fc57495407c4 100644 --- a/bundles/org.openhab.transform.map/pom.xml +++ b/bundles/org.openhab.transform.map/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.map diff --git a/bundles/org.openhab.transform.map/src/main/feature/feature.xml b/bundles/org.openhab.transform.map/src/main/feature/feature.xml index 140e669efef06..46572683a85f9 100644 --- a/bundles/org.openhab.transform.map/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.map/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.transform.map/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.transform.map/${project.version} + diff --git a/bundles/org.openhab.transform.map/src/main/java/org/openhab/transform/map/internal/MapTransformationService.java b/bundles/org.openhab.transform.map/src/main/java/org/openhab/transform/map/internal/MapTransformationService.java index 263e817b2251f..7eed8d81d3d99 100644 --- a/bundles/org.openhab.transform.map/src/main/java/org/openhab/transform/map/internal/MapTransformationService.java +++ b/bundles/org.openhab.transform.map/src/main/java/org/openhab/transform/map/internal/MapTransformationService.java @@ -69,5 +69,4 @@ protected Properties internalLoadTransform(String filename) throws Transformatio throw new TransformationException("An error occurred while opening file.", e); } } - } diff --git a/bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java b/bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java index f19bdc5d231c2..0552a64a9f07d 100644 --- a/bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java +++ b/bundles/org.openhab.transform.map/src/test/java/org/openhab/transform/map/internal/MapTransformationServiceTest.java @@ -176,5 +176,4 @@ protected void waitForAssert(Callable assertion, int timeout, int sleepTim } assertion.call(); } - } diff --git a/bundles/org.openhab.transform.regex/pom.xml b/bundles/org.openhab.transform.regex/pom.xml index b4cff64c22abc..f51dd7f92e4f4 100644 --- a/bundles/org.openhab.transform.regex/pom.xml +++ b/bundles/org.openhab.transform.regex/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.regex diff --git a/bundles/org.openhab.transform.regex/src/main/feature/feature.xml b/bundles/org.openhab.transform.regex/src/main/feature/feature.xml index abf07d2b42a3e..a04f22bd14ab6 100644 --- a/bundles/org.openhab.transform.regex/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.regex/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.transform.regex/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.transform.regex/${project.version} + diff --git a/bundles/org.openhab.transform.regex/src/main/java/org/openhab/transform/regex/internal/RegExTransformationService.java b/bundles/org.openhab.transform.regex/src/main/java/org/openhab/transform/regex/internal/RegExTransformationService.java index 079ecc42fd5a7..0e20fa21feae9 100644 --- a/bundles/org.openhab.transform.regex/src/main/java/org/openhab/transform/regex/internal/RegExTransformationService.java +++ b/bundles/org.openhab.transform.regex/src/main/java/org/openhab/transform/regex/internal/RegExTransformationService.java @@ -94,5 +94,4 @@ public class RegExTransformationService implements TransformationService { return result; } - } diff --git a/bundles/org.openhab.transform.regex/src/main/resources/ESH-INF/config/regexProfile.xml b/bundles/org.openhab.transform.regex/src/main/resources/ESH-INF/config/regexProfile.xml index e10cde18988a6..aecf47d4560ca 100644 --- a/bundles/org.openhab.transform.regex/src/main/resources/ESH-INF/config/regexProfile.xml +++ b/bundles/org.openhab.transform.regex/src/main/resources/ESH-INF/config/regexProfile.xml @@ -7,7 +7,8 @@ - Regular expression to be applied on the state. Should contain a capture group whose outcome will be the result. For example: .*=(\\d*.\\d*).* extracts the 23.5 from temp=23.5°C + Regular expression to be applied on the state. Should contain a capture group whose outcome will be the + result. For example: .*=(\\d*.\\d*).* extracts the 23.5 from temp=23.5°C diff --git a/bundles/org.openhab.transform.regex/src/test/java/org/openhab/transform/regex/internal/AbstractTransformationServiceTest.java b/bundles/org.openhab.transform.regex/src/test/java/org/openhab/transform/regex/internal/AbstractTransformationServiceTest.java index c34a3fa16ab04..0eb4455ef6127 100644 --- a/bundles/org.openhab.transform.regex/src/test/java/org/openhab/transform/regex/internal/AbstractTransformationServiceTest.java +++ b/bundles/org.openhab.transform.regex/src/test/java/org/openhab/transform/regex/internal/AbstractTransformationServiceTest.java @@ -32,5 +32,4 @@ public abstract class AbstractTransformationServiceTest { + "" + "" + ""; - } diff --git a/bundles/org.openhab.transform.scale/pom.xml b/bundles/org.openhab.transform.scale/pom.xml index 5ba3119b54819..0ec61059aef2d 100644 --- a/bundles/org.openhab.transform.scale/pom.xml +++ b/bundles/org.openhab.transform.scale/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.scale diff --git a/bundles/org.openhab.transform.scale/src/main/feature/feature.xml b/bundles/org.openhab.transform.scale/src/main/feature/feature.xml index 2e5b6444341c1..7ad1d30bdf286 100644 --- a/bundles/org.openhab.transform.scale/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.scale/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.transform.scale/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.transform.scale/${project.version} + diff --git a/bundles/org.openhab.transform.scale/src/main/java/org/openhab/transform/scale/internal/Range.java b/bundles/org.openhab.transform.scale/src/main/java/org/openhab/transform/scale/internal/Range.java index 77599d4aeaec2..99a9589907260 100644 --- a/bundles/org.openhab.transform.scale/src/main/java/org/openhab/transform/scale/internal/Range.java +++ b/bundles/org.openhab.transform.scale/src/main/java/org/openhab/transform/scale/internal/Range.java @@ -109,5 +109,4 @@ public boolean contains(final BigDecimal value) { return true; } - } diff --git a/bundles/org.openhab.transform.scale/src/main/java/org/openhab/transform/scale/internal/ScaleTransformationService.java b/bundles/org.openhab.transform.scale/src/main/java/org/openhab/transform/scale/internal/ScaleTransformationService.java index 101b4d12f0ceb..5e3a5b16095b8 100644 --- a/bundles/org.openhab.transform.scale/src/main/java/org/openhab/transform/scale/internal/ScaleTransformationService.java +++ b/bundles/org.openhab.transform.scale/src/main/java/org/openhab/transform/scale/internal/ScaleTransformationService.java @@ -94,7 +94,7 @@ public Object put(Object key, Object value) { * the range where it fits i.e. [min..max]=value or ]min..max]=value * * @param properties the list of properties defining all the available ranges - * @param source the input to transform + * @param source the input to transform * */ @Override @@ -179,5 +179,4 @@ protected Map internalLoadTransform(String filename) throws Trans throw new TransformationException("An error occurred while opening file.", ex); } } - } diff --git a/bundles/org.openhab.transform.scale/src/test/java/org/openhab/transform/scale/internal/ScaleTransformServiceTest.java b/bundles/org.openhab.transform.scale/src/test/java/org/openhab/transform/scale/internal/ScaleTransformServiceTest.java index 4938f31f86695..a32a786417b67 100644 --- a/bundles/org.openhab.transform.scale/src/test/java/org/openhab/transform/scale/internal/ScaleTransformServiceTest.java +++ b/bundles/org.openhab.transform.scale/src/test/java/org/openhab/transform/scale/internal/ScaleTransformServiceTest.java @@ -146,5 +146,4 @@ public void testTransformAndFormat() throws TransformationException { String transformedResponse = processor.transform(existingscale, source); Assert.assertEquals("Correcte (992) !", transformedResponse); } - } diff --git a/bundles/org.openhab.transform.xpath/pom.xml b/bundles/org.openhab.transform.xpath/pom.xml index 4a1bace5dd7f0..c3da60f00c381 100644 --- a/bundles/org.openhab.transform.xpath/pom.xml +++ b/bundles/org.openhab.transform.xpath/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.xpath diff --git a/bundles/org.openhab.transform.xpath/src/main/feature/feature.xml b/bundles/org.openhab.transform.xpath/src/main/feature/feature.xml index 94b64066b8c7f..e9bbc0de360dd 100644 --- a/bundles/org.openhab.transform.xpath/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.xpath/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.transform.xpath/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.transform.xpath/${project.version} + diff --git a/bundles/org.openhab.transform.xpath/src/main/java/org/openhab/transform/xpath/internal/XPathTransformationService.java b/bundles/org.openhab.transform.xpath/src/main/java/org/openhab/transform/xpath/internal/XPathTransformationService.java index dc4a886210a47..6128c642f440e 100644 --- a/bundles/org.openhab.transform.xpath/src/main/java/org/openhab/transform/xpath/internal/XPathTransformationService.java +++ b/bundles/org.openhab.transform.xpath/src/main/java/org/openhab/transform/xpath/internal/XPathTransformationService.java @@ -81,5 +81,4 @@ public class XPathTransformationService implements TransformationService { } } } - } diff --git a/bundles/org.openhab.transform.xpath/src/main/resources/ESH-INF/config/xpathProfile.xml b/bundles/org.openhab.transform.xpath/src/main/resources/ESH-INF/config/xpathProfile.xml index b25645d887d98..1180fcb2bf8b3 100644 --- a/bundles/org.openhab.transform.xpath/src/main/resources/ESH-INF/config/xpathProfile.xml +++ b/bundles/org.openhab.transform.xpath/src/main/resources/ESH-INF/config/xpathProfile.xml @@ -7,7 +7,8 @@ - XPath expression to be applied on the state: For example: /*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/ + XPath expression to be applied on the state: For example: + /*[name()='PTZStatus']/*[name()='AbsoluteHigh']/*[name()='azimuth']/ diff --git a/bundles/org.openhab.transform.xpath/src/test/java/org/openhab/transform/xpath/internal/AbstractTransformationServiceTest.java b/bundles/org.openhab.transform.xpath/src/test/java/org/openhab/transform/xpath/internal/AbstractTransformationServiceTest.java index cbf6b511d5702..e438c6382554e 100644 --- a/bundles/org.openhab.transform.xpath/src/test/java/org/openhab/transform/xpath/internal/AbstractTransformationServiceTest.java +++ b/bundles/org.openhab.transform.xpath/src/test/java/org/openhab/transform/xpath/internal/AbstractTransformationServiceTest.java @@ -32,5 +32,4 @@ public abstract class AbstractTransformationServiceTest { + "" + "" + ""; - } diff --git a/bundles/org.openhab.transform.xpath/src/test/java/org/openhab/transform/xpath/internal/XPathTransformationServiceTest.java b/bundles/org.openhab.transform.xpath/src/test/java/org/openhab/transform/xpath/internal/XPathTransformationServiceTest.java index 920c6641d45ad..35f106ee0f675 100644 --- a/bundles/org.openhab.transform.xpath/src/test/java/org/openhab/transform/xpath/internal/XPathTransformationServiceTest.java +++ b/bundles/org.openhab.transform.xpath/src/test/java/org/openhab/transform/xpath/internal/XPathTransformationServiceTest.java @@ -38,5 +38,4 @@ public void testTransformByXPath() throws TransformationException { // Asserts assertEquals("8", transformedResponse); } - } diff --git a/bundles/org.openhab.transform.xslt/pom.xml b/bundles/org.openhab.transform.xslt/pom.xml index 03ef5332e88c5..af93f1f664452 100644 --- a/bundles/org.openhab.transform.xslt/pom.xml +++ b/bundles/org.openhab.transform.xslt/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.transform.xslt diff --git a/bundles/org.openhab.transform.xslt/src/main/feature/feature.xml b/bundles/org.openhab.transform.xslt/src/main/feature/feature.xml index 886d7b1718097..fa44e473affdb 100644 --- a/bundles/org.openhab.transform.xslt/src/main/feature/feature.xml +++ b/bundles/org.openhab.transform.xslt/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.transform.xslt/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.transform.xslt/${project.version} + diff --git a/bundles/org.openhab.transform.xslt/src/main/java/org/openhab/transform/xslt/internal/XsltTransformationService.java b/bundles/org.openhab.transform.xslt/src/main/java/org/openhab/transform/xslt/internal/XsltTransformationService.java index 690a8e7e2151b..1fc378c7a5a76 100644 --- a/bundles/org.openhab.transform.xslt/src/main/java/org/openhab/transform/xslt/internal/XsltTransformationService.java +++ b/bundles/org.openhab.transform.xslt/src/main/java/org/openhab/transform/xslt/internal/XsltTransformationService.java @@ -92,5 +92,4 @@ public class XsltTransformationService implements TransformationService { return out.toString(); } - } diff --git a/bundles/org.openhab.transform.xslt/src/test/java/org/openhab/transform/xslt/internal/AbstractTransformationServiceTest.java b/bundles/org.openhab.transform.xslt/src/test/java/org/openhab/transform/xslt/internal/AbstractTransformationServiceTest.java index dd3b343db2381..cf4fb9e7a8af8 100644 --- a/bundles/org.openhab.transform.xslt/src/test/java/org/openhab/transform/xslt/internal/AbstractTransformationServiceTest.java +++ b/bundles/org.openhab.transform.xslt/src/test/java/org/openhab/transform/xslt/internal/AbstractTransformationServiceTest.java @@ -32,5 +32,4 @@ public abstract class AbstractTransformationServiceTest { + "" + "" + ""; - } diff --git a/bundles/org.openhab.transform.xslt/src/test/java/org/openhab/transform/xslt/internal/XsltTransformationServiceTest.java b/bundles/org.openhab.transform.xslt/src/test/java/org/openhab/transform/xslt/internal/XsltTransformationServiceTest.java index d569cae909768..b8e4b57a17413 100644 --- a/bundles/org.openhab.transform.xslt/src/test/java/org/openhab/transform/xslt/internal/XsltTransformationServiceTest.java +++ b/bundles/org.openhab.transform.xslt/src/test/java/org/openhab/transform/xslt/internal/XsltTransformationServiceTest.java @@ -38,5 +38,4 @@ public void testTransformByXSLT() throws TransformationException { // Asserts assertEquals("8", transformedResponse); } - } diff --git a/bundles/org.openhab.voice.googletts/pom.xml b/bundles/org.openhab.voice.googletts/pom.xml index e0b7713cd0094..5796766d546ad 100644 --- a/bundles/org.openhab.voice.googletts/pom.xml +++ b/bundles/org.openhab.voice.googletts/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.voice.googletts diff --git a/bundles/org.openhab.voice.googletts/src/main/feature/feature.xml b/bundles/org.openhab.voice.googletts/src/main/feature/feature.xml index f09b9d8b6482a..6899300967903 100644 --- a/bundles/org.openhab.voice.googletts/src/main/feature/feature.xml +++ b/bundles/org.openhab.voice.googletts/src/main/feature/feature.xml @@ -1,21 +1,21 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.apache.httpcomponents/httpclient-osgi/4.5.5 - mvn:org.apache.httpcomponents/httpcore-osgi/4.4.9 - mvn:org.openhab.osgiify/com.google.api.api-common/1.7.0 - mvn:org.openhab.osgiify/com.google.api.gax/1.42.0 - mvn:org.openhab.osgiify/com.google.auth.google-auth-library-credentials/0.13.0 - mvn:org.openhab.osgiify/com.google.auth.google-auth-library-oauth2-http/0.13.0 - mvn:org.openhab.osgiify/com.google.http-client.google-http-client-jackson2/1.27.0 - mvn:com.fasterxml.jackson.core/jackson-core/2.9.6 - mvn:com.google.guava/guava/20.0 - mvn:com.google.http-client/google-http-client/1.27.0 - mvn:commons-codec/commons-codec/1.10 - mvn:org.threeten/threetenbp/1.3.3 - mvn:org.openhab.addons.bundles/org.openhab.voice.googletts/${project.version} - + + openhab-runtime-base + mvn:org.apache.httpcomponents/httpclient-osgi/4.5.5 + mvn:org.apache.httpcomponents/httpcore-osgi/4.4.9 + mvn:org.openhab.osgiify/com.google.api.api-common/1.7.0 + mvn:org.openhab.osgiify/com.google.api.gax/1.42.0 + mvn:org.openhab.osgiify/com.google.auth.google-auth-library-credentials/0.13.0 + mvn:org.openhab.osgiify/com.google.auth.google-auth-library-oauth2-http/0.13.0 + mvn:org.openhab.osgiify/com.google.http-client.google-http-client-jackson2/1.27.0 + mvn:com.fasterxml.jackson.core/jackson-core/2.9.6 + mvn:com.google.guava/guava/20.0 + mvn:com.google.http-client/google-http-client/1.27.0 + mvn:commons-codec/commons-codec/1.10 + mvn:org.threeten/threetenbp/1.3.3 + mvn:org.openhab.addons.bundles/org.openhab.voice.googletts/${project.version} + diff --git a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/GoogleCloudAPI.java b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/GoogleCloudAPI.java index 57f9624a54a45..c98f132617133 100644 --- a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/GoogleCloudAPI.java +++ b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/GoogleCloudAPI.java @@ -396,5 +396,4 @@ private String getUniqueFilenameForText(String text, String voiceName) { boolean isInitialized() { return initialized; } - } diff --git a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/GoogleTTSConfig.java b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/GoogleTTSConfig.java index 719ba47cc557d..52a9dc3378123 100644 --- a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/GoogleTTSConfig.java +++ b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/GoogleTTSConfig.java @@ -85,13 +85,9 @@ void setPurgeCache(Boolean purgeCache) { @Override public String toString() { - return "GoogleTTSConfig{" + - "serviceAccountKey='" + serviceAccountKey + '\'' + - ", pitch=" + pitch + - ", speakingRate=" + speakingRate + - ", volumeGainDb=" + volumeGainDb + - ", purgeCache=" + purgeCache + - '}'; + return "GoogleTTSConfig{" + "serviceAccountKey='" + serviceAccountKey + '\'' + ", pitch=" + pitch + + ", speakingRate=" + speakingRate + ", volumeGainDb=" + volumeGainDb + ", purgeCache=" + purgeCache + + '}'; } String toConfigString() { diff --git a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/ListVoicesResponse.java b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/ListVoicesResponse.java index 9acf1d643edd0..903a94f2927b3 100644 --- a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/ListVoicesResponse.java +++ b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/ListVoicesResponse.java @@ -37,5 +37,4 @@ public class ListVoicesResponse { public void setVoices(List voices) { this.voices = voices; } - } diff --git a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/SynthesisInput.java b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/SynthesisInput.java index aa9332725ef3f..f3f7a26f85df9 100644 --- a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/SynthesisInput.java +++ b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/SynthesisInput.java @@ -57,5 +57,4 @@ public void setSsml(String ssml) { public void setText(String text) { this.text = text; } - } diff --git a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/SynthesizeSpeechRequest.java b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/SynthesizeSpeechRequest.java index 0bfb00f6915e4..94afe4639cbd1 100644 --- a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/SynthesizeSpeechRequest.java +++ b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/SynthesizeSpeechRequest.java @@ -66,5 +66,4 @@ public void setInput(SynthesisInput input) { public void setVoice(VoiceSelectionParams voice) { this.voice = voice; } - } diff --git a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/Voice.java b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/Voice.java index ff7e3911f4b94..d4976ade9166d 100644 --- a/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/Voice.java +++ b/bundles/org.openhab.voice.googletts/src/main/java/org/openhab/voice/googletts/internal/protocol/Voice.java @@ -72,5 +72,4 @@ public SsmlVoiceGender getSsmlGender() { public void setSsmlGender(SsmlVoiceGender ssmlGender) { this.ssmlGender = ssmlGender; } - } diff --git a/bundles/org.openhab.voice.googletts/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.voice.googletts/src/main/resources/ESH-INF/config/config.xml index 88fe31cd50928..8798c563db237 100644 --- a/bundles/org.openhab.voice.googletts/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.voice.googletts/src/main/resources/ESH-INF/config/config.xml @@ -1,16 +1,17 @@ - + script Google Cloud TTS API service account key. A JSON content is expected here copied from the - downloaded key file. + downloaded key + file. @@ -33,7 +34,8 @@ - Purges the cache e.g. after testing different voice configuration parameters. When enabled the cache is purged once. Make sure to disable this setting again so the cache is maintained after restarts. + Purges the cache e.g. after testing different voice configuration parameters. When enabled the cache is + purged once. Make sure to disable this setting again so the cache is maintained after restarts. false diff --git a/bundles/org.openhab.voice.mactts/pom.xml b/bundles/org.openhab.voice.mactts/pom.xml index 3b49eedc0f5a4..071f2c72bdf4e 100644 --- a/bundles/org.openhab.voice.mactts/pom.xml +++ b/bundles/org.openhab.voice.mactts/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.voice.mactts diff --git a/bundles/org.openhab.voice.mactts/src/main/feature/feature.xml b/bundles/org.openhab.voice.mactts/src/main/feature/feature.xml index d9ea436b913b3..2c848fcaab8e5 100644 --- a/bundles/org.openhab.voice.mactts/src/main/feature/feature.xml +++ b/bundles/org.openhab.voice.mactts/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.voice.mactts/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.voice.mactts/${project.version} + diff --git a/bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java b/bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java index cc7c69da7aecb..9c86110d17093 100644 --- a/bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java +++ b/bundles/org.openhab.voice.mactts/src/main/java/org/openhab/voice/mactts/internal/MacTTSService.java @@ -1,140 +1,139 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.voice.mactts.internal; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Collections; -import java.util.HashSet; -import java.util.Locale; -import java.util.Set; - -import org.apache.commons.io.IOUtils; -import org.eclipse.smarthome.core.audio.AudioException; -import org.eclipse.smarthome.core.audio.AudioFormat; -import org.eclipse.smarthome.core.audio.AudioStream; -import org.eclipse.smarthome.core.voice.TTSException; -import org.eclipse.smarthome.core.voice.TTSService; -import org.eclipse.smarthome.core.voice.Voice; -import org.osgi.service.component.annotations.Component; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This is a TTS service implementation for Mac OS, which simply uses the "say" command from the OS. - * - * @author Kai Kreuzer - Initial contribution and API - * @author Pauli Antilla - * @author Kelly Davis - */ -@Component -public class MacTTSService implements TTSService { - - private final Logger logger = LoggerFactory.getLogger(MacTTSService.class); - - /** - * Set of supported voices - */ - private final Set voices = initVoices(); - - /** - * Set of supported audio formats - */ - private final Set audioFormats = initAudioFormats(); - - @Override - public Set getAvailableVoices() { - return this.voices; - } - - @Override - public Set getSupportedFormats() { - return this.audioFormats; - } - - @Override - public AudioStream synthesize(String text, Voice voice, AudioFormat requestedFormat) throws TTSException { - // Validate arguments - if ((null == text) || text.isEmpty()) { - throw new TTSException("The passed text is null or empty"); - } - if (!this.voices.contains(voice)) { - throw new TTSException("The passed voice is unsupported"); - } - boolean isAudioFormatSupported = false; - for (AudioFormat currentAudioFormat : this.audioFormats) { - if (currentAudioFormat.isCompatible(requestedFormat)) { - isAudioFormatSupported = true; - break; - } - } - if (!isAudioFormatSupported) { - throw new TTSException("The passed AudioFormat is unsupported"); - } - - try { - return new MacTTSAudioStream(text, voice, requestedFormat); - } catch (AudioException e) { - throw new TTSException(e); - } - } - - /** - * Initializes this.voices - * - * @return The voices of this instance - */ - private final Set initVoices() { - Set voices = new HashSet<>(); - InputStreamReader inputStreamReader = null; - BufferedReader bufferedReader = null; - try { - Process process = Runtime.getRuntime().exec("say -v ?"); - inputStreamReader = new InputStreamReader(process.getInputStream()); - bufferedReader = new BufferedReader(inputStreamReader); - - String nextLine; - while ((nextLine = bufferedReader.readLine()) != null) { - voices.add(new MacTTSVoice(nextLine)); - } - } catch (IOException e) { - logger.error("Error while executing the 'say -v ?' command: {}", e.getMessage()); - } finally { - IOUtils.closeQuietly(bufferedReader); - } - return voices; - } - - /** - * Initializes this.audioFormats - * - * @return The audio formats of this instance - */ - private final Set initAudioFormats() { - AudioFormat audioFormat = new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, - null, (long) 44100); - return Collections.singleton(audioFormat); - } - - @Override - public String getId() { - return "mactts"; - } - - @Override - public String getLabel(Locale locale) { - return "macOS TTS"; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.voice.mactts.internal; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Collections; +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; + +import org.apache.commons.io.IOUtils; +import org.eclipse.smarthome.core.audio.AudioException; +import org.eclipse.smarthome.core.audio.AudioFormat; +import org.eclipse.smarthome.core.audio.AudioStream; +import org.eclipse.smarthome.core.voice.TTSException; +import org.eclipse.smarthome.core.voice.TTSService; +import org.eclipse.smarthome.core.voice.Voice; +import org.osgi.service.component.annotations.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is a TTS service implementation for Mac OS, which simply uses the "say" command from the OS. + * + * @author Kai Kreuzer - Initial contribution and API + * @author Pauli Antilla + * @author Kelly Davis + */ +@Component +public class MacTTSService implements TTSService { + + private final Logger logger = LoggerFactory.getLogger(MacTTSService.class); + + /** + * Set of supported voices + */ + private final Set voices = initVoices(); + + /** + * Set of supported audio formats + */ + private final Set audioFormats = initAudioFormats(); + + @Override + public Set getAvailableVoices() { + return this.voices; + } + + @Override + public Set getSupportedFormats() { + return this.audioFormats; + } + + @Override + public AudioStream synthesize(String text, Voice voice, AudioFormat requestedFormat) throws TTSException { + // Validate arguments + if ((null == text) || text.isEmpty()) { + throw new TTSException("The passed text is null or empty"); + } + if (!this.voices.contains(voice)) { + throw new TTSException("The passed voice is unsupported"); + } + boolean isAudioFormatSupported = false; + for (AudioFormat currentAudioFormat : this.audioFormats) { + if (currentAudioFormat.isCompatible(requestedFormat)) { + isAudioFormatSupported = true; + break; + } + } + if (!isAudioFormatSupported) { + throw new TTSException("The passed AudioFormat is unsupported"); + } + + try { + return new MacTTSAudioStream(text, voice, requestedFormat); + } catch (AudioException e) { + throw new TTSException(e); + } + } + + /** + * Initializes this.voices + * + * @return The voices of this instance + */ + private final Set initVoices() { + Set voices = new HashSet<>(); + InputStreamReader inputStreamReader = null; + BufferedReader bufferedReader = null; + try { + Process process = Runtime.getRuntime().exec("say -v ?"); + inputStreamReader = new InputStreamReader(process.getInputStream()); + bufferedReader = new BufferedReader(inputStreamReader); + + String nextLine; + while ((nextLine = bufferedReader.readLine()) != null) { + voices.add(new MacTTSVoice(nextLine)); + } + } catch (IOException e) { + logger.error("Error while executing the 'say -v ?' command: {}", e.getMessage()); + } finally { + IOUtils.closeQuietly(bufferedReader); + } + return voices; + } + + /** + * Initializes this.audioFormats + * + * @return The audio formats of this instance + */ + private final Set initAudioFormats() { + AudioFormat audioFormat = new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, + null, (long) 44100); + return Collections.singleton(audioFormat); + } + + @Override + public String getId() { + return "mactts"; + } + + @Override + public String getLabel(Locale locale) { + return "macOS TTS"; + } +} diff --git a/bundles/org.openhab.voice.marytts/pom.xml b/bundles/org.openhab.voice.marytts/pom.xml index 457e1d0f06b25..d73add22999cf 100644 --- a/bundles/org.openhab.voice.marytts/pom.xml +++ b/bundles/org.openhab.voice.marytts/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.voice.marytts diff --git a/bundles/org.openhab.voice.marytts/src/main/feature/feature.xml b/bundles/org.openhab.voice.marytts/src/main/feature/feature.xml index c7c64026ac2f7..fb0c0e4f8022d 100644 --- a/bundles/org.openhab.voice.marytts/src/main/feature/feature.xml +++ b/bundles/org.openhab.voice.marytts/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:commons-collections/commons-collections/3.2.2 - mvn:org.openhab.addons.bundles/org.openhab.voice.marytts/${project.version} - + + openhab-runtime-base + mvn:commons-collections/commons-collections/3.2.2 + mvn:org.openhab.addons.bundles/org.openhab.voice.marytts/${project.version} + diff --git a/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java b/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java index ff0372ab4ca21..5f147823e04c0 100644 --- a/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java +++ b/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSAudioStream.java @@ -122,8 +122,8 @@ private InputStream getWavHeaderInputStream(int length) throws IOException { header[22] = channel; header[23] = 0; header[24] = (byte) (srate & 0xff); - header[25] = (byte) ((srate >> 8) & 0xff); - header[26] = (byte) ((srate >> 16) & 0xff); + header[25] = (byte) ((srate >> 8) & 0xff); + header[26] = (byte) ((srate >> 16) & 0xff); header[27] = (byte) ((srate >> 24) & 0xff); header[28] = (byte) ((bitrate / 8) & 0xff); header[29] = (byte) (((bitrate / 8) >> 8) & 0xff); diff --git a/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSService.java b/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSService.java index 964a4e39e4468..493a2024fadb9 100644 --- a/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSService.java +++ b/bundles/org.openhab.voice.marytts/src/main/java/org/openhab/voice/marytts/internal/MaryTTSService.java @@ -189,5 +189,4 @@ public String getId() { public String getLabel(Locale locale) { return "MaryTTS"; } - } diff --git a/bundles/org.openhab.voice.picotts/pom.xml b/bundles/org.openhab.voice.picotts/pom.xml index 3ff76168af4f2..e9e0aa7ed1591 100644 --- a/bundles/org.openhab.voice.picotts/pom.xml +++ b/bundles/org.openhab.voice.picotts/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.voice.picotts diff --git a/bundles/org.openhab.voice.picotts/src/main/feature/feature.xml b/bundles/org.openhab.voice.picotts/src/main/feature/feature.xml index 3fb597fe20aaf..2218a82c59cb6 100644 --- a/bundles/org.openhab.voice.picotts/src/main/feature/feature.xml +++ b/bundles/org.openhab.voice.picotts/src/main/feature/feature.xml @@ -1,9 +1,9 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:org.openhab.addons.bundles/org.openhab.voice.picotts/${project.version} - + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.voice.picotts/${project.version} + diff --git a/bundles/org.openhab.voice.picotts/src/main/java/org/openhab/voice/picotts/internal/PicoTTSService.java b/bundles/org.openhab.voice.picotts/src/main/java/org/openhab/voice/picotts/internal/PicoTTSService.java index 50bf1af83f509..0c871e70d7a7a 100644 --- a/bundles/org.openhab.voice.picotts/src/main/java/org/openhab/voice/picotts/internal/PicoTTSService.java +++ b/bundles/org.openhab.voice.picotts/src/main/java/org/openhab/voice/picotts/internal/PicoTTSService.java @@ -1,87 +1,86 @@ -/** - * Copyright (c) 2010-2020 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.voice.picotts.internal; - -import java.util.Collections; -import java.util.Locale; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.eclipse.smarthome.core.audio.AudioException; -import org.eclipse.smarthome.core.audio.AudioFormat; -import org.eclipse.smarthome.core.audio.AudioStream; -import org.eclipse.smarthome.core.voice.TTSException; -import org.eclipse.smarthome.core.voice.TTSService; -import org.eclipse.smarthome.core.voice.Voice; -import org.osgi.service.component.annotations.Component; - -/** - * @author Florian Schmidt - Initial Contribution - */ -@Component -public class PicoTTSService implements TTSService { - private final Set voices = Stream - .of(new PicoTTSVoice("de-DE"), new PicoTTSVoice("en-US"), new PicoTTSVoice("en-GB"), - new PicoTTSVoice("es-ES"), new PicoTTSVoice("fr-FR"), new PicoTTSVoice("it-IT")) - .collect(Collectors.toSet()); - - private final Set audioFormats = Collections.singleton( - new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, null, 16000L)); - - @Override - public Set getAvailableVoices() { - return this.voices; - } - - @Override - public Set getSupportedFormats() { - return this.audioFormats; - } - - @Override - public AudioStream synthesize(String text, Voice voice, AudioFormat requestedFormat) throws TTSException { - if (text == null || text.isEmpty()) { - throw new TTSException("The passed text can not be null or empty"); - } - - if (!this.voices.contains(voice)) { - throw new TTSException("The passed voice is unsupported"); - } - - boolean isAudioFormatSupported = this.audioFormats.stream().anyMatch(audioFormat -> { - return audioFormat.isCompatible(requestedFormat); - }); - - if (!isAudioFormatSupported) { - throw new TTSException("The passed AudioFormat is unsupported"); - } - - try { - return new PicoTTSAudioStream(text, voice, requestedFormat); - } catch (AudioException e) { - throw new TTSException(e); - } - } - - @Override - public String getId() { - return "picotts"; - } - - @Override - public String getLabel(Locale locale) { - return "PicoTTS"; - } - -} +/** + * Copyright (c) 2010-2020 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.voice.picotts.internal; + +import java.util.Collections; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.smarthome.core.audio.AudioException; +import org.eclipse.smarthome.core.audio.AudioFormat; +import org.eclipse.smarthome.core.audio.AudioStream; +import org.eclipse.smarthome.core.voice.TTSException; +import org.eclipse.smarthome.core.voice.TTSService; +import org.eclipse.smarthome.core.voice.Voice; +import org.osgi.service.component.annotations.Component; + +/** + * @author Florian Schmidt - Initial Contribution + */ +@Component +public class PicoTTSService implements TTSService { + private final Set voices = Stream + .of(new PicoTTSVoice("de-DE"), new PicoTTSVoice("en-US"), new PicoTTSVoice("en-GB"), + new PicoTTSVoice("es-ES"), new PicoTTSVoice("fr-FR"), new PicoTTSVoice("it-IT")) + .collect(Collectors.toSet()); + + private final Set audioFormats = Collections.singleton( + new AudioFormat(AudioFormat.CONTAINER_WAVE, AudioFormat.CODEC_PCM_SIGNED, false, 16, null, 16000L)); + + @Override + public Set getAvailableVoices() { + return this.voices; + } + + @Override + public Set getSupportedFormats() { + return this.audioFormats; + } + + @Override + public AudioStream synthesize(String text, Voice voice, AudioFormat requestedFormat) throws TTSException { + if (text == null || text.isEmpty()) { + throw new TTSException("The passed text can not be null or empty"); + } + + if (!this.voices.contains(voice)) { + throw new TTSException("The passed voice is unsupported"); + } + + boolean isAudioFormatSupported = this.audioFormats.stream().anyMatch(audioFormat -> { + return audioFormat.isCompatible(requestedFormat); + }); + + if (!isAudioFormatSupported) { + throw new TTSException("The passed AudioFormat is unsupported"); + } + + try { + return new PicoTTSAudioStream(text, voice, requestedFormat); + } catch (AudioException e) { + throw new TTSException(e); + } + } + + @Override + public String getId() { + return "picotts"; + } + + @Override + public String getLabel(Locale locale) { + return "PicoTTS"; + } +} diff --git a/bundles/org.openhab.voice.pollytts/README.md b/bundles/org.openhab.voice.pollytts/README.md index 71249266e4842..e16db7945a219 100644 --- a/bundles/org.openhab.voice.pollytts/README.md +++ b/bundles/org.openhab.voice.pollytts/README.md @@ -43,6 +43,22 @@ A value of 365 removes files that have been unused for a year. Use "default" to select the system default audio format. The default audio format can be overriden with the value "mp3" or "ogg". + +### Service Configuration via Text files + +Create a new file in `$OPENHAB_ROOT/conf/services` named `pollytts.cfg` + +It's contents should look similar to: + +``` +org.openhab.pollytts:accessKey=ACCESS_KEY_ID +org.openhab.pollytts:secretKey=SECRET_KEY +org.openhab.pollytts:serviceRegion=SERVICE_REGION +org.openhab.pollytts:cacheExpiration=EXPIRATION_IN_DAYS +``` + +These have the same meanings as described in the **Service Configuration** block above. + ## Rule Examples ``` diff --git a/bundles/org.openhab.voice.pollytts/pom.xml b/bundles/org.openhab.voice.pollytts/pom.xml index 0acbbd3cd4e5b..e871fad6bf3d0 100644 --- a/bundles/org.openhab.voice.pollytts/pom.xml +++ b/bundles/org.openhab.voice.pollytts/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.voice.pollytts diff --git a/bundles/org.openhab.voice.pollytts/src/main/feature/feature.xml b/bundles/org.openhab.voice.pollytts/src/main/feature/feature.xml index 1f3f11e31e269..3f542ba82eba3 100644 --- a/bundles/org.openhab.voice.pollytts/src/main/feature/feature.xml +++ b/bundles/org.openhab.voice.pollytts/src/main/feature/feature.xml @@ -1,17 +1,17 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - openhab.tp-jackson - mvn:com.fasterxml.jackson.dataformat/jackson-dataformat-cbor/2.9.9 - mvn:org.apache.httpcomponents/httpcore-osgi/4.4.9 - mvn:org.apache.httpcomponents/httpclient-osgi/4.5.5 - mvn:org.openhab.osgiify/com.amazonaws.aws-java-sdk-core/1.11.490 - mvn:org.openhab.osgiify/com.amazonaws.aws-java-sdk-polly/1.11.490 - mvn:commons-logging/commons-logging/1.2 - mvn:joda-time/joda-time/2.8.1 - mvn:org.openhab.addons.bundles/org.openhab.voice.pollytts/${project.version} - + + openhab-runtime-base + openhab.tp-jackson + mvn:com.fasterxml.jackson.dataformat/jackson-dataformat-cbor/2.9.9 + mvn:org.apache.httpcomponents/httpcore-osgi/4.4.9 + mvn:org.apache.httpcomponents/httpclient-osgi/4.5.5 + mvn:org.openhab.osgiify/com.amazonaws.aws-java-sdk-core/1.11.490 + mvn:org.openhab.osgiify/com.amazonaws.aws-java-sdk-polly/1.11.490 + mvn:commons-logging/commons-logging/1.2 + mvn:joda-time/joda-time/2.8.1 + mvn:org.openhab.addons.bundles/org.openhab.voice.pollytts/${project.version} + diff --git a/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/PollyTTSAudioStream.java b/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/PollyTTSAudioStream.java index 8493f2cb9bc57..cc474e02499ad 100644 --- a/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/PollyTTSAudioStream.java +++ b/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/PollyTTSAudioStream.java @@ -34,5 +34,4 @@ class PollyTTSAudioStream extends FileAudioStream { public PollyTTSAudioStream(File audioFile, AudioFormat format) throws AudioException { super(audioFile, format); } - } diff --git a/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/PollyTTSService.java b/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/PollyTTSService.java index ed4af0bdfac34..910297c5ee6cb 100644 --- a/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/PollyTTSService.java +++ b/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/PollyTTSService.java @@ -236,5 +236,4 @@ public String getId() { public String getLabel(Locale locale) { return "PollyTTS"; } - } diff --git a/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/cloudapi/PollyTTSCloudImpl.java b/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/cloudapi/PollyTTSCloudImpl.java index 275d576ee31bc..ab03072009e31 100644 --- a/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/cloudapi/PollyTTSCloudImpl.java +++ b/bundles/org.openhab.voice.pollytts/src/main/java/org/openhab/voice/pollytts/internal/cloudapi/PollyTTSCloudImpl.java @@ -130,5 +130,4 @@ public InputStream getTextToSpeech(String text, String label, String audioFormat .withVoiceId(voiceID).withOutputFormat(OutputFormat.fromValue(format)); return client.synthesizeSpeech(request).getAudioStream(); } - } diff --git a/bundles/org.openhab.voice.pollytts/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.voice.pollytts/src/main/resources/ESH-INF/config/config.xml index 43b02bacbe732..962cb014255e4 100644 --- a/bundles/org.openhab.voice.pollytts/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.voice.pollytts/src/main/resources/ESH-INF/config/config.xml @@ -43,7 +43,8 @@ - Allows for overriding the system default audio format. "MP3" and "OGG" are the only audio formats that are supported. + Allows for overriding the system default audio format. "MP3" and "OGG" are the only audio formats that + are supported. @@ -54,7 +55,7 @@ - Determines the age in days when unused cached files are purged. + Determines the age in days when unused cached files are purged. Use 0 to disable this functionality. 0 diff --git a/bundles/org.openhab.voice.voicerss/pom.xml b/bundles/org.openhab.voice.voicerss/pom.xml index 1a12289c4e84c..c526e218d3ea0 100644 --- a/bundles/org.openhab.voice.voicerss/pom.xml +++ b/bundles/org.openhab.voice.voicerss/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.bundles org.openhab.addons.reactor.bundles - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.voice.voicerss diff --git a/bundles/org.openhab.voice.voicerss/src/main/feature/feature.xml b/bundles/org.openhab.voice.voicerss/src/main/feature/feature.xml index 57ff9a976e519..1300eb7334fb1 100644 --- a/bundles/org.openhab.voice.voicerss/src/main/feature/feature.xml +++ b/bundles/org.openhab.voice.voicerss/src/main/feature/feature.xml @@ -1,10 +1,10 @@ - mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features - - openhab-runtime-base - mvn:${project.groupId}/openhab-addons-external/${project.version}/cfg/voicerss - mvn:org.openhab.addons.bundles/org.openhab.voice.voicerss/${project.version} - + + openhab-runtime-base + mvn:${project.groupId}/openhab-addons-external/${project.version}/cfg/voicerss + mvn:org.openhab.addons.bundles/org.openhab.voice.voicerss/${project.version} + diff --git a/bundles/org.openhab.voice.voicerss/src/main/java/org/openhab/voice/voicerss/internal/VoiceRSSAudioStream.java b/bundles/org.openhab.voice.voicerss/src/main/java/org/openhab/voice/voicerss/internal/VoiceRSSAudioStream.java index 92e9738179af1..5e85d2c8b9568 100644 --- a/bundles/org.openhab.voice.voicerss/src/main/java/org/openhab/voice/voicerss/internal/VoiceRSSAudioStream.java +++ b/bundles/org.openhab.voice.voicerss/src/main/java/org/openhab/voice/voicerss/internal/VoiceRSSAudioStream.java @@ -32,5 +32,4 @@ class VoiceRSSAudioStream extends FileAudioStream { public VoiceRSSAudioStream(File audioFile, AudioFormat format) throws AudioException { super(audioFile, format); } - } diff --git a/bundles/org.openhab.voice.voicerss/src/main/java/org/openhab/voice/voicerss/internal/cloudapi/VoiceRSSCloudImpl.java b/bundles/org.openhab.voice.voicerss/src/main/java/org/openhab/voice/voicerss/internal/cloudapi/VoiceRSSCloudImpl.java index 5f843d7507cff..277218450c287 100644 --- a/bundles/org.openhab.voice.voicerss/src/main/java/org/openhab/voice/voicerss/internal/cloudapi/VoiceRSSCloudImpl.java +++ b/bundles/org.openhab.voice.voicerss/src/main/java/org/openhab/voice/voicerss/internal/cloudapi/VoiceRSSCloudImpl.java @@ -177,5 +177,4 @@ private String createURL(String apiKey, String text, String locale, String audio return "http://api.voicerss.org/?key=" + apiKey + "&hl=" + locale + "&c=" + audioFormat + "&f=44khz_16bit_mono&src=" + encodedMsg; } - } diff --git a/bundles/org.openhab.voice.voicerss/src/main/resources/ESH-INF/config/config.xml b/bundles/org.openhab.voice.voicerss/src/main/resources/ESH-INF/config/config.xml index 4f0c3ce506e40..381e2db96bee7 100644 --- a/bundles/org.openhab.voice.voicerss/src/main/resources/ESH-INF/config/config.xml +++ b/bundles/org.openhab.voice.voicerss/src/main/resources/ESH-INF/config/config.xml @@ -8,7 +8,8 @@ - The API Key to get access to http://www.voicerss.org. You need to register with at least a free account to get an API key. + The API Key to get access to http://www.voicerss.org. You need to register with at least a free account + to get an API key. diff --git a/bundles/pom.xml b/bundles/pom.xml index 42565f154f1d1..18eb9219efa96 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons org.openhab.addons.reactor - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.addons.bundles @@ -40,6 +42,7 @@ org.openhab.binding.adorne org.openhab.binding.airquality org.openhab.binding.airvisualnode + org.openhab.binding.alarmdecoder org.openhab.binding.allplay org.openhab.binding.amazondashbutton org.openhab.binding.amazonechocontrol @@ -66,6 +69,7 @@ org.openhab.binding.coolmasternet org.openhab.binding.coronastats org.openhab.binding.daikin + org.openhab.binding.danfossairunit org.openhab.binding.darksky org.openhab.binding.deconz org.openhab.binding.denonmarantz @@ -80,6 +84,8 @@ org.openhab.binding.dwdunwetter org.openhab.binding.ecobee org.openhab.binding.elerotransmitterstick + org.openhab.binding.energenie + org.openhab.binding.enigma2 org.openhab.binding.enocean org.openhab.binding.enturno org.openhab.binding.etherrain @@ -109,6 +115,7 @@ org.openhab.binding.hydrawise org.openhab.binding.hyperion org.openhab.binding.iaqualink + org.openhab.binding.icalendar org.openhab.binding.icloud org.openhab.binding.ihc org.openhab.binding.innogysmarthome @@ -174,6 +181,7 @@ org.openhab.binding.onkyo org.openhab.binding.opengarage org.openhab.binding.opensprinkler + org.openhab.binding.openthermgateway org.openhab.binding.openuv org.openhab.binding.openweathermap org.openhab.binding.orvibo @@ -212,6 +220,7 @@ org.openhab.binding.snmp org.openhab.binding.solaredge org.openhab.binding.solarlog + org.openhab.binding.somfymylink org.openhab.binding.somfytahoma org.openhab.binding.sonos org.openhab.binding.sonyaudio @@ -222,7 +231,7 @@ org.openhab.binding.systeminfo org.openhab.binding.tado org.openhab.binding.tankerkoenig - org.openhab.binding.telegram + org.openhab.binding.telegram org.openhab.binding.tellstick org.openhab.binding.tesla org.openhab.binding.tibber diff --git a/features/openhab-addons-external/pom.xml b/features/openhab-addons-external/pom.xml index bcf3d2d8cac3c..a24267f046a7d 100644 --- a/features/openhab-addons-external/pom.xml +++ b/features/openhab-addons-external/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.features.karaf org.openhab.addons.reactor.features.karaf - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT openhab-addons-external diff --git a/features/openhab-addons/pom.xml b/features/openhab-addons/pom.xml index 188e8947725de..e489705893a89 100644 --- a/features/openhab-addons/pom.xml +++ b/features/openhab-addons/pom.xml @@ -1,11 +1,13 @@ - + + 4.0.0 org.openhab.addons.features.karaf org.openhab.addons.reactor.features.karaf - 2.5.5-SNAPSHOT + 2.5.6-SNAPSHOT org.openhab.addons.features.karaf.openhab-addons @@ -45,13 +47,15 @@ + - +